Android使用AIDL实现进程间通信

Android系统中每一个进程都有自己的Dalvik VM实例,都有自己的一块独立的内存,都在自己的内存上存储自己的数据,执行着自己的操作,都在自己的那片狭小的空间里过完自己的一生。而AIDL就类似与两个进程之间的桥梁,使得两个进程之间可以进行数据的传输,跨进程通信有多种选择,比如 BroadcastReceiver , Messenger 等,但是 BroadcastReceiver 占用的系统资源比较多,如果是频繁的跨进程通信的话显然是不可取的;Messenger 进行跨进程通信时请求队列是同步进行的,无法并发执行。

 

AIDL(Android接口定义语言): AIDL是在Android中实现进程间通信的一种机制,其本质是一种语言,AIDL的优势在于速度快(系统底层直接是共享内存),性能稳,效率高,一般进程间通信就用它。

AIDL其实是对Binder机制的封装,通过Binder来实现进程间的通信。所以两个通信的进程中有一个是客户端(Client),一个是服务器端(Service)。

例子:使用AIDL实现在客户端调用服务端的getString()方法获取字符串

一:服务器端

1.在Android Studio中新建一个Service项目。

2.创建一个AIDL接口:

(1)在app\src\main目录下右击创建一个AIDL文件,取名为“MyAidlService”:

Android使用AIDL实现进程间通信_第1张图片

(2)创建完毕后Service项目中MyAidlService.aidl文件的文件路径默认为:com.example.service(下图红圈内),MyAidlService.aidl文件代码如下:

Android使用AIDL实现进程间通信_第2张图片

MyAidlService.aidl文件中有一个接口,接口内有一个getString()方法。

3.定义好AIDL接口后需要编写Service端的代码:

新建一个MyService类继承自Service类,代码如下:

package com.example.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class MyService extends Service {
    
    class Mybind extends MyAidlService.Stub{
        @Override
        public String getString() throws RemoteException{
            String string = "我是从服务器返回的";
            return string;
        }
    }

    Mybind mybind = new Mybind();
    
    @Override
    public IBinder onBind(Intent intent) {
        return mybind;
    }

    

}

在MyService类中定义了一个内部类Mybind继承自MyAidlService.Stub类(MyAidlService.Stub类继承自Binder类),在Mybind类中重写了getString()方法,此处即是getString()方法的逻辑实现处。接着创建了Mybind类的一个实例对象mybind,并在onBind()方法中将该对象return。

到此Service端的代码基本结束,只剩下AndroidManifest.xml还需要配置一下,这部分内容放在下面讲。

二:客户端

1.在Android Studio中新建一个Client项目。

2.同样需要创建一个AIDL接口,步骤同服务器端,需要注意的是,Service和Client端的MyAidlService.aidl文件名、文件内容、文件路径要相同,由于Service项目内MyAidlService.aidl文件的默认路径为com.example.service,Client项目内MyAidlService.aidl文件的默认路径为com.example.client,所以这里将Client项目内的文件路径修改为com.example.service。

3.定义好AIDL接口后需要编写Client端的代码:

(1)在Client端的页面创建两个按钮和一个文本框,分别用来绑定服务、解绑服务、显示获取到的字符串。

(2)在MainActivity中的代码如下:

package com.example.client;

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.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.example.service.MyAidlService;

public class MainActivity extends AppCompatActivity {

    private Button bindService,unbindService;
    private TextView text;
    private MyAidlService myAidlService;

    private ServiceConnection connection = new ServiceConnection() {//创建服务连接对象
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {//当成功绑定服务时回调该方法
            myAidlService = MyAidlService.Stub.asInterface(service);//向下转型得到服务器端Mybind类的实例
            try{
                String str = myAidlService.getString();//调用实例的getString方法
                text.setText(str);//将获取到的字符串显示到屏幕
            }catch (RemoteException e){
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {//解除服务绑定时回调该方法
            myAidlService = null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bindService = (Button) findViewById(R.id.bind);
        unbindService = (Button) findViewById(R.id.unbind);
        text = (TextView) findViewById(R.id.text);

        bindService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();//构建一个意图
                intent.setAction("com.example.service.MyService");
                intent.setPackage("com.example.service");
                bindService(intent,connection,BIND_AUTO_CREATE);//绑定服务,绑定成功时
              //服务器端的onBind()方法return的Mybind实例就会作为参数传递给connection实例
            }
        });

        unbindService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                unbindService(connection);//解除服务绑定
            }
        });
    }
}

客户端的代码到此结束,剩下的就是在Service项目中修改AndroidManifest.xml文件,给MyService设置过滤器,代码如下:


    
        
    

所有的代码都写完了,接下来在模拟器上安装Service端和Client端,首先安装Service端,启动后回到手机主界面,再安装Client端,启动后点击BIND按钮,在下面的文本框就会弹出服务器端的字符串:"我是从服务器端返回的"。至此实现了Service端和Client端的通信。 效果如下:

Android使用AIDL实现进程间通信_第3张图片

 

总结:AIDL机制实现进程间通信是基于Binder机制的,AIDL其实是对Binder机制的封装。所以AIDL的实现过程和活动绑定服务的方式很相像,因为活动绑定服务也是通过Binder实现的。两者的区别在于活动绑定服务时Service类中新建了一个继承自Binder类内部类,而在AIDL实现进程间通信里的Service类新建了一个继承自MyAidlService.Stub类的内部类,MyAidlService.Stub类其实也是继承自Binder类的,只不过该类里面多了MyAidlService.aidl文件内定义的getString()方法。

你可能感兴趣的:(Java基础知识)