Android IPC机制之AIDL
什么是AIDL
AIDL:Android Interface Definition Language,即Android接口定义语言。
服务端:
1、创建一个AIDL文件,实际上是一个interface,声明一个方法
2、创建一个服务,利用AIDL文件的Stub方法在服务中实例化AIDL文件,实现AIDL文件中接口中定义的方法,返回一个IBinder对象
3、当绑定服务时将这个IBinder对象返回
客户端:
1、创建一个和服务端一模一样的AIDL文件,声明同样的方法
2、绑定服务,得到服务端返回的IBinder对象
3、将IBinder对象转换为本地定义AIDL文件,实际上是一个已经实例化的AIDL对象
4、用这个AIDL对象就可以调用服务端的方法
服务端的代码:
首先在Android Studio中创建一个aidl文件,Android Studio会自动创建一个aidl的文件夹:

创建一个aidl文件 IMyAdd,其中定义个简单的加法运算:
// IMyAdd.aidl
package com.jiao.myaidl; // Declare any non-default types here with import statements interface IMyAdd {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
int add(int first,int second);
}
然后创建一个service
package com.jiao.myaidl; import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable; /**
* Created by jiaocg on 2016/3/9.
*/
public class MyAddService extends Service { public MyAddService() {
} private Binder mBinder = new IMyAdd.Stub() {
@Override
public int add(int first, int second) throws RemoteException {
return first + second;
}
}; @Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
在清单文件中注册service
<service android:name="com.jiao.myaidl.MyAddService">
<intent-filter>
<action android:name="com.jiao.myaidl.action.MYADD_SERVICE" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
客户端代码
和服务端一样首先创建同样的aidl文件,并且声明同样的方法(注意,一定要在同一个包名下)
创建aidl文件:
// IMyAdd.aidl
package com.jiao.myaidl; // Declare any non-default types here with import statements interface IMyAdd {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
int add(int first,int second);
}
客户端调用代码:
package com.jiao.myaidl; import android.content.ComponentName;
import android.content.Context;
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.Toast; import com.jiao.myaidl.client.R; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private boolean mIsBindService;
private IMyAdd mIMyAdd;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) { Toast.makeText(MainActivity.this, "绑定服务成功", Toast.LENGTH_SHORT).show();
mIMyAdd = IMyAdd.Stub.asInterface(service);
} @Override
public void onServiceDisconnected(ComponentName name) { bindService();
}
};
private Button bt_aidl_add;
private Button bt_aidl_bind;
private Button bt_aidl_unbind; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initView(); } private void initView() { bt_aidl_bind = (Button) findViewById(R.id.bt_aidl_bind);
bt_aidl_unbind = (Button) findViewById(R.id.bt_aidl_unbind);
bt_aidl_add = (Button) findViewById(R.id.bt_aidl_add);
bt_aidl_add.setOnClickListener(this);
bt_aidl_bind.setOnClickListener(this);
bt_aidl_unbind.setOnClickListener(this);
} //绑定服务
private void bindService() {
Intent intent = new Intent();
intent.setAction("com.jiao.myaidl.action.MYADD_SERVICE");
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
mIsBindService = true;
} //解绑服务
private void unbindService() { if (mIsBindService) {
mIsBindService = false;
unbindService(mConnection);
}
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_aidl_bind: bindService(); break;
case R.id.bt_aidl_unbind:
Toast.makeText(this, "解绑成功", Toast.LENGTH_SHORT).show();
unbindService();
break;
case R.id.bt_aidl_add: if (mIsBindService && mIMyAdd != null) {
try {
int result = mIMyAdd.add(5, 5); Toast.makeText(this, result + "", Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
} } else {
Toast.makeText(this,"没有绑定服务", Toast.LENGTH_SHORT).show();
} break;
}
} }
布局代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <Button
android:layout_marginTop="50dp"
android:id="@+id/bt_aidl_bind"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="绑定服务" /> <Button
android:id="@+id/bt_aidl_unbind"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="解绑服务" /> <Button
android:id="@+id/bt_aidl_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="AIDL测试" />
</LinearLayout>
上述步骤完成之后,将两个工程同时运行,即可测试客户端能否调用服务端的方法
二 AIDL的高级应用
上个例子是用来说明客户端通过绑定服务的方式来调用服务端的方法,下面再介绍一种客户端用来获取
服务端的对象和数据,实现服务端和客户端的数据共享;
步骤和第一个例子的步骤是一样的,首先要创建一个对象类,我们设为 Computer
创建一个computer AIDL文件来声明这个对象:
服务端代码:
// Computer.aidl
package com.jiao.myaidl.entity; // Declare any non-default types here with import statements parcelable Computer;
然后创建Computer对象类
package com.jiao.myaidl.entity; import android.os.Parcel;
import android.os.Parcelable; /**
* Created by jiaocg on 2016/3/9.
*/
public class Computer implements Parcelable { public int computerId;
public String name;
public String model; public Computer(int computerId, String name, String model) { this.computerId = computerId;
this.name = name;
this.model = model;
} protected Computer(Parcel in) {
computerId = in.readInt();
name = in.readString();
model = in.readString();
} public static final Creator<Computer> CREATOR = new Creator<Computer>() {
@Override
public Computer createFromParcel(Parcel in) {
return new Computer(in);
} @Override
public Computer[] newArray(int size) {
return new Computer[size];
}
}; @Override
public int describeContents() {
return 0;
} @Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(computerId);
dest.writeString(name);
dest.writeString(model);
}
}
这里要特别注意创建的ComputerAIDL文件和Computer对象类 要在同一个包里:
如下图所示:

