如何在 Android Oreo 中管理来自未知来源的安装?

How to manage installation from Unknown Sources in Android Oreo?

在 Android Oreo (8.0) 中,对如何允许安装来自未知来源的应用程序(从用户的角度)以及获取安装它们的权限的过程进行了一些更改(从开发者的角度来看)。

因为我发现在开发者这边特别难找到所有必要的步骤,所以我觉得在这里问解决方案并自己回答问题很有用,现在我找到了答案,以备将来参考给那些面临同样障碍的人。

答案将包括以下问题:

  1. 如何检查是否允许我请求软件包安装?
  2. 我必须请求什么确切的权限?
  3. 如何提示用户授予此权限?
  4. 如何提示用户安装指定的 .apk?

(如果我在这里仍然遗漏任何内容,我将不胜感激指出这一点的任何其他答案或评论。)

首先,您的申请需要在 build.gradle 或 AndroidManifest.xml 让所有这些都起作用。

接着回答上面的问题:

  1. How to check whether I'm allowed to request a package install?

您可以在您的 Activity 代码中的任何位置使用 getPackageManager().canRequestPackageInstalls() 进行检查。请注意,如果您未声明适当的权限或针对错误的 SDK 版本,此方法始终 returns false

  1. What exact permission do I have to request?

您必须在 AndroidManifest.xml 中声明 Manifest.permission.REQUEST_INSTALL_PACKAGES,如下所示:

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
  1. How can I prompt the user to grant this permission?

您可以使用 Intent ACTION_MANAGE_UNKNOWN_APP_SOURCES:

将用户发送到适当的目的地
startActivity(new Intent(android.provider.Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES));

您还可以将用户更直接地转到您的应用程序的特定设置,方法是:

startActivity(new Intent(android.provider.Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:your.application.package")));
  1. How do I prompt the user to install a specified .apk?

一旦您确定您被授予适当的权限,您可以提示用户在您的 Activity 代码中的任何位置安装您的 .apk 文件(其中 this 指的是您的 Activity 的 Context), 使用:

Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setDataAndType(FileProvider.getUriForFile(this, "your.application.package.fileprovider", new File("/path/to/your/apk")), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

startActivity(intent);

如果您想知道安装是成功、取消还是失败,您也可以添加intent.putExtra(Intent.EXTRA_RETURN_RESULT, true)并以startActivityForResult(Intent, int)开头。

有关如何正确获取 .apk 文件的 URI 的信息,请参阅 FileProvider

在 adb shell 中,您可以使用 appops 管理应用的特定权限。 示例:

# To get a list of packagenames that is allowed to install from other sources
appops query-op REQUEST_INSTALL_PACKAGES allow 

# To allow an app install packages from other sources
appops set <package name> REQUEST_INSTALL_PACKAGES deny 

当 运行 adb shell appops help:

时打印的帮助文本
AppOps service (appops) commands:
  help
    Print this help text.
  set [--user <USER_ID>] <PACKAGE | UID> <OP> <MODE>
    Set the mode for a particular application and operation.
  get [--user <USER_ID>] <PACKAGE | UID> [<OP>]
    Return the mode for a particular application and optional operation.
  query-op [--user <USER_ID>] <OP> [<MODE>]
    Print all packages that currently have the given op in the given mode.
  reset [--user <USER_ID>] [<PACKAGE>]
    Reset the given application or all applications to default modes.
  write-settings
    Immediately write pending changes to storage.
  read-settings
    Read the last written settings, replacing current state in RAM.
  options:
    <PACKAGE> an Android package name.
    <OP>      an AppOps operation.
    <MODE>    one of allow, ignore, deny, or default
    <USER_ID> the user id under which the package is installed. If --user is not
              specified, the current user is assumed.