在android中,不同的应用运行在各自的进程中,互不干扰,一个进程也不能直接的去访问另一个进程的内存空间,因此,进程间通讯,android提供了AIDL这个工具来实现。

AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。AIDL IPC机制是面向接口的,更加轻量级。它是使用代理类在客户端和实现端传递数据

1.定义AIDL接口

其实,AIDL接口文件和普通的接口文件没有什么区别,只不过它的扩展名是.aidl罢了。因此同其它接口是一样的,只能是接口的声明和方法的声明,它还不能有static成员变量。编辑完成之后,它会自动在gen目录文件夹下自动生成IBinder接口文件。service必须实现这个IBinder接口,那么客户端才能绑定此service然后才能从IBinder中调用方法实现不同进程间的通讯。客户端要想绑定此service并且能顺利的实现通讯,必须要完整的拷贝一份AIDL接口,包括包名以及类名和所需要的其它东东,都必须是完全相同的拷贝,不能有一点差别。(暂时我的理解就是这样)AIDL声明接口的语法很是简单,只是用来描述参数以及返回值,甚至可以是其它的AIDL接口类型。不同的参数类型引用的时候是不一样的。如java数据的基本类(int,long,char,boolean)以及string和charSquence,list,map等是不需要import导入的;如果需要使用其它的AIDL接口以及实现了Parcelable接口的类,它们即使是在同一个包中,也是需要import的。还有就是,对于非java基本数据类型,包括string和charSquence,需要加上方向的指示(in,out,inout),in表示是由客户端设置,out表示服务器端设置,inout表示两端都可以进行设置

2.创建传递数据Bean--Student类

Student是一个实现了Parcelable接口序列化的类,实现此接口必须要实现以下三个接口:

(1)writeToParcel(Parcel dest, int flags),将序列化存储的数据写入到外部提供的Parcel对象当中,以便读取。

(2)describeContents,网上叫内容接口描述,直接返回0即可,具体是干啥用的,反正我也不知道。

(3)static final Parcelable.Creator 对象 CREATOR,名字是固定的不可以更改。对应的两个接口分别是

createFromParcel(Parcel source):实现从source中创建出Bean实例的功能,如new Student(source)

newArray(int size):创建一个长度为size的类型为Bean的数组,如new Student[size]

(4)此外,既然数据能存了,还得必须能读出来啊,因此方法readFromParcel(Parcel in)这是可以要有的,读取

的顺序与写入的顺序是一样一样的,不能有错。Student类如下:

package com.dandy.AIDL;import android.os.Parcel;import android.os.Parcelable;public class Student implements Parcelable {public static final int SEX_MALE = 1;public static final int SEX_FEMALE = 2;public int sno;public String name;public int sex;public int age;public Student() {}public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>() {@Overridepublic Student createFromParcel(Parcel source) {return new Student(source);}@Overridepublic Student[] newArray(int size) {return new Student[size];}};private Student(Parcel in) {readFromParcel(in);}@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeInt(sno);dest.writeString(name);dest.writeInt(sex);dest.writeInt(age);}public void readFromParcel(Parcel in) {sno = in.readInt();name = in.readString();sex = in.readInt();age = in.readInt();}}

(5)实体类Student创建完成之后,需要创建Student.aidl文件,注意的是,这里的parcelable与实现的Parcelable是不一样的,

前者首字母p是小写,后者首字母P是大写,千万不要搞混咯。代码如下:

package com.dandy.AIDL;parcelable Student;

简单得很,就一句话就完事了。

3.创建AIDL接口

新建包:com.dandy.AIDL,然后在包中新建名为IMyService.aidl和IMyServiceResult.aidl的接口。如下:

package com.dandy.AIDL;interface IMyServiceResult{void backResult(int result);}
package com.dandy.AIDL;import com.dandy.AIDL.Student;import com.dandy.AIDL.IMyServiceResult;interface IMyService{List<Student> getStudent();int addStudent(in Student student);void result(in IMyServiceResult resultService);}

  

IMyService是主体,既是让我们外部实现调用的,而IMyServiceResult是作为IMyService中的一个方法中的参数。

4.实现接口

创建一个服务类来实现刚才定义的IMyService.aidl接口,代码如下:

