没有权限启动服务意图-发送者没有获得权限。

7

我正在阅读Mark Murphy的优秀的Commonsware书籍,但是需要消化的内容很多。我创建了一个名为“FakePlayer”的应用程序(假装是一个mp3播放器)。它包含一个服务。作为学习经验,我尝试编写一个微不足道的应用程序(只有一个按钮),其单击处理程序执行以下操作:

Intent i = new Intent();
i.setAction("com.example.cwfakeplayer.MyPlayerService");
Context context = getApplicationContext();
context.startService(i);

它运行良好 - 服务启动正常。我注意到Eclipse抱怨没有对服务的权限,所以我更新了服务的清单文件,添加了两行,即android:permissions和android:exported:

    <service 
        android:name="MyPlayerService"
        android:permission="com.example.fakeplayer.permission.MY_PLAYER_PERMISSION"
        android:exported="true"
       <intent-filter>
            <action android:name="com.example.fakeplayer.MyPlayerService"></action>
       </intent-filter>
      </service>

我使用Eclipse下的“debug”功能,将播放器应用重新加载到设备上(我正在使用Galaxy S2)。似乎它起作用了;启动器应用程序引发了一个权限异常,这是我预料到的。

然后,我在启动器应用程序的清单中添加了以下内容(以授予权限):

<manifest
  ...
  <uses-sdk ....
  ....
  <uses-permission android:name="com.example.fakeplayer.permission.MY_PLAYER_PERMISSION" />

我将starter app重新加载到设备上(使用Eclipse下的debug)。在starter app中仍然出现了权限错误。
我从设备中删除了两个应用程序并进行了重新安装(debug方式),先安装service app,然后再安装starter app。但仍然出现了权限错误。
我正在阅读Murphy高级Android书籍中的“如何使用远程服务”部分,所以我意识到这可能不是跨应用程序工作的最佳方式。
我执行了“adb shell dumpsys package”命令,找到了starter app,并发现它的“permissionsFixed=false”,并且没有“grantedPermissions”部分。我认为这意味着对starter app的清单更改未能使该权限添加到应用程序中。但我不知道为什么会这样。作为一次学习体验,到目前为止只产生了困惑...
非常感谢任何线索!谢谢!
2个回答

4

我通过添加2行代码 android:permissions 和 android:exported 来更新服务清单。从技术上讲,android:exported =“true”是多余的,因为具有 <intent-filter> 就会自动使 <service> 被导出。

我从设备中删除了这两个应用程序,并进行了重新安装(使用调试...),先安装服务应用程序,然后是启动程序。仍然收到 perm 错误。

您没有显示在何处使用 <permission> 元素声明自定义权限。实际上,如果您控制两个应用程序,请在两个清单中放置相同的 <permission> 元素,以便您的两个应用程序的安装顺序不再重要。


同时,在第一位加入<permission>也是有帮助的。感谢您的回答以及出色的书籍和示例代码。我在Android书中没有看到使用<permission>的示例代码,所以在我的代码中忽略了它。(我确实阅读了这一章节 - 但我非常“代码聚焦”)。 - Art Swri
@ArtSwri:嗯,你显然正在阅读的那本书(“Advanced Android”)已经在一年前被淘汰了,其内容已经整合到我的主要著作中。那本书肯定涵盖了自定义权限的<permission>元素,因为我在一个插件示例中使用了它们:https://github.com/commonsguy/cw-omnibus/tree/master/RemoteViews 话虽如此,感谢你的好评! - CommonsWare
哇,我比想象中落后得更多了——我的订阅已经到期了。现在离开去续订... - Art Swri
@CommonsWare 对于你回答的后半部分 - 他不是已经在 <service> 标签内使用了 android:permission=... 吗? - David Doria
@DavidDoria:android:permission 属性并未声明自定义权限,而是 <permission> 声明。android:permission 表示组件应该由权限(自定义或其他)进行保护,但如果该权限不存在,则不会使用它。 - CommonsWare
1
从Android 12开始,必须设置android:exported;使用true使活动对其他应用程序可用,否则使用false。移除"android:exported="true"错误后,请注意此更改。 - NickUnuchek

-2

尝试在您的清单文件中替换此内容

<service android:name="com.example.fakeplayer.MyPlayerService"></service>

而不是

<service 
    android:name="MyPlayerService"
    android:permission="com.example.fakeplayer.permission.MY_PLAYER_PERMISSION"
    android:exported="true"
   <intent-filter>
        <action android:name="com.example.fakeplayer.MyPlayerService"></action>
   </intent-filter>
  </service>

如果这不起作用,请友好地发布您的错误信息。

据我所知,删除<intent>将导致导出默认为false,这意味着该服务在包含它的应用程序之外不可见。因此,我预期发生的事情是:启动器应用程序中的startService()无效 - 没有任何可见的内容来处理Intent。(除了我在按钮点击方法中拥有的Log.d之外,日志中没有任何内容。我很感激您的努力,但不认为这实际上是一个解决方案。) - Art Swri

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