【问题标题】:AOSP - install packages in background without user confirmationAOSP - 在后台安装软件包而无需用户确认
【发布时间】:2018-06-14 00:52:28
【问题描述】:

我正在为 Android 8.1 版构建 AOSP,我想实现自己的应用商店,因此需要在系统上安装 apk。

到目前为止,我看到的唯一方法是使用类似以下的方法:

val intent = Intent(Intent.ACTION_VIEW)
val file = File(Environment.getExternalStorageDirectory().toString() + "/APKs/" + "spotify.apk")
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)

但是,这需要用户在安装每个软件包之前进行确认。如果应用程序是内置在图像中的系统应用程序,是否还有其他方法可以在没有用户确认的情况下实现此目的?另外,安装在后台有效地做什么?只是将 APK 文件移动到 /data/app 还是会发生什么?

【问题讨论】:

标签: android apk android-source


【解决方案1】:

看看runInstall()方法

https://android.googlesource.com/platform/frameworks/base/+/master/cmds/pm/src/com/android/commands/pm/Pm.java

所需权限:

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

【讨论】:

  • 我去看看 hit,谢谢。另一个问题是,是否还有一种方法可以自动填充已安装应用程序的登录字段?我想自动登录它们(我在系统上有凭据)。我目前正在通过 AccessibilityService 进行此操作,但这似乎很麻烦。
【解决方案2】:

我是这样解决的:

先决条件:

如前所述,您的 APK 需要由系统签名。实现这一目标的一种方法是自己构建 AOSP 映像并将源代码添加到构建中。

代码:

作为系统应用安装后,您可以使用包管理器方法安装和卸载 APK,如下所示:

安装:

public boolean install(final String apkPath, final Context context) {
    Log.d(TAG, "Installing apk at " + apkPath);
    try {
        final Uri apkUri = Uri.fromFile(new File(apkPath));
        final String installerPackageName = "MyInstaller";
        context.getPackageManager().installPackage(apkUri, installObserver, PackageManager.INSTALL_REPLACE_EXISTING, installerPackageName);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

卸载:

public boolean uninstall(final String packageName, final Context context) {
    Log.d(TAG, "Uninstalling package " + packageName);
    try {
        context.getPackageManager().deletePackage(packageName, deleteObserver, PackageManager.DELETE_ALL_USERS);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

要在您的 APK 安装/卸载后进行回调,您可以使用这个:

/**
 * Callback after a package was installed be it success or failure.
 */
private class InstallObserver implements IPackageInstallObserver {

    @Override
    public void packageInstalled(String packageName, int returnCode) throws RemoteException {

        if (packageName != null) {
            Log.d(TAG, "Successfully installed package " + packageName);
            callback.onAppInstalled(true, packageName);
        } else {
            Log.e(TAG, "Failed to install package.");
            callback.onAppInstalled(false, null);
        }
    }

    @Override
    public IBinder asBinder() {
        return null;
    }
}

/**
 * Callback after a package was deleted be it success or failure.
 */
private class DeleteObserver implements IPackageDeleteObserver {

    @Override
    public void packageDeleted(String packageName, int returnCode) throws RemoteException {
        if (packageName != null) {
            Log.d(TAG, "Successfully uninstalled package " + packageName);
            callback.onAppUninstalled(true, packageName);
        } else {
            Log.e(TAG, "Failed to uninstall package.");
            callback.onAppUninstalled(false, null);
        }
    }

    @Override
    public IBinder asBinder() {
        return null;
    }
}

/**
 * Callback to give the flow back to the calling class.
 */
public interface InstallerCallback {
    void onAppInstalled(final boolean success, final String packageName);
    void onAppUninstalled(final boolean success, final String packageName);
}

【讨论】:

  • 这是否意味着这个版本会导致未经认证的谷歌设备?因为我们正在更改构建代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-28
  • 2013-11-19
  • 2017-11-02
  • 2020-05-15
  • 2020-09-26
相关资源
最近更新 更多