Android does not require root to implement the APK silent installation

Source: Internet
Author: User

Reprint Please specify source: http://blog.csdn.net/yyh352091626/article/details/50533137

Android's silent installation seems like an interesting and tempting thing to do, but, in common practice, it seems difficult to implement a silent installation if the phone does not have root privileges, because Android does not provide a intent call to display, typically installing the APK in the following ways:

Intent Intent = new Intent (Intent.action_view); Intent.setdataandtype (uri.fromfile (file), "application/ Vnd.android.package-archive "); StartActivity (intent);
However, this does not really implement a silent installation, because there is a user interface that will let the user know. So, how to install the APK silently in the background? Can only try to see the Android system source code normal installation apk process, I download the source code is Android5.0 system, 5 g size, but may be due to Android5.0 some security updates, with the previous version or there is a certain gap, but, learn one after another similar process, it is much simpler, like learning C language, then learn Java, is not What a difficult thing ~

The Android system divides all permission (permissions) into four levels according to its potential risk, namely "normal", "dangerous", "signature", "Signatureorsystem". The permissions for the APK installation are install_packages, and the permission level belongs to the latter two. So, finally want to implement the APK silent installation, it is necessary to some special processing, the implementation of the installation of this process, must be a system process.

So, let's see how Android itself implements the APK installation. The command installed is PM install ... We locate the system source/frameworks/base/cmds/pm/src/com/android/commands/pm/ Pm.java This file, he implements the PM command, we look at the Runinstall method, which is the APK installation process.

    private void Runinstall () {int installflags = 0;        int userId = Userhandle.user_all;        String installerpackagename = null;        String opt;        String originatinguristring = null;        String referrer = null;        String abi = null; while ((Opt=nextoption ()) = null) {if (Opt.equals ("-L")) {installflags |= packagemanager.inst            All_forward_lock;            } else if (Opt.equals ("-R")) {installflags |= packagemanager.install_replace_existing;                } else if (Opt.equals ("-i")) {installerpackagename = Nextoptiondata ();                    if (Installerpackagename = = null) {System.err.println ("Error:no value specified for-i");                Return            }} else if (Opt.equals ("-T")) {installflags |= packagemanager.install_allow_test;    } else if (Opt.equals ("-S")) {//Override if-s option is specified.            Installflags |= packagemanager.install_external;                } else if (Opt.equals ("-F")) {//Override if-s option is specified.            Installflags |= packagemanager.install_internal;            } else if (Opt.equals ("-D")) {installflags |= packagemanager.install_allow_downgrade;                } else if (Opt.equals ("--originating-uri")) {originatinguristring = Nextoptiondata (); if (originatinguristring = = null) {SYSTEM.ERR.PRINTLN ("error:must supply argument for--originating-u                    Ri ");                Return                }} else if (Opt.equals ("--referrer")) {referrer = Nextoptiondata ();                    if (referrer = = null) {SYSTEM.ERR.PRINTLN ("error:must supply argument for--referrer");                Return   }} else if (Opt.equals ("--abi")) {abi = Checkabiargument (Nextoptiondata ());         } else if (Opt.equals ("--user")) {userId = Integer.parseint (Nextoptiondata ());                } else {System.err.println ("error:unknown option:" + opt);            Return            }} if (UserID = = userhandle.user_all) {userid = Userhandle.user_owner;        Installflags |= packagemanager.install_all_users;        } final Uri Verificationuri;        Final Uri Originatinguri;        Final Uri Referreruri;        if (originatinguristring! = null) {Originatinguri = Uri.parse (originatinguristring);        } else {originatinguri = null;        } if (referrer! = null) {Referreruri = Uri.parse (referrer);        } else {referreruri = null;        }//Populate Apkuri, must be present final String Apkfilepath = Nextarg ();        System.err.println ("\tpkg:" + Apkfilepath); if (Apkfilepath = = null) {System.err.println ("error:no package specified ");        Return        }//Populate Verificationuri, optionally present final String Verificationfilepath = Nextarg ();            if (Verificationfilepath! = null) {System.err.println ("\tver:" + Verificationfilepath);        Verificationuri = Uri.fromfile (new File (Verificationfilepath));        } else {verificationuri = null;        } localpackageinstallobserver Obs = new Localpackageinstallobserver (); try {verificationparams verificationparams = new Verificationparams (Verificationuri, origin            Atinguri, Referreruri, verificationparams.no_uid, NULL); Mpm.installpackageasuser (Apkfilepath, Obs.getbinder (), Installflags, Installerpackagename, verification Params, Abi, userId); Attention!!                        Finally, this method is called to install the synchronized (OBS) {while (!obs.finished) {try {                    Obs.wait (); } catch (Interruptedexception e)                    {}} if (Obs.result = = packagemanager.install_succeeded) {                System.out.println ("Success");                            } else {System.err.println ("Failure [" + installfailuretostring (OBS)                + "]");            }}} catch (RemoteException e) {System.err.println (e.tostring ());        System.err.println (Pm_not_running_err); }    }

Once you know the process, you probably know how to do it. Now that the bottom of the system is blocking the API, try to get around this layer of masking to use it. The first thought is the use of aidl, do not know aidl this thing, first ask Niang go ~ ~ In the above code, the final implementation of the installation of that sentence, Mpm.installpackageasuser (...), mPm what is a thing? Not hard to find, Ipackagemanager type, then where does this class come from? Search, located in the/frameworks/base/core/java/android/content/pm under this package, copy to our project directory, the package name can not change, only copy this file, must be not, will report some other aidl can not find, Accordingly also copies come over. Android5.0, aidl change or relatively large, so to copy a lot of things come over, but also to make some changes ... I also spent a long time to change to his no error.

Finally, the project directory is as follows ~ ~


So, how to use it?

1, first obtain the system service Android.os.ServiceManager, this is hidden again, how to do? The time to test the Java level is right, with the reflection mechanism, to obtain the ServiceManager class, and the method inside the class;

2, with the service, we will go to get ipackagemanager this object;

3, call Ipackagemanager inside the InstallPackage method to install;

The implementation code is as follows:

Package Com.example.autoinstall;import Java.io.file;import Java.io.fileoutputstream;import java.io.IOException; Import Java.io.inputstream;import java.io.outputstream;import Java.lang.reflect.method;import android.app.Activity ; Import Android.content.intent;import Android.content.pm.ipackageinstallobserver2;import Android.content.pm.ipackagemanager;import Android.content.pm.verificationparams;import Android.net.Uri;import Android.os.bundle;import Android.os.ibinder;import Android.os.remoteexception;import Android.view.View;public Class Mainactivity extends Activity {@Overrideprotected void onCreate (Bundle savedinstancestate) {super.oncreate ( Savedinstancestate); Setcontentview (R.layout.activity_main);}        /** * button Click event * @param view */public void Install (view view) {String path = "";        if (Fileutils.issdcardready ()) {path = Fileutils.getsdcardpath ();        } else {path = Fileutils.getcachepath (this); }string fileName = path + "/aidlserverdemo.apk"; File fiLe = new File (filename); try {if (!file.exists ()) COPYAPK2SD (filename);                        Uri uri = uri.fromfile (new File); Obtain android.os.servicemanagerclass<?> Clazz = Class.forName ("Android.os.ServiceManager") through the Java reflection mechanism; method = Clazz.getmethod ("GetService", String.class), IBinder IBinder = (ibinder) method.invoke (NULL, "package") ; Ipackagemanager IPM = IPackageManager.Stub.asInterface (IBinder); @SuppressWarnings ("deprecation")                        Verificationparams verificationparams = new Verificationparams (null, NULL, NULL, VERIFICATIONPARAMS.NO_UID, NULL); Execution of installation (methods and detailed parameters may vary by system) Ipm.installpackage (FileName, New Packageinstallobserver (), 2, NULL, Verificatio Nparams, "");} catch (Exception e) {//TODO auto-generated catch Blocke.printstacktrace ();}} Used to display the result class Packageinstallobserver extends Ipackageinstallobserver2.stub {@Overridepublic void Onuseractionrequired (Intent Intent) throws RemoteException {//TODO auto-generated method stub} @Overridepublicvoid onpackageinstalled (string basepackagename, int returncode, string msg, Bundle extras) throws RemoteException {//retu Rncode<span style= "font-family:arial, Helvetica, Sans-serif;" > 1, is the installation successful </span>}};/** * Copy assets folder APK plugin to SD * * @param stroutfilename * @throws ioexception */private void Co PYAPK2SD (String stroutfilename) throws IOException {Fileutils.createdippath (stroutfilename); InputStream myInput = This.getassets (). Open ("aidlserverdemo.apk"), outputstream myoutput = new FileOutputStream (stroutfilename); byte[] Buffer = new Byte[1024];int length = myinput.read (buffer), while (length > 0) {myoutput.write (buffer, 0, length); length = Myinput.read (buffer);} Myoutput.flush (); Myinput.close (); Myoutput.close ();}}

Each version of the system source code inside the aidl may be different, so the specific method and parameters to call, but also according to the actual situation, you need to carefully read the source of Pm.java this file.

In other versions, you may only need to copy these 4 files: Packagemanager.java, Ipackagedeleteobserver.aidl, Ipackagerinstallobserver.aidl, Ipackagemoveobserver.aidl

Then, you need to add Install_package permissions in the config manifest file.

<uses-permission android:name= "Android.permission.INSTALL_PACKAGES"/>

Then set the UID of the app to system level and add the following properties under the Manifest tab

Android:shareduserid= "Android.uid.system"

In this case, silent installation is not possible because the system does not consider your app to be a system-level application, so you should also sign the app's APK (note: Not the silent install APK, which is the one that implements the silent installer). The signing process is as follows:

A total of three files are required:

1, Signapk.jar% system source%/out/host/linux-x86/framework/signapk.jar

2, Platform.x509.pem% system source%/build/target/product/security/platform.x509.pem

3, Platform.pk8% system source%/build/target/product/security/platform.pk8

Open terminal, execute command java-jar signapk.jar platform.x509.pem platform.pk8 unsigned apk after signing apk, for example

Java-jar Signapk.jar Platform.x509.pem  platform.pk8 autoinstall.apk autoinstall_new.apk

After that, the signature apk installed on the phone, open, click on silent installation, go to the program page to see, found the installation success ~ ~



The test found a problem, that is, the method of generating the APK can only be used in the Android native system or in their own compiled system, because such a system can get platform.pk8 and Platform.x509.pem these two files. For example, on the Huawei or Xiaomi system, it cannot be installed. Use the original Android key to sign, the program runs OK on the emulator (may restart), but put on the G3 phone to install the direct prompt "package ... has no signatures that match those in the shared use R Android.uid.system ", third-party ROM this is also in the protection system security angle to consider.

This article is mainly to provide a way to implement the silent installation, but how to do compatible with each system, extrapolate, but also need you crossing to read the Android system source code.

In addition, because of the wall, many people can not download the system source code, here again by the way attached Android5.0 system source of cloud Disk Address: Link: Http://pan.baidu.com/s/1dElkPlZ Password: 4pue


Finally, attached demo: Android No root implementation apk silent installation source

Android does not require root to implement the APK silent installation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.