如何限制特定包调用绑定服务

How to restrict bound service to be called by particular packages

我写了一个绑定服务,我希望这个服务只能从特定的应用程序调用。我不希望其他应用能够调用此服务。

目前我知道的选项是:

  1. 使用权限。似乎有 3 个安全许可,dangerous,signature 和 signatureOrSystem。不幸的是,这些权限中的 none 对我有用,因为我不希望用户接受此权限,而且这两个应用程序没有相同的签名,而且这些都不是系统应用程序。
  2. 在服务绑定或调用服务时获取应用名称。我在 Whosebug here 上查找了执行此操作的方法。不幸的是,这对我不起作用,因为它总是 returns 服务所在的应用程序 ID。

是否有任何其他选项适合我,或者我可以使用上述选项并进行一些更改以达到所需的要求。

绑定服务码

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
            }
        }
    }
}

调用 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

好的,我能够根据给定的答案解决这个问题here。 link中给出的答案显然是行不通的,但是你可以从用于绑定服务的Handler中获取app ID。

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);
        }
    }

我使用的是 msg.sendingUid 而不是 Binder.getCallingUid(),它对我来说效果很好。