Android Studio创建AIDL文件并实现进程间通讯

来源:互联网 发布:人工智能 金融投资 编辑:程序博客网 时间:2024/06/10 08:29

在Android系统中,跨进程通信是非常普遍的事情,它用到了Binder机制处理进程之间的交互。Binder机制会开放一些接口给Java层,供android开发工程师调用进程之间通信。这些接口android封装到了AIDL文件里,当我们项目用到跨进程通信时可以创建.aidl文件,.aidl文件可以协助我们达到跨进程的通信。下面简单介绍用AndroidStudio创建AIDL文件的过程。

a.新建AIDL文件

1.项目文件夹右键---> new --->选择AIDL



2.自定义一个接口名称



3.创建之后我们看到了xxx.aidl文件,然后编辑自己项目需要实现的方法,这里很简单就获取一个字符串的方法getAllName。



4.写好之后,我们需要重新ReBuild,完后在项目build/generated/source/aidl/debug/包名 目录下就看到了系统为我们生成的以刚才.aidl文件名命名的java文件。



该java文件系统会自动生成代码:

Stub:描述了一个Java服务,对应是一个远程的Service。

Proxy:描述了一个Java服务的代理对象,在Client端就会得到这个对象。

这两者都实现了IPersonManager接口。

asInterface:将Java服务的代理对象即一个BinderProxy封装成了一个IPersonManager.Stub.Proxy对象,实现了IPersonManager接口。

onTransact:负责接收分发进程间的通信。它首先会收到Client发来的请求,不同的方法进入相应的case代码中,然后交给Stub的子类去处理事件,例如 java.lang.String _result = this.getAllName();   这里的this就可以让它的子类去接收该请求并处理。

IBinder的transact方法:用来发送进程间的请求。


b.利用AIDL实现进程间的通讯

一:接口文件中只含有基础数据类型

如上aidl文件,IPersonManager中只用到了基本数据类型,此时要完善Server端的小项目,还需要新建一个Service。

Server端代码如下

[java] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. public class PersonService extends Service {  
  2.   
  3.     private static String names = "alice & iland";  
  4.     public PersonBinder mPersonBinder;  
  5.     @Override  
  6.     public void onCreate() {  
  7.         super.onCreate();  
  8.         mPersonBinder = new PersonBinder();  
  9.     }  
  10.   
  11.     @Override  
  12.     public IBinder onBind(Intent intent) {  
  13.         return mPersonBinder;  
  14.     }  
  15.     public class PersonBinder extends IPersonManager.Stub{  
  16.   
  17.         @Override  
  18.         public String getAllName() throws RemoteException {  
  19.             return names;  
  20.         }  
  21.     }  
  22.   
  23. }  

继承系统的Service,并建立一个内部类继承IPersonManager.Stub,这里很简单,当客户端请求要获取名字时我们这里把names给到客户端。


Client端代码如下

