I'll try to outline this scenario as well as I can. The main question is: how can I declare 2 receivers dynamically which both receive the same broadcast, but only one has the correct permission to receive it? In my testing so far, both receivers get the broadcast due to my app holding the declared permission, rather than just the one.
In App A, I am sending a broadcast which I am protecting with the new permission I am defining.
In App B, I want to ensure that the broadcast from App A is in fact being protected. So I dynamically declare the 2 receivers for the same IntentFilter
, one holding the new permission and one without. However, in App B's manifest, I of course declare <uses-permission android:name="new permission" />
However, both receivers are getting it, not just the one holding the permission. I assume that it's because App B itself is declared to use the permission. Here's my code:
App A manifest:
<permission
android:name="com.my.custom.permission"
android:label="my_permission"
android:protectionLevel="signature" />
App A source:
Intent intent = new Intent(SOME_CUSTOM_ACTION);
...
sendBroadcast(intent, "com.my.custom.permission");
App B manifest:
<uses-permission android:name="com.my.custom.permission" />
App B service:
private BroadcastReceiver rNoPermission = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (SOME_CUSTOM_ACTION.equals(intent.getAction())) {
Log.d(TAG, "receiver was able to receive without permission");
}
}
};
private BroadcastReceiver rYesPermission = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (SOME_CUSTOM_ACTION.equals(intent.getAction())) {
Log.d(TAG, "receiver was able to receive properly with permission");
}
}
};
public void start() {
IntentFilter filter = new IntentFilter(SOME_CUSTOM_ACTION);
registerReceiver(rNoPermission, filter); // purposely don't register with permission
registerReceiver(rYesPermission, filter, "com.my.custom.permission", null);
}
public void end() {
unregisterReceiver(rNoPermission);
unregisterReceiver(rYesPermission);
}
Flow:
start()
method is calledBroadcastReceiver
s get calledend()
methodAny ideas?
Realized where my mistake is. Permissions are granted at the application level, not at the component level. As per Android documentation:
To enforce a permission when sending, you supply a non-null permission argument to
sendBroadcast(Intent, String)
orsendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)
. Only receivers who have been granted this permission (by requesting it with the tag in their AndroidManifest.xml) will be able to receive the broadcast.
(Source: http://developer.android.com/reference/android/content/BroadcastReceiver.html)
and:
Senders of an intent can verify that the recipient has a permission specifying a non-Null permission with the method call. Only applications with that permission will receive the intent.
(Source: http://developer.android.com/training/articles/security-tips.html)
So as of now there doesn't appear to be a way to do what I mention above without splitting the BroadcastReceiver
s into 2 separate apps, one using the permission and one without.