IPC_Aidl的基本使用过程

Posted 從前以後

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IPC_Aidl的基本使用过程相关的知识,希望对你有一定的参考价值。

AIDL全称 android Interface definition language的缩写,顾名思义,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口.
下面是AIDL的详细使用过程。
简单起见,就完成一个客户端调用服务端,完成一次两个数加法的运算。
首先新建一个工程Server,然后规范起见,创建一个单独的.aidl的包。右键新建文件,创建一个.aidl的文件。

package com.example.server.aidl;
interface IAdd

int  add(int i,int j);

这个时候在工程根目录下会自动创建一个.java 的文件

接着就是写Server端的服务了

package com.example.server;
import com.example.server.aidl.IAdd;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class MyService extends Service 


    @Override
    public IBinder onBind(Intent intent) 
        // TODO 自动生成的方法存根
        return add;
    
    IAdd.Stub  add=new IAdd.Stub() 

        @Override
        public int add(int i, int j) throws RemoteException 
                int sum=i+j;
                Log.e("ethan", "sum=="+sum);
            return sum;
        
    ;

服务内部没有特别的东西,就是实例化一个IAdd的接口对象,然后把该对象转换成IBinder类型的对象(stub方法就是干这事的)。之后通过onBind()方法返回 ,实例化并转化类型过后的对象add。

由于是跨进程启动,所以需要隐式启动服务。因此在Manifest中给服务注册上Action

 <service android:name="com.example.server.MyService">
            <intent-filter >
                <action android:name="com.example.server.MyService.MyAidl"/>
            </intent-filter>
        </service>

接下来就是客户端的代码实现了
首先把服务端的Aidl复制到客户端(连包名一起)

接着就是写MainActivity里面的代码了

public class MainActivity extends Activity implements OnClickListener 
    private Button button1,button2;
    private IAdd add;
    ServiceConnection conn=new ServiceConnection()         
        @Override
        public void onServiceDisconnected(ComponentName name)      
           
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) 
            add=IAdd.Stub.asInterface(service);     
        
    ;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    
    private void initViews() 
        // TODO 自动生成的方法存根
        button1=(Button) findViewById(R.id.button1);
        button2=(Button) findViewById(R.id.button2);
        button1.setOnClickListener(this);
        button2.setOnClickListener(this);
    
    @Override
    public void onClick(View v) 
    switch (v.getId()) 
    case R.id.button1:
        bindService(new Intent("com.example.server.MyService.MyAidl"), conn, BIND_AUTO_CREATE);
        break;
    case R.id.button2:
        try 
            add.add(3, 2);
         catch (RemoteException e) 
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        
        break;
    

    

在MainActivity里面,首先注册两个按钮,一个用来绑定Service,一个用来调用远程服务。接着实例化一个ServiceConnection的对象conn,然后在button1的点击事件里,执行bindService,bindServic
e的三个参数分别为隐式地洞Service的intent,ServiceConnection的实例化对象conn,以及flag参数。当执行完该方法后,会回调ServiceConnection里面的public void onServiceConnected(ComponentName name, IBinder service) 提供一个IBinder 的对象service回来,这个service其实是BinderProxy类型,然后调用aidl接口将service转换成IAdd类型的对象add。
于是就可以通过add,调用IAdd接口里面的方法了。
接着点击button2,执行接口IAdd接口里面的add方法。

    case R.id.button2:
        try 
            add.add(3, 2);
         catch (RemoteException e) 
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        
        break;

接着,控制台顺利打印出Log sum=5。证明调用远程服务成功了。

 E/ethan(2015): sum==5

回看AIDL的使用过程,其实和IPC(一)使用纯Binder进行进程间通信
大体上差不多,AIDL其实就是把Binder中的transact函数封装到了IAdd接口内部。上文拿到的IAdd的接口对象add,实际上是BinderProxy(实现了IBinder接口)的对象转化过来的,也就是把BinderProxy对象封装到了IAdd接口对象内部。当我们调用add.add()方法时候,内部还是调用的BinderProxy中的transact()方法来发送数据的。

下篇IPC(五)——浅谈AIDL的架构原理

以上是关于IPC_Aidl的基本使用过程的主要内容,如果未能解决你的问题,请参考以下文章

iOS唯一的遗憾是太短了!不愧是App Store年度最佳游戏《甜甜圈都市》

7.Go语言高并发与微服务实战 --- 远程过程调用 RPC

Blackberry应用程序中的Web服务存根

rpc机制和实现过程

如果结果没有在客户端存根处解包,RPC 模型会发生啥?

打地鼠游戏之动画效果