ama*_*Bit 23

没有Android M以上的系统权限就可以.

if ((mPm.checkUidPermission(android.Manifest.permission.INSTALL_PACKAGES, installerUid)
        == PackageManager.PERMISSION_GRANTED)
        || (installerUid == Process.ROOT_UID)
        || mIsInstallerDeviceOwner) {
    mPermissionsAccepted = true;
} else {
    mPermissionsAccepted = false;
}
Run Code Online (Sandbox Code Playgroud)

设备所有者静默安装和卸载应用程序:

设备所有者现在可以使用PackageInstaller API以独立于Google Play for Work的方式静默安装和卸载应用程序.

更多链接.


这可以在Android 6.0及更高版本中使用.

  • 使您的应用成为设备所有者.

一旦您的应用获得了设备所有者权限,我们就可以无需任何用户干预即可静默安装,卸载和更新.

public static boolean installPackage(Context context, InputStream in, String packageName)
        throws IOException {
    PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
    PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
            PackageInstaller.SessionParams.MODE_FULL_INSTALL);
    params.setAppPackageName(packageName);
    // set params
    int sessionId = packageInstaller.createSession(params);
    PackageInstaller.Session session = packageInstaller.openSession(sessionId);
    OutputStream out = session.openWrite("COSU", 0, -1);
    byte[] buffer = new byte[65536];
    int c;
    while ((c = in.read(buffer)) != -1) {
        out.write(buffer, 0, c);
    }
    session.fsync(out);
    in.close();
    out.close();

    session.commit(createIntentSender(context, sessionId));
    return true;
}



private static IntentSender createIntentSender(Context context, int sessionId) {
        PendingIntent pendingIntent = PendingIntent.getBroadcast(
                context,
                sessionId,
                new Intent(ACTION_INSTALL_COMPLETE),
                0);
        return pendingIntent.getIntentSender();
    }
Run Code Online (Sandbox Code Playgroud)

卸载:

String appPackage = "com.your.app.package";
Intent intent = new Intent(getActivity(), getActivity().getClass());
PendingIntent sender = PendingIntent.getActivity(getActivity(), 0, intent, 0);
PackageInstaller mPackageInstaller = getActivity().getPackageManager().getPackageInstaller();
mPackageInstaller.uninstall(appPackage, sender.getIntentSender());
Run Code Online (Sandbox Code Playgroud)

Git repo在这里.

  • 非常感谢..但我无法安装apk..整个代码运行没有错误,但没有安装apk。是不是我的理解有误。静默安装 apk 需要 root 设备..? (2认同)
  • 无提示安装不需要设备根植.你的手机应该运行Android M及以上.您应该授予设备所有者权限.@sandeep请关注此... https://codelabs.developers.google.com/codelabs/cosu/#0 (2认同)
  • 请注意,ACTION_INSTALL_COMPLETE是您必须自己声明的变量.在repo:https://github.com/googlesamples/android-testdpc/blob/5b8297e9d51983a774ba3391e28a6aa35ca3f062/app/src/main/java/com/afwsamples/testdpc/cosu/CosuUtils.java中,它被定义为`public static final字符串ACTION_INSTALL_COMPLETE ="com.afwsamples.testdpc.INSTALL_COMPLETE";`. (2认同)

Flo*_*ont 6

您无法使用PackageInstaller.Session.commit()在新创建的用户中静默安装第三方应用程序,而无需特定的"权限".
你要么需要:

  • INSTALL_PACKAGES许可.但是此权限不适用于第三方应用程序.因此,即使使用您的个人资料所有者应用,您也不会拥有此特定权限.
  • 运行该过程为ROOT_UID.这意味着您必须根设备.

来自Android源代码:

if ((mPm.checkUidPermission(android.Manifest.permission.INSTALL_PACKAGES, installerUid) == PackageManager.PERMISSION_GRANTED) 
   || (installerUid == Process.ROOT_UID)) {
    mPermissionsAccepted = true;
} else {
    mPermissionsAccepted = false;
}
Run Code Online (Sandbox Code Playgroud)

如果您既没有root访问INSTALL_PACKAGES权限也没有权限,则会提示用户询问他是否确认了权限.然后,该确认在提交使用process的的PackageInstaller's会议.显然,在这种情况下,这不是透明的,因为用户必须手动确认您的应用程序的安装.


dev*_*evz 6

@amalBit 提供的安装方法对我不起作用。这很奇怪,因为这就是它在Google Sample 中的实现方式

这个 答案帮助我找到了解决方案。我不得不更改代码的某些部分。这是我的实现:

public static void installPackage(Context context, InputStream inputStream)
        throws IOException {
    PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
    int sessionId = packageInstaller.createSession(new PackageInstaller
            .SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL));
    PackageInstaller.Session session = packageInstaller.openSession(sessionId);

    long sizeBytes = 0;

    OutputStream out = null;
    out = session.openWrite("my_app_session", 0, sizeBytes);

    int total = 0;
    byte[] buffer = new byte[65536];
    int c;
    while ((c = inputStream.read(buffer)) != -1) {
        total += c;
        out.write(buffer, 0, c);
    }
    session.fsync(out);
    inputStream.close();
    out.close();

    // fake intent
    IntentSender statusReceiver = null;
    Intent intent = new Intent(context, SomeActivity.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
            1337111117, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    session.commit(pendingIntent.getIntentSender());
    session.close();
}
Run Code Online (Sandbox Code Playgroud)

这个方法可以这样调用:

        InputStream inputStream = getActivity().getAssets().open("my_awesome_app.apk");
        InstallationHelper.installPackage(getActivity(), inputStream);
Run Code Online (Sandbox Code Playgroud)


Vib*_*pra -3

安装:

Intent promptInstall = new Intent(Intent.ACTION_VIEW);
        promptInstall.setDataAndType(Uri.fromFile(new File(Environment
                .getExternalStorageDirectory() + "/download/" + APK_NAME)),
                "application/vnd.android.package-archive");
        promptInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(promptInstall);
Run Code Online (Sandbox Code Playgroud)

卸载:

Intent intent = new Intent(Intent.ACTION_DELETE, Uri.fromParts("package",
getPackageManager().getPackageArchiveInfo(apkUri.getPath(), 0).packageName,null));
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)