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是以串行的方式来处理客户端发来的信息,如果有大量的消息发到服务端,服务端仍然一个一个的处理再响应客户 ...
随机推荐
- 在_Layout模版中使用@Styles.Render()没有效果
刚才有测试一个功能,就是在_Layout母版中使用了@Styles.Render()时行Render样式文件,所有在此母版下的视图均没有应用到样式,没有效果.是什么原因? 经查证资料,原来Insus. ...
- STOP:c0000218 {Registry File Failure}
这几天够折腾的了,一台很老很老的服务器,在启动之后,一个阵列磁盘掉线了: 也许是磁盘坏了: 服务器4个硬盘做的是RAID1,正常来说,坏了其中一二个硬盘是没有问题的.现更换了一个好的硬盘之后,系统无法 ...
- Java.io.DataInputStream.readInt()
1. 代码 import java.io.DataInputStream; import java.io.IOException; public class Test { public static ...
- /dev/random 和 /dev/urandom的一点备忘
1. 基本介绍 /dev/random和/dev/urandom是Linux系统中提供的随机伪设备,这两个设备的任务,是提供永不为空的随机字节数据流.很多解密程序与安全应用程序(如SSH Keys, ...
- GJM :JS + CSS3 打造炫酷3D相册 [转载]
感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...
- FHS定义的Linux目录树
根目录/: 最重要的一个目录,与开机/修复/还原有关.该目录所在的分区越小越好,安装的程序也最好不要放在该分区内. 根目录下必须存在的子目录: 目录 说明 /bin 存放了很多常用命令,能被root和 ...
- Virtual Box和Linux的网络配置盲记
近来可能在虚拟机重装了Linux的缘故,在用yum安装软件时出现错误,在提示上连接镜像网站时,都是"linux counldn't resolve host"这样的提示.我估计是l ...
- java内存模型-重排序
数据依赖性 如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性.数据依赖分下列三种类型: 名称 代码示例 说明 写后读 a = 1;b = a; 写一个变量之 ...
- Redis-分片
分片(partitioning)就是将你的数据拆分到多个 Redis 实例的过程,这样每个实例将只包含所有键的子集.本文第一部分将向你介绍分片的概念,第二部分将向你展示 Redis 分片的可选方案. ...
- zDialog 可拖拽弹出层
zDialog弹出框: 代替window.open.window.alert.window.confirm:提供良好的用户体验: 水晶质感,设计细腻,外观漂亮: 兼容ie6/7/8.firefox2/ ...