Android: java.lang.SecurityException: 权限拒绝:启动Intent

114

我创建了一个应用程序,其中包含GWVectraNotifier活动,其他应用程序可以调用该活动以显示通知。

在通知对话框中,将有“显示”按钮和“关闭”按钮。

单击“显示”按钮,将启动相应的活动。

为了检查上述应用程序的功能,

我从K9Mail应用程序启动了GWVectraNotifier活动,在检查邮件事件触发时。

我能够成功启动GWVectraNotifier活动,但是在单击“显示”按钮后,我需要启动K9mail的“MessageList”活动。 为此,我编写了以下代码:

Intent i = new Intent();
i.setComponent(new ComponentName("com.fsck.k9", "com.fsck.k9.activity.MessageList"));
i.putExtra("account", accUuid);
i.putExtra("folder", accFolder);
startActivity(i); 

会抛出以下异常:

WARN/ActivityManager(59): Permission denied: checkComponentPermission() reqUid=10050
WARN/ActivityManager(59): Permission Denial: starting Intent { cmp=com.fsck.k9/.activity.MessageList (has extras) } from ProcessRecord{43f6d7c8 675:com.i10n.notifier/10052} (pid=675, uid=10052) requires null
WARN/System.err(675): java.lang.SecurityException: Permission Denial: starting Intent { cmp=com.fsck.k9/.activity.MessageList (has extras) } from ProcessRecord{43f6d7c8 675:com.i10n.notifier/10052} (pid=675, uid=10052) requires null
WARN/System.err(675):     at android.os.Parcel.readException(Parcel.java:1247)
WARN/System.err(675):     at android.os.Parcel.readException(Parcel.java:1235)
WARN/System.err(675):     at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:1298)
WARN/System.err(675):     at android.app.Instrumentation.execStartActivity(Instrumentation.java:1373)
WARN/System.err(675):     at android.app.Activity.startActivityForResult(Activity.java:2817)
WARN/System.err(675):     at android.app.Activity.startActivity(Activity.java:2923)
WARN/System.err(675):     at com.i10n.notifier.GWVectraNotifier$2$1.run(GWVectraNotifier.java:63)
WARN/System.err(675):     at android.app.Activity.runOnUiThread(Activity.java:3707)
WARN/System.err(675):     at com.i10n.notifier.GWVectraNotifier$2.onClick(GWVectraNotifier.java:53)
WARN/System.err(675):     at android.view.View.performClick(View.java:2408)
WARN/System.err(675):     at android.view.View$PerformClick.run(View.java:8816)
WARN/System.err(675):     at android.os.Handler.handleCallback(Handler.java:587)
WARN/System.err(675):     at android.os.Handler.dispatchMessage(Handler.java:92)
WARN/System.err(675):     at android.os.Looper.loop(Looper.java:123)
WARN/System.err(675):     at android.app.ActivityThread.main(ActivityThread.java:4627)
WARN/System.err(675):     at java.lang.reflect.Method.invokeNative(Native Method)
WARN/System.err(675):     at java.lang.reflect.Method.invoke(Method.java:521)
WARN/System.err(675):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
WARN/System.err(675):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
WARN/System.err(675):     at dalvik.system.NativeStart.main(Native Method)

实际上,我不明白在我的Notifier应用程序的清单文件中包括哪些权限才能访问k9Mail的MessageList。下面是k9mail应用程序清单文件中包含的权限:

<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.READ_OWNER_DATA"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="org.thialfihar.android.apg.permission.READ_KEY_DETAILS"/>
<permission android:name="com.fsck.k9.permission.READ_ATTACHMENT"
            android:permissionGroup="android.permission-group.MESSAGES"
            android:protectionLevel="dangerous"
            android:label="@string/read_attachment_label"
            android:description="@string/read_attachment_desc"/>
<uses-permission android:name="com.fsck.k9.permission.READ_ATTACHMENT"/>
<permission android:name="com.fsck.k9.permission.REMOTE_CONTROL"
             android:permissionGroup="android.permission-group.MESSAGES"
             android:protectionLevel="dangerous"
             android:label="@string/remote_control_label"
             android:description="@string/remote_control_desc"/>
<uses-permission android:name="com.fsck.k9.permission.REMOTE_CONTROL"/>
<permission android:name="com.fsck.k9.permission.READ_MESSAGES"
            android:permissionGroup="android.permission-group.MESSAGES"
            android:protectionLevel="normal"
            android:label="@string/read_messages_label"
            android:description="@string/read_messages_desc"/>
<uses-permission android:name="com.fsck.k9.permission.READ_MESSAGES"/>
<permission android:name="com.fsck.k9.permission.DELETE_MESSAGES"
            android:permissionGroup="android.permission-group.MESSAGES"
            android:protectionLevel="normal"
            android:label="@string/delete_messages_label"
            android:description="@string/read_messages_desc"/>
<uses-permission android:name="com.fsck.k9.permission.DELETE_MESSAGES"/>           

