Custom permission on Broadcast

from the CommonsWare Community archives

At October 8, 2021, 7:20pm, Jan asked:

I read the BroadcastReceiver documentation but I didn’t find it clear on using the uses-permission
and permission elements in the manifest.

My BroadcastReceiverNoPermission class works (onReceive gets the broadcast) without the custom permission but not when I pass one in on the sendBroadcast (for BroadcastReceiverWithPermission class). I am assuming the fault lies in the manifest because there doesn’t seem any other place that it could be failing.

In both app A and app B, I put in the uses-permission element in their respective manifests. The documentation seemed to say you needed that for both the sending app and the receiving app.

The permission name is a custom string (such as com.myapp.MyRequest). I’m letting the default level be “normal” for the custom permission so the user never gets queried about usage of the permission.

I don’t really understand why the permission element is needed but it seems to be in order that the permission can be shown in the App Info box. So I put the permission element in both manifests too. But the App Info box never shows the custom permission on either App. Documentation says this element goes within the manifest element so that is where I put it. <permission>  |  Android Developers

When I do a sendBroadcast, I add the permission to the call. The receiver never gets invoked (no OnReceive in my class BroadcastReceiverWithPermission).

The registerReceiver calls appropriately passes in the permission string for the receiver using permissions and leaves it off for the receiver that doesn’t.

I know the actual values for permission matches everywhere (a string).

Should I have uses-permission in the manifest for both apps?
Should I have permission element in the manifest for both apps?


At October 8, 2021, 8:23pm, mmurphy replied:

AFAIK, <uses-permission> is only needed on the sending app, in your scenario.

Um, well, that custom permission needs to be defined somewhere.

That’s necessary, particularly if you do not know what order the two apps will be installed in. The permission needs to be defined by a <permission> element before you can use it in <uses-permission> or android:permission or similar places.

I do not know what box you are referring to. I am not aware that the Settings app provides any information about apps that define permissions. And, since custom permissions have had problems, I have not experimented with them much since the Android 5.0 days. Custom permissions really were designed for device manufacturers and pre-installed apps.

That says that you are requiring that the receiver app have a <uses-permission> element for your custom permission.

It sounds like the answer is “yes”. You seem to be attempting to require that both the sender and the receiver hold that custom permission for your broadcast to work.

Yes.

Note that snce you have a normal protection level, any app installed after one of yours can have a <uses-permission> element for your custom permission and have the same rights that your app does. If you are trying to limit this to only your apps, you need to use a signature permission and use the same signing key for both apps. And I do not know what the current rules are with respect to Play App Signing for whether it is possible to use the same signing key with both apps.


At October 8, 2021, 8:55pm, Jan replied:

I guess I’ll have to give up on permissions. I was hoping to use it as a security measure so that just not any app could get the broadcast.

One more question:
My interpretation of receiver tag is that the Android system would create the receiver if the app wasn’t active and a broadcast was done. But that isn’t happening.

Have I misinterpreted what it says:
You can either dynamically register an instance of this class with Context.registerReceiver() or statically declare an implementation with the tag in your AndroidManifest.xml.

There are two ways to make a broadcast receiver known to the system: One is declare it in the manifest file with this element. The other is to create the receiver dynamically in code and register it with the Context.registerReceiver() method.

It is only when I do the registerReceiver that I get the broadcast - which means the app has to be running to make the call to registerReceiver.

Have you ever seen receiver element specified in the manifest to work by starting the component (BroadcastReceiver) when app wasn’t running? I suspect it only works for system broadcasts and Android just never changed their wishful thinking documentation (which happens a lot).


At October 8, 2021, 9:12pm, mmurphy replied:

If you can figure out the signature stuff, that would still work. But normal is not really designed for your scenario.

That suggests that your broadcast is using an implicit Intent. In addition to a custom action string, you need to use setPackage() or setComponentName() on the Intent to be broadcast. Then you can register for it in the manifest. See Android O and the Implicit Broadcast Ban for more.

If my guess is correct, it is more that they do not have their implicit broadcast ban documentation linked to from all the right places.


At October 8, 2021, 9:25pm, Jan replied:

Thanks. Your blog article was very helpful.