SecurityException:权限拒绝:通过显式意图启动 Activity 时

SecurityException: Permission Denial: While launching Activity via explicit intent

我正在阅读 declaring permissions in activity .根据文档

You can use the manifest's tag to control which apps can start a particular activity. A parent activity cannot launch a child activity unless both activities have the same permissions in their manifest. If you declare a element for a particular activity, the calling activity must have a matching element.

为了尝试这个,我创建了 2 个示例应用程序。第一个应用程序将尝试使用 显式意图 直接启动第二个应用程序的 activity, 此外,第二个应用程序将为我从第一个应用程序启动的特定 activity 声明权限。

这些是我遵循的步骤

  1. 创建了 2 个应用程序(比如发送方和接收方)
  2. 在发件人
  3. Manifest中添加权限<uses-permission android:name="permission.SHARE_POST"/>
  4. 现在,通过单击发件人应用程序的按钮,我正在调用名为 ShareActivity 的收件人 Activity,如下所示

        Intent intent = new Intent();
        intent.setComponent(new ComponentName("basics.android.com.androidbasics","basics.android.com.androidbasics.ShareActivity"));
        startActivity(intent);
    

    注意:basics.android.com.androidbasics为接收方包名

  5. 下面给出的是第二个应用程序(接收方)清单中的 activity 声明

           <activity
            android:name=".ShareActivity"
            android:exported="true"
            android:permission="permission.SHARE_POST"/>
    

现在,当我 运行 这两个应用程序并尝试从发件人启动 ShareActivity 时,我收到以下错误

Caused by: java.lang.SecurityException: Permission Denial: starting Intent { cmp=basics.android.com.androidbasics/.ShareActivity } from ProcessRecord{e09a1fc 26267:sender.android.com.sender/u0a925} (pid=26267, uid=10925) requires permission.SHARE_POST

发件人似乎还没有权限 permission.SHARE_POST。但是我已经在发件人的清单中声明了。 这里发生了什么事?

使用自定义权限在 Android 中是一项相当高级的事情。基本配方是:

  1. 确定您想要的权限名称。它需要在设备上是唯一的。因此,permission.SHARE_POST 不是一个好的选择 — 添加一个与您的域名相关联的前缀或您正在使用的任何其他前缀作为应用程序 applicationId 值的基础。
  2. 在使用权限保护自己的应用程序中,声明一个 <permission> 元素,其中一个 android:name 属性包含步骤 #1 中的权限名称。可选地,给它一个 android:protectionLevel 属性(例如,signature,因此只有由相同签名密钥签名的应用程序才能协同工作)。
  3. 在使用权限保护自己的应用程序中,在组件上添加一个 android:permission 属性(例如,<activity>),其值为您在步骤 #1 中的权限名称。
  4. 在希望与第 3 步中的应用进行通信的应用中,添加 <uses-permission> 属性,其中 android:name 属性包含第 1 步中的权限名称。
  5. 在这两个应用中,将您的 minSdkVersion 设置为 21,因为旧版本的自定义权限存在安全问题。

如果防御者(第 2 步和第 3 步)总是在客户端(第 4 步)之前安装,这将有效。如果您希望应用程序可以按任一顺序安装,请将上面的步骤 #2 替换为:

  1. both apps中,声明一个<permission>元素,其中android:name属性保存权限名称从第 1 步开始。可选地,给它一个 android:protectionLevel 属性(例如,signature,因此只有由相同签名密钥签名的应用程序才能协同工作)。此外,请确保两个应用程序始终由相同的签名密钥签名,否则它们不能同时定义相同的权限。