请问我应该在我的应用中包含哪些权限?在上面列出的权限中,有一些是只针对 k9mail 的,因为它们是为 k9 编写的权限类。因此,我只能在给定的权限中包含 Android 内置的权限。我也尝试过这样做,但它并没有解决我的问题 :(


我通过在AndroidManifest.xml文件中的MessageList Activity标签下添加以下意图过滤器来解决这个问题: <intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter> - Swathi EP
我已经添加了<intent-filter><action android:name="android.intent.action.MAIN" /></intent-filter>和android:exported="true",但是仍然出现java.lang.security异常?请问你可以帮我解决这个问题吗? - Charan Pai
9个回答

157
你需要在尝试启动的活动中的清单文件中添加android:exported="true"
android:exported文档中可以看到:
android:exported表示该活动是否可以由其他应用程序的组件启动 - 如果可以,则为“true”,如果不能,则为“false”。如果为“false”,则只能通过相同应用程序或具有相同用户ID的应用程序的组件来启动该活动。
默认值取决于活动是否包含意图过滤器。没有任何过滤器意味着只能通过指定其确切类名来调用该活动。这意味着该活动仅适用于应用程序内部使用(因为其他人不会知道类名)。因此,在这种情况下,默认值为“false”。另一方面,至少有一个过滤器存在意味着该活动适用于外部使用,因此默认值为“true”。
此属性不是限制活动对其他应用程序公开方式的唯一方法。您还可以使用权限来限制可以调用该活动的外部实体(请参阅permission属性)。

3
如果你先安装带有导出服务的应用程序,然后再安装主应用程序,你将无法成功地卸载服务...但相反的方式确实有效。这是因为在安装主应用程序时缺少必要的权限,但我不知道如何在不删除权限的情况下解决它...请为我解决问题的一半。 - Bibu
显然,首先必须安装托管服务的应用程序。否则客户端将无法工作。谢谢 @Bibu 我们为此问题奋斗了几天。 - odifek

102

你看到的 java.lang.SecurityException 是因为可能输入了指向同一活动的两个条目。删除第二个条目,问题就会解决。

更多解释

您可能已经在清单中声明了该活动两次,并且具有不同的属性,例如:

 <activity android:name=".myclass"> </activity>
并且
 <activity android:name=".myclass" android:label="@string/app_name"> 
     <intent-filter> 
         <action android:name="android.intent.action.MAIN" />
         <category android:name="android.intent.category.LAUNCHER" />
     </intent-filter>
 </activity>

您应该从清单中删除不需要的内容


2
您可能已经在清单文件中声明了两次活动,且其属性不同,例如: <activity android:name=".myclass"></activity> 和 <activity android:name=".myclass" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> ,您应从清单文件中删除不需要的那个。 - Jomia
1
很棒的答案,jomia。但是我有一个问题,在同一时间内我只有一个启动器活动。相同的代码在模拟器上运行良好,但在设备上显示安全异常。能否请您详细说明一下。 - Tofeeq Ahmad
我认为你需要在设备上卸载该应用并重新安装它。然后它就会正常工作。 - Jomia

16

在 Manifest 文件中,在 </application> 之前添加以下内容

<activity android:name="com.fsck.k9.activity.MessageList">
   <intent-filter>
      <action android:name="android.intent.action.MAIN">
      </action>
   </intent-filter>
</activity>

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.i10n.notifier" android:versionCode="1" android:versionName="1.0"> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/> <uses-permission android:name="android.permission.READ_OWNER_DATA"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> - Swathi EP
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> - Swathi EP
在上面的三个评论中,我已经粘贴了我的Notifier应用程序清单文件。谢谢你的回复。 - Swathi EP
你还没有粘贴这行代码:<activity android:name="com.fsck.k9.activity.MessageList"/> - Muhammad Shahab
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.fsck.k9.activity.MessageList"/> </application> </manifest> . 请将第三行替换为这个,检查并告诉我。 - Muhammad Shahab
显示剩余8条评论

8

其他答案都是关于如何声明接收应用程序活动的,但这个答案直接说明了如何调用隐式意图。谢谢! - shaheer_

6
我遇到了同样的问题,并希望避免像你所描述的那样添加意图过滤器。经过一番搜索,我发现一个xml属性android:exported,您应该将其添加到要调用的活动中。
如果您的活动没有添加任何意图过滤器,则默认设置为false,但是如果您确实有意图过滤器,则会将其设置为true。
这是文档 http://developer.android.com/guide/topics/manifest/activity-element.html#exported 简而言之:在AndroidManifest.xml文件中的您的活动中添加android:exported="true",避免添加intent-filter :)

1
我通过将target sdk版本从19更改为kitkat版本之后的AndroidManifest.xml,解决了这个异常。
<uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />

顺便提一下,目前Gradle已经处理了这个问题,Android开发者不需要在清单文件中指定SDK版本。 - kiedysktos
1
有一个可怕的解决方案。永远不要向下兼容。 - Jared Burrows
这个方法可以运行,但很可能会引起更多问题,而不是解决问题。这是我的观点。 - Evren Ozturk

1
“可能是配置出现了错误,很容易解决。例如:Manifest.xml文件。”

enter image description here

但是在我的配置中,默认的活动是.Splash

enter image description here

你需要检查这个配置和文件Manifest.xml
祝好运

1
确保组件的“exported”标志设置为true。 此外,定义权限的组件应在使用它的组件之前安装。

此外,您必须确保将应用程序放置在系统/priv-app分区中,以享受系统级别的豪华体验。这是KitKat及更高版本设备所必需的。 - Naren

0
我的问题是我有这个: 错误 而不是这个: 正确

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接