踩坑之_绑定远程服务

当需要进程间通信的时候有时候需要用到aidl技术,此时就需要绑定远程的服务

具体如何使用aidl技术,在此处不做介绍,只是说说在开发中在绑定过程中遇到的坑

不多说直接上代码:

 	 Intent intent = new Intent();
        intent.setAction("wsls.MyService");//通过隐式意图启动远程服务
        mConn = new MyServiceConnection();
        bindService(intent, mConn, Context.BIND_AUTO_CREATE)
   private class MyServiceConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
          //绑定成功回调,返回绑定的IBinder对象
          
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
           //远程服务断开连接(比如远程服务挂掉了)
        }
    }



次方法在4.4及以下没有问题,能够正常绑定,但运行在5.0之后会报以下异常

Caused by: java.lang.IllegalArgumentException: Service Intent must be explicit

于是开始查看源码,点击bindService方法,跳转到

ContextWrapper类中的
@Override
public boolean bindService(Intent service, ServiceConnection conn,
        int flags) {
    return mBase.bindService(service, conn, flags);
}
通过代码可以发现,绑定服务工作转换到mBase.bindService,mBase又是一个什么东西呢?点击查看
Context mBase;发现就是个上下文.context是一个抽象类,它的实现类是ContextImp
于是乎我们查看ContextImp类中的代码
  @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, Process.myUserHandle());
    }
然后会调用bindServiceCommon方法
 private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
            UserHandle user) {
        IServiceConnection sd;
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
                    mMainThread.getHandler(), flags);
        } else {
            throw new RuntimeException("Not supported in system context");
        }
        validateServiceIntent(service);
        try {
            IBinder token = getActivityToken();
            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
                    && mPackageInfo.getApplicationInfo().targetSdkVersion
                    < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                flags |= BIND_WAIVE_PRIORITY;
            }
            service.prepareToLeaveProcess();
            int res = ActivityManagerNative.getDefault().bindService(
                mMainThread.getApplicationThread(), getActivityToken(),
                service, service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, user.getIdentifier());
            if (res < 0) {
                throw new SecurityException(
                        "Not allowed to bind to service " + service);
            }
            return res != 0;
        } catch (RemoteException e) {
            return false;
        }
    }
通过代码可以发现内部会调用 validateServiceIntent(service);他是干什么的呢?

 private void validateServiceIntent(Intent service) {
        if (service.getComponent() == null && service.getPackage() == null) {
            if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
                IllegalArgumentException ex = new IllegalArgumentException(
                        "Service Intent must be explicit: " + service);
                throw ex;
            } else {
                Log.w(TAG, "Implicit intents with startService are not safe: " + service
                        + " " + Debug.getCallers(2, 3));
            }
        }
    }
通过代码可以发现在5.0以上的异常就是他抛出来的,他会通过传进去的intent进行判断包名(远程的包名)是否为空,并判断当前版本是否大于版本LOLLIPOP,
如果是5.0以上的则直接抛出一个异常,低于5.0的未做处理,这就是为什么在4.0能正常启动远程服务,5.0不可以的原因.在此贴上正确代码
 	intent.setAction("wsls.MyService");
        intent.setPackage("com.wsl.test");//这句不能少
        mConn = new MyServiceConnection();
        boolean b = bindService(intent, mConn, Context.BIND_AUTO_CREATE);

分析到此结束

另外补充一点,包名一定要以com开头,不然也无法启动远程的服务

初次写博客,请大家多多包涵,欢迎大家吐槽




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值