Search code examples
androidandroid-intentandroid-activitybroadcastreceiverandroid-permissions

Enforcing android permissions within the same app


Here is a scenario. My app has

  • BroadcastSenderActivity
  • SampleBroadcastReceiver

I am using the sendBroadcast(intent, permission) method to send out my broadcast because I would like only my SampleBroadcastReceiver to receive the broadcast message and prevent other receivers in my app from receiving the message.

Note: All receivers are registered for the same action but at the time of broadcast based on the system conditions the message will be broadcasted with varying permissions.

From the documentation I learnt that I need the following in the manifest :

  1. Need to declare <permission android:name="com.example.MYPERMISSION" android:label="my_permission" android:protectionLevel="normal"></permission> in the manifest

  2. Have this stmt to request for the permission which is at the app level <uses-permission android:name="com.example.MYPERMISSION"/>

QUESTION -

  • Instead of app-level permission request how can I request permission only for a particular component in my app? eg. SampleBroadcastReceiver (see code below). Is it possible?*

  • What's the purpose of the <android-permission> tag which is available for all inidividual components? Can it serve my purpose ?

    AndroidManifest

        .........
    

    <activity
          android:name="com.example.activities.BroadcastSenderActivity"
          android:label="BroadcastSenderActivity"
          android:theme="@android:style/Theme.Light" >
          <intent-filter>
            <action android:name="android.intent.action.MAIN" />
    
            <category android:name="android.intent.category.LAUNCHER" />
         </intent-filter>
    </activity>
    
    <!-- **************************************  RECEIVER ******************************************* -->
    <receiver android:name="com.example.broadcastTest.SampleBroadcastReceiver"
        android:exported="false">
        <intent-filter>
            <action android:name="com.example.ACTION_BROADCAST_SEND" />
        </intent-filter>
    </receiver>
    <receiver android:name="com.example.broadcastTest.BroadcastReceiver_1"
        android:exported="false">
        <intent-filter>
            <action android:name="com.example.ACTION_BROADCAST_SEND" />
        </intent-filter>
    </receiver>
    <receiver android:name="com.example.broadcastTest.BroadcastReceiver_2"
        android:exported="false">
        <intent-filter>
            <action android:name="com.example.ACTION_BROADCAST_SEND" />
        </intent-filter>
    </receiver>
    


    public class BroadcastSenderActivity extends Activity {

public BroadcastSenderActivity() {

}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d(Logger.TAG, "BroadcastSenderActivity - onCreate");
    setContentView(R.layout.broadcast_tester);
    Button btn = (Button)findViewById(R.id.sendBroadcastBtn);
    btn.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            Intent broadcastIntent = new Intent();
            Log.d(Logger.TAG, "BroadcastSenderActivity - sending the broadcast");
            broadcastIntent.setAction(com.example.ACTION_BROADCAST_SEND);
            BroadcastSenderActivity.this.sendBroadcast(broadcastIntent, com.example.MYPERMISSION);

Solution

  • You can secure each separate component with a specific permission. This is the android:permission="..." attribute that can be applied to each component separately. This allows you to require different permissions, for example, to launch a specific Activity, start a specific Service or use a specific BroadcastReceiver. This attribute indicates that the application needs to hold the specified permission in order to use the specific component.

    An application holds a set of permissions. These permissions are requested in the manifest by the <uses-permission> tags. The user is shown this list when the application is installed and the application is granted these permissions upon installation.

    When you send a broadcast, usually all installed and/or registered BroadcastReceivers are able to see this broadcast. When you use the method sendBroadcast(intent, permission) the permission parameter is used to control which receivers are able to see the broadcast. However, this permission checking is also done at the application level. This means that if an application has been granted the specified permission, then all of that application's BroadcastReceivers will be able to see the broadcast.

    Therefore, what you want to do is not possible using the Android permission mechanism. Because an application either has or does not have a specific permission, you cannot have fine-grained control over which components can be used by a specific application.

    Hopefully this answers your question.

    EDIT: Alternative suggestion:

    Since this is all within a single application, you should be able to manage this yourself. Personally, I think using the Android permission framework for this is overkill. You can just add an appropriate extra to the broadcast Intent and use that for controlling access to the receivers. Or, you can define 2 different Intent actions, and use that to control access.