然后创建一个IComputerManager aidl文件,其中声明两个方法:
添加对象和获取所有对象
// IComputerManager.aidl
package com.jiao.myaidl; // Declare any non-default types here with import statements
import com.jiao.myaidl.entity.Computer;
interface IComputerManager {
void addComputer(in Computer computer);
List<Computer> getComputerList();
}
创建一个ComputerService
package com.jiao.myaidl; import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException; import com.jiao.myaidl.entity.Computer; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; public class ComputerService extends Service {
public ComputerService() {
} private CopyOnWriteArrayList<Computer> mComputerList = new CopyOnWriteArrayList<>(); private final IComputerManager.Stub mBinder = new IComputerManager.Stub() { @Override
public void addComputer(Computer computer) throws RemoteException { mComputerList.add(computer);
} @Override
public List<Computer> getComputerList() throws RemoteException {
return mComputerList;
}
}; @Override
public void onCreate() {
super.onCreate();
mComputerList.add(new Computer(0, "苹果", "model1"));
mComputerList.add(new Computer(1, "联想", "model2"));
mComputerList.add(new Computer(2, "华为", "model3"));
} @Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
// throw new UnsupportedOperationException("Not yet implemented");
return mBinder;
}
}
清单文件声明服务:
<service android:name="com.jiao.myaidl.ComputerService">
<intent-filter>
<action android:name="com.jiao.myaidl.action.COMPUTER_SERVICE" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </service>
客户端代码:
首先和服务端一样要创建同样的Computer AIDL文件和Computer对象 并且包名要一致
(即客户端 Computer aidl文件的包名和Computer对象的包名要一致 同时 也要和服务器存放computer的包名一致)
创建Computer AIDL文件
// Computer.aidl
package com.jiao.myaidl.entity; // Declare any non-default types here with import statements /**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
parcelable Computer;
创建Computer对象
package com.jiao.myaidl.entity; import android.os.Parcel;
import android.os.Parcelable; /**
* Created by jiaocg on 2016/3/10.
*/ public class Computer implements Parcelable { public int computerId;
public String name;
public String model; public Computer(int computerId, String name, String model) { this.computerId = computerId;
this.name = name;
this.model = model;
} protected Computer(Parcel in) {
computerId = in.readInt();
name = in.readString();
model = in.readString();
} public static final Creator<Computer> CREATOR = new Creator<Computer>() {
@Override
public Computer createFromParcel(Parcel in) {
return new Computer(in);
} @Override
public Computer[] newArray(int size) {
return new Computer[size];
}
}; @Override
public int describeContents() {
return 0;
} @Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(computerId);
dest.writeString(name);
dest.writeString(model);
}
}
客户调用代码
package com.jiao.myaidl; import android.content.ComponentName;
import android.content.Context;
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.Toast; import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.api.GoogleApiClient;
import com.jiao.myaidl.client.R;
import com.jiao.myaidl.entity.Computer; import java.util.List; public class Main2Activity extends AppCompatActivity implements View.OnClickListener { private boolean mIsBindService;//是否绑定了服务
private IComputerManager mRemoteComputerManager;
private Button bt_aidl_add;
private Button bt_aidl_bind;
private Button bt_aidl_unbind; //在IBinder代表的进程退出时被调用 IBinder死亡时调用
//自定义的死亡通知接受者必须要重写父类DeathRecipient的成员函数binderDied。
// 当Binder驱动程序通知一个Binder代理对象它所引用的Binder本地对象已经死亡时,
// 就会调用它所指定的死亡通知接受者的成员函数binderDied。
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { @Override
public void binderDied() { if (mRemoteComputerManager != null) {
mRemoteComputerManager.asBinder().unlinkToDeath(mDeathRecipient, 0);
mRemoteComputerManager = null;
bindService(); }
}
}; private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) { mIsBindService = true;
Toast.makeText(Main2Activity.this, "绑定服务成功", Toast.LENGTH_SHORT).show();
mRemoteComputerManager = IComputerManager.Stub.asInterface(service); try {
//注册 IBinder 死亡通知
mRemoteComputerManager.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
} @Override
public void onServiceDisconnected(ComponentName name) { mRemoteComputerManager = null;
}
};
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2); initView();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
} private void initView() { bt_aidl_bind = (Button) findViewById(R.id.bt_aidl_bind);
bt_aidl_unbind = (Button) findViewById(R.id.bt_aidl_unbind);
bt_aidl_add = (Button) findViewById(R.id.bt_aidl_add);
bt_aidl_add.setOnClickListener(this);
bt_aidl_bind.setOnClickListener(this);
bt_aidl_unbind.setOnClickListener(this);
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_aidl_bind: bindService(); break;
case R.id.bt_aidl_unbind:
Toast.makeText(this, "解绑成功", Toast.LENGTH_SHORT).show();
unbindService();
break;
case R.id.bt_aidl_add: if (!mIsBindService || mRemoteComputerManager == null){
Toast.makeText(this,"not bind service",Toast.LENGTH_SHORT).show();
return;
}
try {
List<Computer> computerList = mRemoteComputerManager.getComputerList();
for (int i =0;i<computerList.size();i++){
String str = "computerId:" + String.valueOf(computerList.get(i).computerId) +
" brand:" + computerList.get(i).name +
" model:" + computerList.get(i).model ; System.out.println(str);
}
} catch (RemoteException e) {
e.printStackTrace();
} break;
}
} private void bindService() { Intent it = new Intent();
it.setAction("com.jiao.myaidl.action.COMPUTER_SERVICE");
it.setPackage("com.jiao.myaidl.server");
mIsBindService = bindService(it, mConnection, Context.BIND_AUTO_CREATE); } private void unbindService() { if (!mIsBindService) {
return;
}
mIsBindService = false;
unbindService(mConnection);
} }
以上就实现了客户端从服务器获取对象,并使用对象,实现了服务端和客户端的数据共享。
Android IPC机制之AIDL的更多相关文章
- Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用
在上一篇文章Android IPC机制(二)用Messenger进行进程间通信中我们介绍了使用Messenger来进行进程间通信的方法.可是我们能发现Messenger是以串行的方式来处理client ...
- Android IPC通信和AIDL技术应用
首先我们了解一下 IPC和AIDL IPC:进程间通信 AIDL:Android Interface Definition Language,即Android接口定义语言. 为什么使用: Androi ...
- Android IPC机制全解析<一>
概要 多进程概念及多进程常见注意事项 IPC基础:Android序列化和Binder 跨进程常见的几种通信方式:Bundle通过Intent传递数据,文件共享,ContentProvider,基于Bi ...
- Android IPC机制基础
概要 多进程概念及多进程常见注意事项 IPC基础:Android序列化和Binder 跨进程常见的几种通信方式:Bundle通过Intent传递数据,文件共享,ContentProvider,基于Bi ...
- android IPC 机制 (开发艺术探索)
一.IPC 机制介绍 IPC是Inter-Process Communication的缩写,含义就是进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程.那么什么是进程,什么是线程,进程和线程 ...
- Android IPC机制—Binder的工作机制
进程和线程的关系 IPC机制即为跨进程通信,是inter-Process Communication的缩写.是指两个进程之间进行通信.在说进程通信之前,我们的弄明白什么是线程,什么是进程.进程和线程是 ...
- 深入理解Android IPC机制之Binder机制
Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有的进程间通信IPC手段包括(Internet Process Connection): 管道(Pipe).信号(Sign ...
- 【Android - IPC】之AIDL简介
参考资料: 1.<Android开发艺术探索>第二章2.4.4 2.Android AIDL Binder框架解析:http://blog.csdn.net/lmj623565791/ar ...
- Android IPC机制(三)使用AIDL实现跨进程方法调用
上一篇文章中我们介绍了使用Messenger来进行进程间通信的方法,但是我们能发现Messenger是以串行的方式来处理客户端发来的信息,如果有大量的消息发到服务端,服务端仍然一个一个的处理再响应客户 ...
随机推荐
- [译]学习IPython进行交互式计算和数据可视化(六)
第五章:高性能并行计算 一个反复被提及的反对使用Python进行高性能数值计算的言论是这种语言是动态解释型的,速度太慢.一种编译型低级语言,如C,能提供比它快几个数量级的运算速度.我们在第三章--使用 ...
- ADB pm 命令
usage: pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_TER] pm list permission-grou ...
- Nancy 学习-进阶部分 继续跨平台
前面两篇,讲解Nancy的基础,及Nancy自宿主和视图引擎. 现在来学习一些进阶部分. Bootstrapper Bootstrapper 就相当于 asp.net 的Global.asax . 我 ...
- printf的题目
以前学习于渊老师的<自己动手写操作系统>一书的时候,也自己实现过printf,不过那是比较简单的版本.最近看<程序员面试宝典>,做到这么一道题目:#include <st ...
- aspNet各种模块介绍
For browsers that do not support HTML5, you can use Modernizr. Modernizr is an open-source JavaScrip ...
- TabHost的使用
Android中的选项卡是用TabHost实现的. 首先,定义TabHost的布局文件: <?xml version="1.0" encoding="utf-8&q ...
- JQuery的调用
在head标签中引用一个JQuery的文件用以制作鼠标点击动画,(JQuery包可从网上下载) JS包,脚本语言 <script language="javascript" ...
- 代码与图详解性能之Python集合类型(list tuple dict set generator)
Python内嵌的集合类型有list.tuple.set.dict. 列表list:看似数组,但比数组强大,支持索引.切片.查找.增加等功能. 元组tuple:功能跟list差不多,但一旦生成,长度及 ...
- 从零开始学Python第0周:Python基本介绍(部分内容来源于网络)
Python入门介绍 一,Python的基本介绍 (1)概要 Python是一种解释型,面向对象,动态数据类型的高级程序设计语言.常被广泛用于处理系统管理任务和web编程.现如今Python已经成为了 ...
- jQuery实现发送短信验证码后60秒倒计时
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script sr ...