[java] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. public class MainActivity extends AppCompatActivity implements View.OnClickListener{  
  2.     private static final String TAG = "MainActivity";  
  3.     private Button btnGet;  
  4.     private EditText etShow;  
  5.     public IPersonManager mIPersonManager;  
  6.     ServiceConnection sc = new ServiceConnection() {  
  7.         @Override  
  8.         public void onServiceConnected(ComponentName name, IBinder service) {  
  9.             Log.i(TAG, "onServiceConnected: ");  
  10.             mIPersonManager = IPersonManager.Stub.asInterface(service);  
  11.         }  
  12.   
  13.         @Override  
  14.         public void onServiceDisconnected(ComponentName name) {  
  15.             Log.i(TAG, "onServiceDisconnected: ");  
  16.             mIPersonManager = null;  
  17.         }  
  18.     };  
  19.     @Override  
  20.     protected void onCreate(Bundle savedInstanceState) {  
  21.         super.onCreate(savedInstanceState);  
  22.         setContentView(R.layout.activity_main);  
  23.         btnGet = (Button) findViewById(R.id.btn_getname);  
  24.         etShow = (EditText) findViewById(R.id.et_allnamef);  
  25.         btnGet.setOnClickListener(this);  
  26.   
  27.         Intent intent = new Intent("com.ly.testaidlserver.aidl.AIDL_SERVICE");  
  28.         intent.setPackage("com.ly.testaidlserver");  
  29.         bindService(intent,sc, Service.BIND_AUTO_CREATE);  
  30.     }  
  31.   
  32.     @Override  
  33.     public void onClick(View v) {  
  34.         switch (v.getId()){  
  35.             case R.id.btn_getname:  
  36.                 String names = null;  
  37.                 try {  
  38.                     if (mIPersonManager!=null)  
  39.                         names = mIPersonManager.getAllName();  
  40.                 } catch (RemoteException e) {  
  41.                     e.printStackTrace();  
  42.                 }  
  43.                 etShow.setText(names);  
  44.                 break;  
  45.             default:  
  46.                 break;  
  47.         }  
  48.     }@Override  
  49.     protected void onDestroy() {  
  50.         super.onDestroy();  
  51.         unbindService(sc);  
  52.     }  
  53.   
  54. }  

在onServiceConnected方法中拿到IPersonManager的代理对象,最终获取到 alice & ilan,与服务端数据一致。


注意:

1.bindService方法在5.0以后做出改变,隐式意图需要设置Package 或者 Commponent,直接定义一个action是报异常的。

[java] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. Intent intent = new Intent("com.ly.testaidlserver.aidl.AIDL_SERVICE");  
  2. <span style="background-color: rgb(204, 204, 204);">intent.setPackage("com.ly.testaidlserver");</span>  
  3. bindService(intent,sc, Service.BIND_AUTO_CREATE);  

2.我们需要把Server端的aidl文件复制到Client端,在Client中存放aidl的文件夹也需要跟Server端包名一致。

如图:


上图为aidl文件在Server端存放的路径,下图为复制到Client端aidl文件的路径,这里要保持一致,因此Client端需要针对Server端的包名新建一个Package。

3.当我们启动项目的时候,如果在Activity中IPersonManager找不到报出异常,请在app的build.gradle中添加aidl文件指名目录,如本例中添加,

    sourceSets{
        main {
            aidl.srcDirs = ['src/main/aidl','src/main/java']
        }
    }


二:接口文件中含有复杂数据类型、

1.新建一个Person.aidl     内容非常简单

parcelable Person;

2.新建一个Person实体类,为了能在进程间进行通信必须实现Parcelable接口。

3.在IPersonManager中添加了一个方法,这里注意用到的Person类必须将包名improt进去。

4.将IPersonManager.aidl、Person.aidl、Person.java复制到客户端的aidl包下。

5.查看是否需要修改build.gradle中sourceSets设置


代码基本没有变化:


Person.java

[java] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. public class Person implements Parcelable {  
  2.     String name;  
  3.     int age;  
  4.   
  5.     public Person(String name, int age) {  
  6.         this.name = name;  
  7.         this.age = age;  
  8.     }  
  9.   
  10.     public static final Creator<Person> CREATOR = new Creator<Person>() {  
  11.         @Override  
  12.         public Person createFromParcel(Parcel in) {  
  13.             return new Person(in.readString(), in.readInt());  
  14.         }  
  15.   
  16.         @Override  
  17.         public Person[] newArray(int size) {  
  18.             return new Person[size];  
  19.         }  
  20.     };  
  21.   
  22.     @Override  
  23.     public int describeContents() {  
  24.         return 0;  
  25.     }  
  26.   
  27.     @Override  
  28.     public void writeToParcel(Parcel dest, int flags) {  
  29.         dest.writeString(name);  
  30.         dest.writeInt(age);  
  31.     }  
  32.   
  33.     public String getName() {  
  34.         return name;  
  35.     }  
  36.   
  37.     public void setName(String name) {  
  38.         this.name = name;  
  39.     }  
  40.   
  41.     public int getAge() {  
  42.         return age;  
  43.     }  
  44.   
  45.     public void setAge(int age) {  
  46.         this.age = age;  
  47.     }  
  48. }  

