使用AIDL实现Service与Client绑定后的双向调用

今天在分析Application的启动流程

ActivityThread 中的ApplicationThread 是一个stub类 

ActivityManagerService作为IActivityManager的stub

使用 attachApplication 方法将该ApplicationThread 的 stub对象 传入,这看上去像是一个binder的双向绑定

见如下代码

final ApplicationThread mAppThread = new ApplicationThread();

private void attach(boolean system) {
        
        ......
 
        if (!system) {
            
            ......
            //mgr是其实就是ActivityServiceManager的一个binder远程调用对象
            final IActivityManager mgr = ActivityManager.getService();
            try {
                //这里将mAppThread这个binder对象传入了
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            //ActivityServiceManager持有ApplicationThread这个binder对象 完成Applicaiton的绑定等工作
            ......
 
        } else {
            
            ......
 
        }
 
        ......        
 
}

private class ApplicationThread extends IApplicationThread.Stub{
    ......
   void bindApplication(...)
    ......
}

在大部分的学习资料中,介绍AIDL时一般使用传统的 service-client 做为示例

通常情况下,client远程绑定service并调用service的方法。但是涉及到service调用client方法的却很少,

今天来尝试实现一个client与service的双向绑定

一:定义两个AIDL类

//ClientInterface.aidl

package vivo.testaidl;

interface ClientInterface {
    String messageFromClient();
}



//ServiceInterface.aidl

package vivo.testaidl;

import vivo.testaidl.ClientInterface;

interface ServiceInterface {

    String messageFromService();

    void registerClient(ClientInterface cb);

}

实现了简单的message打印功能

二:编写service端

package vivo.testaidl;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;

/**
 * Created by chenlong on 2019/3/11.
 */
public class RemoteService extends Service {


    private ClientInterface mClientBinder;

    private ServiceInterface mServiceBinder = new ServiceInterface.Stub() {
        @Override
        public String messageFromService() throws RemoteException {
            if (mClientBinder != null) {
                String messageFromClient = mClientBinder.messageFromClient();
                System.out.println("messageFromClient = " + messageFromClient);
            }
            return "message from service";
        }

        @Override
        public void registerClient(ClientInterface clientBinder) throws RemoteException {
//            这里拿到的直接就是ClientInterface的proxy类型
//            之前我们看AIDL源码的时候说过Service的onServiceConnected里面传入的是BinderProxy
//            然后使用asInterface来进行转换为定义的Interface
//            那这里为啥可以直接使用 不需要转换呢 我们看AIDL生成的源码部分
//            Service的registerClient方法
//            @Override
//            public void registerClient(vivo.testaidl.ClientInterface cb) throws android.os.RemoteException {
//                android.os.Parcel _data = android.os.Parcel.obtain();
//                android.os.Parcel _reply = android.os.Parcel.obtain();
//                try {
//                    _data.writeInterfaceToken(DESCRIPTOR);
//                    _data.writeStrongBinder((((cb != null)) ? (cb.asBinder()) : (null)));
//                    mRemote.transact(Stub.TRANSACTION_registerClient, _data, _reply, 0);
//                    _reply.readException();
//                } finally {
//                    _reply.recycle();
//                    _data.recycle();
//                }
//            }
//            调用了 mRemote.transact(Stub.TRANSACTION_registerClient, _data, _reply, 0);
//            我们知道这里会调用Stub的onTransact方法 并传入TRANSACTION_registerClient这个code
//            在看  onTransact 方法
//            case TRANSACTION_registerClient: {
//                data.enforceInterface(DESCRIPTOR);
//                vivo.testaidl.ClientInterface _arg0;
//                _arg0 = vivo.testaidl.ClientInterface.Stub.asInterface(data.readStrongBinder());
//                this.registerClient(_arg0);
//                reply.writeNoException();
//                return true;
//            真相大白
//            其实在registerClient的时候 ServiceInterface已经帮忙转换过了

            mClientBinder = clientBinder;
        }
    };


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return (IBinder) mServiceBinder;
    }


}

三:编写client端

package vivo.testaidl;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;

/**
 * Created by chenlong on 2019/3/11.
 */
public class ClientActivity extends Activity {

    ServiceInterface mService;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = new Intent(this, RemoteService.class);
        this.bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
    }


    ClientInterface mClientBinder = new ClientInterface.Stub() {
        @Override
        public String messageFromClient() throws RemoteException {
            return "Message From Client";
        }
    };


    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = ServiceInterface.Stub.asInterface(service);
            try {
                mService.registerClient(mClientBinder);
                String messageFromService = mService.messageFromService();
                System.out.println("messageFromService = " + messageFromService);
            } catch (RemoteException e) {
                e.printStackTrace();
            }


        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
        }
    };

}

四:注册

<?xml version="1.0" encoding="utf-8"?>
<manifest package="vivo.testaidl"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".ClientActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <service
            android:name=".RemoteService"
            android:enabled="true"
            android:exported="true"
            android:process=":remote"></service>


    </application>

</manifest>

client端在页面启动后绑定service 并且在拿到service的serviceBinder对象后调用方法并传入了一个clientBinder进去,service端拿到clientBinder之后调用了clientBinder的方法 实现双向的通信,整个过程比较简单,唯一一个比较引人注意的地方就是service的registerClient方法,在之前的“从AIDL调用看Binder使用方法”这篇文章中 ,我们拆解了整个AIDL调用的逻辑,并自己实现了模拟的AIDL调用,其中AidlInterfaceUtils的asInterface方法实现了对一个系统提供的远程IBinder的转换,那我们将clientBinder作为参数传给ServiceBinder的时候 Service拿到这个binder 为什么不需要使用asInterface进行转换呢,我们进一步追踪源码

看AIDL 自动生成的源码部分

//            Service的registerClient方法
            @Override
            public void registerClient(vivo.testaidl.ClientInterface cb) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeStrongBinder((((cb != null)) ? (cb.asBinder()) : (null)));
                    mRemote.transact(Stub.TRANSACTION_registerClient, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
//            调用了 mRemote.transact(Stub.TRANSACTION_registerClient, _data, _reply, 0);
//            我们知道这里会调用Stub的onTransact方法 并传入TRANSACTION_registerClient这个code
//            在看  onTransact 方法
            case TRANSACTION_registerClient: {
                data.enforceInterface(DESCRIPTOR);
                vivo.testaidl.ClientInterface _arg0;
                _arg0 = vivo.testaidl.ClientInterface.Stub.asInterface(data.readStrongBinder());
                this.registerClient(_arg0);
                reply.writeNoException();
                return true;
//            真相大白
//            其实在registerClient的时候AIDL自动生成的代码已经把IBinder转为ServiceInterface了

  其实在registerClient的时候AIDL自动生成的代码已经调用了asInterface方法 把IBinder转为ServiceInterface了

代码下载

https://download.csdn.net/download/binghelonglong123/11012666

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值