背景
历史上,Android自定义权限一直很混乱并且安装顺序依赖性很强,这已经被证明会暴露漏洞。
在API 21之前,有一种令人不安的解决方法,即在您的清单中声明另一个应用程序的自定义权限,即可授予权限...但是,自API 21以来,只有一个应用程序可以声明自定义权限,并且进一步声明此相同权限的应用程序的安装将被阻止。
替代方法是重新安装需要该权限的应用程序,以便它们被系统检测到,但这不是一个好的用户体验。或者在运行时检查调用应用程序的权限,但这也不是没有理论缺陷的。
问题
从Android Marshmallow(6.0 - API 23)开始,应用程序需要请求用户的权限,以使用其自定义权限。声明的自定义权限不会自动授予。
这似乎很奇怪,因为现在只有一个应用程序可以声明它。
复制操作
在清单文件中声明自定义权限和BroadcastReceiver。
<permission
android:name="com.example.app.permission.CONTROL_EXAMPLE_APP"
android:description="@string/control_description"
android:icon="@mipmap/ic_launcher"
android:label="@string/control_label"
android:protectionLevel="normal or dangerous"/>
<uses-permission
android:name="com.example.app.permission.CONTROL_EXAMPLE_APP"/>
// etc
<receiver
android:name="com.example.app.MyBroadcastReceiver"
android:permission="com.example.app.permission.CONTROL_EXAMPLE_APP">
<intent-filter android:priority="999">
<action android:name="com.example.app.REQUEST_RECEIVER"/>
</intent-filter>
</receiver>
从第三方应用程序中,在清单文件中声明使用自定义权限(并通过对话框或设置接受它),然后调用:
final Intent intent = new Intent("com.example.app.REQUEST_RECEIVER");
context.sendOrderedBroadcast(intent, "com.example.app.permission.CONTROL_EXAMPLE_APP", new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
// getResultCode();
}
}, null, Activity.RESULT_CANCELED, null, null);
该结果将返回CANCELED,并且日志将显示:
system_process W/BroadcastQueue: Permission Denial: receiving Intent { act=com.example.app.REQUEST_RECEIVER flg=0x10 (has extras) } to com.example.app/.MyBroadcastReceiver requires com.example.app.permission.CONTROL_EXAMPLE_APP due to sender com.example.thirdparty
如果我使用标准的ActivityCompat.requestPermissions()对话框来允许用户接受权限,则接收器会像您预期的那样正常工作。
问题:
这是预期行为吗?还是我忽略了什么?
看起来要求用户弹出一个对话框,说“Example App应用程序想要使用Example App”,这似乎很荒谬,并且确实会让用户感到困惑。
当然,我可以更改权限描述和名称,以便他们接受,例如“与其他已安装的应用程序通信”,但在我叹了口气并采取这种方法之前,我想问一下这个问题。
注:
有序广播的示例是为了复制问题。我的应用程序确实使用了其他内容提供程序和绑定服务的实现。我需要确认的不是替代实现,而是问题本身。
感谢您一直阅读到这里。
编辑:为了澄清,对于其他实现,例如在服务上声明权限(最简单的复制方式),所声明的自定义权限会自动授予。