【问题标题】:Install APK as system app with INSTALL_PACKAGES [duplicate]使用 INSTALL_PACKAGES 将 APK 安装为系统应用 [重复]
【发布时间】:2018-05-30 23:29:36
【问题描述】:

我开发了一个以系统权限运行的应用程序(它内置于 AOSP 的映像中)并具有 INSTALL_PACKAGES 权限。

我的目标是在后台静默安装 APK,无需用户交互。我在 stackoverflow 上阅读了不同的方法,但其中大多数要么已经过时,要么根本不起作用。

例如,如果我尝试使用 PackageManager(通过反射或通过在我的应用程序中作为 shell 命令运行)我会收到以下错误,这就是我目前遇到的问题。

11-20 19:06:10.999  4965  4965 D AndroidRuntime: >>>>>> START 

com.android.internal.os.RuntimeInit uid 10039 <<<<<<
11-20 19:06:11.199  4965  4965 D AndroidRuntime: Calling main entry com.android.commands.pm.Pm
11-20 19:06:11.268  4965  4965 E Pm      : Error
11-20 19:06:11.268  4965  4965 E Pm      : java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.AppOpsManager.checkPackage(int, java.lang.String)' on a null object reference
11-20 19:06:11.268  4965  4965 E Pm      :  at android.os.Parcel.readException(Parcel.java:2010)
11-20 19:06:11.268  4965  4965 E Pm      :  at android.os.Parcel.readException(Parcel.java:1950)
11-20 19:06:11.268  4965  4965 E Pm      :  at android.content.pm.IPackageInstaller$Stub$Proxy.createSession(IPackageInstaller.java:254)
11-20 19:06:11.268  4965  4965 E Pm      :  at com.android.commands.pm.Pm.doCreateSession(Pm.java:607)
11-20 19:06:11.268  4965  4965 E Pm      :  at com.android.commands.pm.Pm.runInstall(Pm.java:431)
11-20 19:06:11.268  4965  4965 E Pm      :  at com.android.commands.pm.Pm.run(Pm.java:150)
11-20 19:06:11.268  4965  4965 E Pm      :  at com.android.commands.pm.Pm.main(Pm.java:107)
11-20 19:06:11.268  4965  4965 E Pm      :  at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
11-20 19:06:11.268  4965  4965 E Pm      :  at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:285)
11-20 19:06:11.270  4965  4965 I app_process: System.exit called, status: 1
11-20 19:06:11.270  4965  4965 I AndroidRuntime: VM exiting with result code 1.

谁能告诉我为什么会发生此错误,或者其他解决方案或使用 INSTALL_PACKAGES 静默安装 APKS 的“现代”方式?

任何帮助表示赞赏。

编辑:

对于将其标记为 nullpointer 异常重复的人 - 您如何建立重复的连接?我专门询问其背后的原因,而不是关于 nullpointer 异常本身。您的重复建议完全没有意义

编辑 2:

我尝试安装 APK 的代码(从 AOSP 源的包安装程序应用复制):

public boolean install(Context context) {

    Log.d(TAG, "Start Installation");

    String packageName = "com.spotify.music";
    String apkPath = Environment.getExternalStorageDirectory().toString() + "/APKs/spotify.apk";

    PackageInstaller.Session session;
    int sessionId;
    PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
    params.setAppPackageName(packageName);

    try {
        sessionId = context.getPackageManager().getPackageInstaller().createSession(params);
        session = context.getPackageManager().getPackageInstaller().openSession(sessionId);
    } catch (IOException e) {
        Log.w(TAG, "Error creating/opening the installing session", e);
        return false;
    }

    try {
        File file = new File(apkPath);

        try (InputStream in = new FileInputStream(file)) {
            long sizeBytes = file.length();
            try (OutputStream out = session.openWrite("PackageInstaller", 0, sizeBytes)) {
                byte[] buffer = new byte[1024 * 1024];
                while (true) {

                    int numRead = in.read(buffer);

                    if (numRead == -1) {
                        session.fsync(out);
                        break;
                    }

                    out.write(buffer, 0, numRead);
                    if (sizeBytes > 0) {
                        float fraction = ((float) numRead / (float) sizeBytes);
                        Log.d(TAG, "Install progress: " + fraction);
                    }
                }
            }
        }

        Log.d(TAG, "Install finished");
        session.commit(PendingIntent.getBroadcast(context, sessionId, new Intent("android.intent.action.MAIN"), 0).getIntentSender());

        return true;
    } catch (IOException | SecurityException e) {
        Log.e(TAG, "Could not write package", e);

        session.close();

        return false;
    }
}

【问题讨论】:

  • 你能分享你用来启动安装的代码吗?
  • @satur9nine 我在 AOSP 源代码中使用了与包安装程序应用程序相同的代码,意思是获取一个 PackageInstaller 对象并打开一个会话

标签: android android-source android-package-managers android-install-apk


【解决方案1】:

我们使用以下代码:

Uri apkUri = Uri.fromFile(apkFile);
IPackageInstallObserver observer = null;
String installerPackageName = "MyInstaller";
getPackageManager().installPackage(apkUri, observer, PackageManager.INSTALL_REPLACE_EXISTING, installerPackageName);

它已被弃用,但即使在 Android 8.1 上仍然有效。

【讨论】:

  • 会试用并回复您 - 谢谢!
  • 我是否必须遵循特定的 gradle 设置才能执行此操作?我的 Android Studio 没有解析 installPackage() 方法
  • 如果您正在构建一个具有系统权限的 Android 应用程序以与系统映像捆绑,它必须使用平台密钥进行签名,并且几乎可以肯定通过 Android.mk make 与 Android 平台的其余部分一起构建文件而不是 gradle。这使您可以访问@hide 方法。在平台构建系统之外访问@hide 方法很困难(但并非不可能)。
猜你喜欢
  • 1970-01-01
  • 2014-07-17
  • 1970-01-01
  • 2011-08-13
  • 1970-01-01
  • 2015-02-28
  • 1970-01-01
  • 2017-05-24
  • 2020-06-19
相关资源
最近更新 更多