Android 7:使用Runtime.getRuntime()。exec安装APK上的NullPointerException

Jon*_*sky 5 java android runtime.exec packageinstaller

我正在尝试使用常规Runtime.getRuntime.exec()例程在Android 7(三星和索尼)中安装APK 。安装失败,但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
Run Code Online (Sandbox Code Playgroud)

我尝试实现这一点:

Process proc = Runtime.getRuntime().exec("pm install /sdcard/imo.apk");
Run Code Online (Sandbox Code Playgroud)

所以:

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

但是在两种情况下都会发生异常。

在少于7个的android系统中可以使用。

权限是:

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
Run Code Online (Sandbox Code Playgroud)

通过外壳安装确实成功。提前致谢

Yor*_*ang 5

我找到了答案。虽然我不确定确切的原因是什么,但这是有效的。我参考了这个博客https://shoewann0402.github.io/2017/06/27/android-n-installSilent-and-uninstallSilent/,但是都是中文的。如果您也懂中文或使用谷歌翻译。

新命令应该是这样的:

pm install -i <you installer package name> --user 0 /sdcard/com.ifeng.news2.apk
Run Code Online (Sandbox Code Playgroud)

这是 Google 添加的一些新安全机制,它要求您使用 userId 0 进行安装。您还需要指定安装程序包名称。

然后在安装程序应用的清单文件中,添加android.permission.INTERACT_ACROSS_USERS_FULL此权限。那么它应该工作。我看到有一些关于 userId 的文档,但没有足够的时间深入研究它。有兴趣的可以自行搜索。


Pav*_*kov 5

我有同样的问题,但我用不同的方式解决了它。我的应用程序是一个启动器,它具有系统权限。这是我的解决方案。

添加到清单头android:sharedUserId="android.uid.system"

将此权限添加到 mainifest android:name="android.permission.INSTALL_PACKAGES"

将此代码添加到某个后台线程

    尝试 {
        String cmd = "pm install -r -i " + LAUNCHER_PACKAGE_ID + " " + activity.getFileStreamPath(apkPath);
        进程 p = Runtime.getRuntime().exec(cmd);
        p.waitFor();
    } 
    捕获(异常 e){
        Log.d(TAG, "SilentInstallActivity 错误:" + e);
    }

使用系统密钥对您的 android 应用程序进行签名。