Android: are context-registered broadcast receivers exported?
From the api docs on the BroadcastReceiver API:
If you don't need to send broadcasts across applications, consider using this class with LocalBroadcastManager instead of the more general facilities described below. This will give you a much more efficient implementation (no cross-process communication needed) and allow you to avoid thinking about any security issues related to other applications being able to receive or send your broadcasts.
That way at least you can keep the receiver only inside your application.
To spare others the work and for my own archiving purposes: Yes, context-registered receivers are exported by default.
There doesn't seem to be a lot of documentation but you can validate this quickly by running a separate app sending a custom broadcast. I tested this on APIs 16-29, the broadcast will be received and so every package will be able to send to your receiver (which can be a security flaw).
To solve the issue without using local broadcasts (should be used wherever possible) you are on the right track in defining a custom permission and restricting broadcasts to apps that have requested that permission. For the sake of completeness:
Define and use a custom permission in the manifest:
<permission android:name="com.example.bcrtest.BROADCAST_PERMISSION"
android:protectionLevel="signature"/>
<uses-permission android:name="com.example.bcrtest.BROADCAST_PERMISSION" />
Register receiver with permission:
registerReceiver(mReceiver, new IntentFilter(MY_INTENT_ACTION), "com.example.bcrtest.BROADCAST_PERMISSION", null );