【问题标题】:SecurityException: Permission Denial: While launching Activity via explicit intentSecurityException:权限拒绝:通过显式意图启动 Activity 时
【发布时间】:2026-02-21 08:30:02
【问题描述】:

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

您可以使用清单的标签来控制哪些应用可以启动特定活动。除非两个活动在其清单中具有相同的权限,否则父活动无法启动子活动。如果您为特定活动声明元素,则调用活动必须具有匹配的元素。

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

这些是我遵循的步骤

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

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

    注意:basics.android.com.androidbasics 是接收者的包名

  4. 下面给出的是第二个应用程序(接收者)清单中的活动声明

           <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 的权限。但是我已经在发件人的清单中声明了它。 这里发生了什么事?

【问题讨论】:

  • 两个应用程序是否都有定义permission.SHARE_POST&lt;permission&gt; 元素?
  • 没有。只有发件人 App 有&lt;uses-permission android:name="permission.SHARE_POST"/&gt;。两者都需要吗? Receiver 只在&lt;activity&gt; 标签中定义android:permission="permission.SHARE_POST"
  • 如果您希望它们可以按任意顺序安装,它们都需要该元素。否则,必须先安装带有&lt;permission&gt; 的应用程序。请注意,自定义权限在 Android 4.4 及更低版本上确实很糟糕,因此我强烈建议这些应用的 minSdkVersion 为 21 或更高。
  • 您可能混淆了&lt;permission&gt;&lt;uses-permission&gt; 吗?请注意,它们是不同的东西,您链接的页面似乎没有提到&lt;permission&gt;,这是实际定义自定义权限所必需的。你也可以看看this page
  • @MikeM。哦,是的!!,所以我混淆了&lt;permission&gt;&lt;uses-permission&gt;。现在,将接收器中的&lt;uses-permission android:name="permission.SHARE_POST"/&gt; 更改为&lt;permission android:name="permission.SHARE_POST" android:protectionLevel="normal" /&gt;。现在它开始工作了。但令人失望的是,Android 文档中没有适当的清晰度供初学者以正确的方式理解它。总之谢谢你。你节省了我很多时间!!`

标签: android android-intent android-activity android-permissions


【解决方案1】:

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

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

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

  1. 两个应用程序中,声明一个&lt;permission&gt; 元素,其中android:name 属性包含步骤#1 中的权限名称。或者,给它一个 android:protectionLevel 属性(例如,signature,因此只有由相同签名密钥签名的应用程序才能一起工作)。此外,请确保两个应用始终使用相同的签名密钥进行签名,否则它们无法定义相同的权限。

【讨论】:

  • 感谢您的详细解释。我希望这是官方 Android 文档中给出的解释!