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

2

6

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

Denudate answered 4/9, 2017 at 12:17 Comment(7)
Why not use ACTION_INSTALL_PACKAGE?Avicenna
DO NOT USE Runtime.getRuntime.exec(). Use a ProcessBuilder instead. At the very least, it will allow you to isolate your NPE.Vally
I am also facing same issue,please post answer if you got Thanks.Brewington
Hi Rishikesh pathak, The Null Pointer exception caused by the reason that started appearing from android 7. The PM user, that installs APK from inside your application (not from the regular shell) does not have permission to do it. It should be a bug, but I really don't know if google is about to fix it. In my project I left the problem as a caveat.Denudate
Thanks @JonahTornovsky for quick response,But i am trying to install app from shell script and getting same exception as yours.kindly check it for more detail: #47669312Brewington
Hi @Rishikeshpathak You install app by script that executed by the other app and not from the shell. It looks the same as to execute installation from your app. You can use android shell "id" command to see what user executes your installation, just put it in your script and run your app: id after you see what is user id, use shell to switch to it and try to execute your installation: $ YOUR_ROOT USER_ID $ pm install -r "/sdcard/Download/SampleApplication.apk"; and see the result. You'll probably get something like that: Error: java.lang.NullPointerExceptionDenudate
Wondering have you gotten the solution? same here. I just updated from M to N and then my code just stops working with this NullPointerException.County
C
5

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.

County answered 14/5, 2018 at 1:34 Comment(0)
C
5

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.

Cristinecristiona answered 23/6, 2018 at 23:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.