IPersonManager.aidl

[java] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. interface IPersonManager {  
  2.    String getAllName();  
  3.    List<Person> getPersonList();  
  4. }  


Server

[java] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. public class PersonService extends Service {  
  2.   
  3.     private List<Person> persons = new ArrayList<Person>();  
  4.     public PersonBinder mPersonBinder;  
  5.     @Override  
  6.     public void onCreate() {  
  7.         super.onCreate();  
  8.         mPersonBinder = new PersonBinder();  
  9.         Person p1 = new Person("alice",23);  
  10.         persons.add(p1);  
  11.         Person p2 = new Person("iland",18);  
  12.         persons.add(p2);  
  13.     }  
  14.   
  15.     @Override  
  16.     public IBinder onBind(Intent intent) {  
  17.         return mPersonBinder;  
  18.     }  
  19.     public class PersonBinder extends IPersonManager.Stub{  
  20.   
  21.         @Override  
  22.         public String getAllName() throws RemoteException {  
  23.             return "";  
  24.         }  
  25.   
  26.         @Override  
  27.         public List<Person> getPersonList() throws RemoteException {  
  28.             return persons;  
  29.         }  
  30.     }  
  31. }  


Clent

[java] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. public class MainActivity extends AppCompatActivity implements View.OnClickListener{  
  2.     private static final String TAG = "MainActivity";  
  3.     private Button btnGet;  
  4.     private EditText etShow;  
  5.     public IPersonManager mIPersonManager;  
  6.     ServiceConnection sc = new ServiceConnection() {  
  7.         @Override  
  8.         public void onServiceConnected(ComponentName name, IBinder service) {  
  9.             Log.i(TAG, "onServiceConnected: ");  
  10.             mIPersonManager = IPersonManager.Stub.asInterface(service);  
  11.         }  
  12.   
  13.         @Override  
  14.         public void onServiceDisconnected(ComponentName name) {  
  15.             Log.i(TAG, "onServiceDisconnected: ");  
  16.             mIPersonManager = null;  
  17.         }  
  18.     };  
  19.     @Override  
  20.     protected void onCreate(Bundle savedInstanceState) {  
  21.         super.onCreate(savedInstanceState);  
  22.         setContentView(R.layout.activity_main);  
  23.         btnGet = (Button) findViewById(R.id.btn_getname);  
  24.         etShow = (EditText) findViewById(R.id.et_allnamef);  
  25.         btnGet.setOnClickListener(this);  
  26.   
  27.         Intent intent = new Intent("com.ly.testaidlserver.aidl.AIDL_SERVICE");  
  28.         intent.setPackage("com.ly.testaidlserver");  
  29.         bindService(intent,sc, Service.BIND_AUTO_CREATE);  
  30.     }  
  31.   
  32.     @Override  
  33.     public void onClick(View v) {  
  34.         switch (v.getId()){  
  35.             case R.id.btn_getname:  
  36.                 ArrayList<Person> persons = null;  
  37.                 try {  
  38.                     if (mIPersonManager!=null)  
  39.                         persons = (ArrayList<Person>) mIPersonManager.getPersonList();  
  40.                 } catch (RemoteException e) {  
  41.                     e.printStackTrace();  
  42.                 }  
  43.                 String result = "";  
  44.                 for (Person person : persons){  
  45.                     result = result+person.getName()+"__"+person.getAge();  
  46.                 }  
  47.                 etShow.setText(result);  
  48.                 break;  
  49.             default:  
  50.                 break;  
  51.         }  
  52.     }@Override  
  53.     protected void onDestroy() {  
  54.         super.onDestroy();  
  55.         unbindService(sc);  
  56.     }  
  57.   
  58. }  


0 0
原创粉丝点击