package com.dandy.service;import java.util.ArrayList;import java.util.List;import com.dandy.AIDL.IMyService;import com.dandy.AIDL.IMyServiceResult;import com.dandy.AIDL.Student;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;public class MyService extends Service{private List<Student> mStudents = new ArrayList<Student>();private static final String PACKAGE_SAYHI = "com.example.aidlclient"; private boolean mCanRun = true;  private int counter = 0;private IMyServiceResult resultService;private final IMyService.Stub mBinder = new IMyService.Stub() {@Overridepublic List<Student> getStudent() throws RemoteException {synchronized (mStudents) {return mStudents;}}@Overridepublic int addStudent(Student student) throws RemoteException {if(!mStudents.contains(student)){ mStudents.add(student); return 1;}return 0;}@Overridepublic void result(IMyServiceResult resultService)throws RemoteException {MyService.this.resultService = resultService;};/** *权限验证 */@Overridepublic boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws RemoteException {String packageName = null;String packages[] = MyService.this.getPackageManager().getPackagesForUid(getCallingUid()); if(packages != null && packages.length > 0) {                  packageName = packages[0];           }   if(!PACKAGE_SAYHI.equals(packageName)){ return false; } return super.onTransact(code, data, reply, flags);  }};@Overridepublic void onCreate() {Thread thread = new Thread(null,new ServiceWorkerTest(),"BackgroundServiceWorkerTest");thread.start();for (int i = 1; i < 6; i++) {              Student student = new Student();              student.name = "student:" + i;              student.age = i * 5;              mStudents.add(student);          }  };@Override      public void onDestroy(){          mCanRun = false;          super.onDestroy();      }  @Overridepublic IBinder onBind(Intent intent) {return mBinder;}class ServiceWorkerTest implements Runnable {@Overridepublic void run() {while (mCanRun) {if(resultService != null){try {resultService.backResult(counter);} catch (RemoteException e) {e.printStackTrace();}}counter++;try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}}


在这里会看到一个IMyService.Stub类,这个类继承自IBinder类,也就是说这个MyService和普通的service 类没有区别,只不过这个这个类是返回的实现AIDL的IBinder对象。

(5)客户端获取,代码如下:

private final ServiceConnection mServiceConnection = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {mIMyService = null;}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mIMyService = IMyService.Stub.asInterface(service);}};
MyService的绑定以及解绑与普通的Service没有区别。

(6)方法的调用

findViewById(R.id.get).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {Student student = mIMyService.getStudent().get(0);Log.i("TAG", "----->student:"+student.toString());} catch (Exception e) {e.printStackTrace();}}});findViewById(R.id.add).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Student student = new Student();student.age = 100;student.name = "dandy";student.sex = Student.SEX_MALE;try {int result = mIMyService.addStudent(student);Log.i("TAG", "------>result:"+result);} catch (RemoteException e) {e.printStackTrace();}}});findViewById(R.id.result).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {mIMyService.result(new IMyServiceResult.Stub() {@Overridepublic void backResult(int result) throws RemoteException {Log.i("TAG", "--------------->result:"+result);}});} catch (RemoteException e) {e.printStackTrace();}}});


(7)AndroidManifest.xml中service配置

<service android:name="com.dandy.service.MyService"            android:process=":remote"            android:exported="true">            <intent-filter >                <category android:name="android.intent.category.DEFAULT" />                <action android:name="com.dandy.service.MyService"/>              </intent-filter>        </service>

android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",

没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。


注:以上内容结合了部分网络上资源内容,还望原著见谅!


资源文件下载。点击此处!


更多相关文章

  1. 一定是我打开的姿势不对——Android下使用kill命令杀死指定进程
  2. Android使用AIDL跨进程数据共享
  3. Android listview中嵌套Checkbox的布局文件
  4. AIDL实现Android的进程通信
  5. android studio导入 so ,jar 文件。
  6. IDA动态调试Android的DEX文件
  7. android反编译apk文件
  8. android工程下的文件资源类型
  9. linux内核启动android文件系统过程分析

随机推荐

  1. Android开发—弹出列表、单选、多选框
  2. Android获取传感器列表
  3. Android软硬整合技术(HAL&Framework):高阶
  4. Android GPS 获得 经纬度 并得到该 坐标
  5. Android---45---使用AIDL Service传递复
  6. Android开发网站
  7. Android(安卓)OOM 解决方案
  8. Android事件拦截与处理
  9. Android使用Application代替全局变量
  10. Android下进行 Facebook 分享