android 7: NullPointerException on APK installing with Runtime.getRuntime().exec

2.5k views Asked by At

I'm trying to install APK in android 7 (samsung and sony) using regular Runtime.getRuntime.exec() routine. The installation fails with the following exception in the logcat:

09-04 14:14:33.932 16623-16623/? D/AndroidRuntime: Calling main entry com.android.commands.pm.Pm
09-04 14:14:33.939 3695-3876/? D/PackageInstaller:  installation of android.content.pm.PackageInstaller$SessionParams@a4d2f0e for non-container user 0
09-04 14:14:33.940 16623-16623/? E/Pm: Error
                                       java.lang.NullPointerException
                                           at android.os.Parcel.readException(Parcel.java:1699)
                                           at android.os.Parcel.readException(Parcel.java:1646)
                                           at android.content.pm.IPackageInstaller$Stub$Proxy.createSession(IPackageInstaller.java:249)
                                           at com.android.commands.pm.Pm.doCreateSession(Pm.java:530)
                                           at com.android.commands.pm.Pm.runInstall(Pm.java:369)
                                           at com.android.commands.pm.Pm.run(Pm.java:142)
                                           at com.android.commands.pm.Pm.main(Pm.java:99)
                                           at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
                                           at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:301)
09-04 14:14:33.941 16623-16623/? I/art: System.exit called, status: 1
09-04 14:14:33.941 16623-16623/? I/AndroidRuntime: VM exiting with result code 1

I try to implement that so:

Process proc = Runtime.getRuntime().exec("pm install /sdcard/imo.apk");

and so:

Process proc = Runtime.getRuntime().exec(new String[]{"/system/bin/sh","-c","/system/bin/pm install /sdcard/imo.apk"});

But exception occurs in the both cases.

In androids less than 7 it works.

The permissions are:

declared permissions:
  android.permission.INTERACT_ACROSS_USERS_FULL: prot=normal
requested permissions:
  android.permission.BIND_NOTIFICATION_LISTENER_SERVICE
  android.permission.READ_EXTERNAL_STORAGE
  android.permission.WRITE_EXTERNAL_STORAGE
  android.permission.READ_LOGS
User 0: ceDataInode=393939 installed=true hidden=false suspended=false stopped=false notLaunched=false enabled=0
  gids=[1007]
  runtime permissions:
    android.permission.CLEAR_APP_USER_DATA: granted=true
    android.permission.INSTALL_PACKAGES: granted=true
    android.permission.READ_EXTERNAL_STORAGE: granted=true
    android.permission.INTERACT_ACROSS_USERS_FULL: granted=true
    android.permission.READ_LOGS: granted=true
    android.permission.CLEAR_APP_CACHE: granted=true
    android.permission.WRITE_EXTERNAL_STORAGE: granted=true

Installation does succeed thru the shell. Thanks in advance

2

There are 2 answers

0
Pavel Bobkov On

I had the same issue but I solved it by a different way. My app is a launcher and it has system privileges. It is my solution.

Add to manifest header android:sharedUserId="android.uid.system"

Add this permission to mainifest android:name="android.permission.INSTALL_PACKAGES"

Add this code to some background thread


    try {
        String cmd = "pm install -r -i " + LAUNCHER_PACKAGE_ID + " " + activity.getFileStreamPath(apkPath);
        Process p = Runtime.getRuntime().exec(cmd);
        p.waitFor();
    } 
    catch (Exception e) {
        Log.d(TAG, "SilentInstallActivity error: " + e);
    }

Sign your android application with system key.

0
York Yang On

I found the answer. Although I'm not sure what is the exact reason but this works. I referred to this blog https://shoewann0402.github.io/2017/06/27/android-n-installSilent-and-uninstallSilent/, but it's all Chinese. In case you also understand Chinese or you use Google translation.

The new command should be like this:

pm install -i <you installer package name> --user 0 /sdcard/com.ifeng.news2.apk

This is some new security mechanism added by Google and it requires you to install using userId 0. Also you need to specify the installer package name.

Then in your installer app's manifest file, add android.permission.INTERACT_ACROSS_USERS_FULL this permission. Then it should work. I saw there are some docs about the userId but just don't have enough time to dig into it. If you are interested, you can search by yourself.