0

I have written a bound service and I would like this service to be only called from particular app. I do not want other apps to be able to make calls to this service.

The options I know so far are:

  1. Use a permission. There seems to be 3 secured permission, dangerous, signature and signatureOrSystem. Unfortunately, none of these permissions will work for me as I don't want users to accept this permission also both app does not have same signature and these are not system app.
  2. Get app name on service bind or when making a call to service. I looked up a way to do this on stackoverflow here. This unfortunately does not works for me as it always returns the app ID in which the service resides.

Is there any other option for me or I can use the above mentioned options with some change to achieve the desired requirement.

Bound Service Code

public class SampleCommsService extends Service {

    private static Messenger messanger;

    @Override
    public IBinder onBind(Intent intent) {
        Log.e("TEST", "package intent: " + intent.getPackage());
        String callingApp = MyApplication.getAppContext().getPackageManager().getNameForUid(Binder.getCallingUid());
        Log.e("TEST", "onBind - package name: " + callingApp);
        return getMyBinder();
    }

    private synchronized IBinder getMyBinder() {
        if (messanger == null) {
            messanger = new Messenger(new SettingsProcessor());
        }
        return messanger.getBinder();
    }

    class SettingsProcessor extends Handler {

        private static final int GET_SETTINGS_REQUEST = 1;
        private static final int UPDATE_SETTINGS_RESPONSE = 2;
        private static final String SETTINGS = "settings";

        @Override
        public void handleMessage(Message msg) {
            String callingApp = MyApplication.getAppContext().getPackageManager().getNameForUid(Binder.getCallingUid());
            Log.e("TEST", "handle message - package name: " + callingApp);

            switch (msg.what) {
                case GET_SETTINGS_REQUEST:
                    sendSettingsValue(msg);
                    break;
                default:
                    super.handleMessage(msg);
            }
        }

        private void sendSettingsValue(Message msg) {
            try {
                Message resp = Message.obtain(null, UPDATE_SETTINGS_RESPONSE);
                Bundle bundle = new Bundle();
                bundle.putBoolean(SETTINGS, MyApplication.isSettingsEnabled());
                resp.setData(bundle);
                msg.replyTo.send(resp);
            } catch (RemoteException e) {
                // ignore
            }
        }
    }
}

Output on calling api:

02-01 15:21:03.138 7704-7704/my.service.package E/TEST: package intent: null
02-01 15:21:03.139 7704-7704/my.service.package E/TEST: onBind - package name: my.service.package
02-01 15:21:12.429 7704-7704/my.service.package E/TEST: handle message - package name: my.service.package
ABS
  • 1,101
  • 10
  • 27

1 Answers1

2

OK, I was able to solve this problem based on a given answer here. The answer given in the link obviously does not works, but you can get the app ID from the Handler used for the bound service.

class SettingsProcessor extends Handler {

        @Override
        public void handleMessage(Message msg) {
            String callingApp = MyApplication.getAppContext().getPackageManager().getNameForUid(msg.sendingUid);
            Log.e("TEST", "handle message - package name: " + callingApp);
        }
    }

Instead of Binder.getCallingUid(), I am using msg.sendingUid and it works fine for me.

ABS
  • 1,101
  • 10
  • 27