Android AIDL 实例
为使应用程序之间能够彼此通信,Android提供了IPC (Inter Process Communication,进程间通信)的一种独特实现: AIDL (Android Interface Definition Language, Android接口定义语言)。
简单来说,AIDL 就是定义一个接口,客户端(调用端)通过 bindService 来与远程服务端建立一个连接,在该连接建立时会将返回一个 IBinder 对象,该对象是服务端 Binder 的 BinderProxy。在建立连接时,客户端通过 asInterface 函数将该 BinderProxy 对象包装成本地的 Proxy,并赋值给Proxy类的mRemote 字段,本地通过 mRemote 即可调用远程方法。
1、创建 .aidl 文件
首先打开 Android Studio,new 一个 AIDL file。具体代码如下 :
interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
basicTypes 方法事接口自带的,不过可以知道,在 aidl 中只能使用这些基本类型参数:int, long, boolean, float,double , String ;
除了 basicTypes 方法之外,我们也可以添加自己的方法。因此,可以删除 basicTypes 方法,添加自己的方法。
二、生成 .java 文件
添加完方法之后,选中 .aidl 文件,在弹出的菜单中选择 Synchronize LocalAIDLS... Service.java,就会会自动帮你生成对应的 java 代码。
格式化代码之后,如下所示:
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: /Users/shenjiaqi/Documents/sjq/booksource/chapter6/DatabaseTest/app/src/main/aidl/com/example/databasetest/IMyAidlInterface.aidl
*/
package com.example.databasetest; public interface IMyAidlInterface extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.example.databasetest.IMyAidlInterface {
private static final java.lang.String DESCRIPTOR = "com.example.databasetest.IMyAidlInterface"; /**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
} /**
* Cast an IBinder object into an com.example.databasetest.IMyAidlInterface interface,
* generating a proxy if needed.
*/
public static com.example.databasetest.IMyAidlInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.example.databasetest.IMyAidlInterface))) {
return ((com.example.databasetest.IMyAidlInterface) iin);
}
return new com.example.databasetest.IMyAidlInterface.Stub.Proxy(obj);
} @Override
public android.os.IBinder asBinder() {
return this;
} @Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_basicTypes: {
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
boolean _arg2;
_arg2 = (0 != data.readInt());
float _arg3;
_arg3 = data.readFloat();
double _arg4;
_arg4 = data.readDouble();
java.lang.String _arg5;
_arg5 = data.readString();
this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
} private static class Proxy implements com.example.databasetest.IMyAidlInterface {
private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) {
mRemote = remote;
} @Override
public android.os.IBinder asBinder() {
return mRemote;
} public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
} /**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean) ? (1) : (0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);
mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
} static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
} /**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
}
如果,你需要修改 .aidl 文件,那么修改之后,选择 build -> make project 即可,会重新生成对应的java文件。
其中的 proxy 是一个静态类,实现了这个 IMyAidlInterface 接口。Stub 继承了 Binder 同时实现了 IMyAidlInterface 接口。
三、传输复杂数据
如果,需要传递复杂数据,那么就需要实现 Parcelable 接口,可序列化:
public class Info implements Parcelable {
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Info() {
}
public Info(Parcel in) {
content = in.readString();
}
public static final Creator<Info> CREATOR = new Creator<Info>() {
@Override
public Info createFromParcel(Parcel in) {
return new Info(in);
}
@Override
public Info[] newArray(int size) {
return new Info[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(content);
}
/**
* 参数是一个Parcel,用它来存储与传输数据
*
* @param dest
*/
public void readFromParcel(Parcel dest) {
//注意,此处的读值顺序应当是和writeToParcel()方法中一致的
content = dest.readString();
}
//方便打印数据
@Override
public String toString() {
return "content : " + content;
}
}
与此同时,也要建一个 info.aidl 文件,表明数据也是可以传递的。
package com.viii.aidlclient; //注意:Info.Info.java的包名应当是一样的 //这个文件的作用是引入了一个序列化对象 Info 供其他的AIDL文件使用 //注意parcelable是小写
parcelable Info;
这样就可以使用 info 对象了。 不用在受前面的基本类型变量所控制。
四、建立 service
接下去,新建一个Service负责接收消息,并在AndroidManifest.xml里面注册 Service:
public class MyService extends Service {
private static final String TAG = "MyService";
// private MyBinder mMyBinder = new MyBinder();
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind: ");
// 应该返回 mBinder
return null;
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate: ");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
// 这里就是服务端的实现
private final IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
// 具体实现过程
}
};
}
这时候,可以 basicTypes 方法添加具体函数代码,实现你想要的功能。
当我们在本地获取到代理后之后,调用 basicTypes 就会触发服务端的调用。
5、获取服务
接下去在mainactivity中进行绑定。
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private IMyAidlInterface mService;
private boolean mIsBound;
private AdditionServiceConnection mServiceConnection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
doBindService() ;
}/**
* bind service
*/
private void doBindService() {
mServiceConnection = new AdditionServiceConnection();
Intent intent = new Intent(this, MyService.class);
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
}
/**
* unbind service
*/
private void doUnbindService() {
if (mIsBound) {
unbindService(mServiceConnection);
mServiceConnection = null;
mIsBound = false;
}
}
/**
* ServiceConection
*/
class AdditionServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 连接的时候获取本地代理,这样我们就可以调用 service 中的方法了。
mService = IMyAidlInterface.Stub.asInterface((IBinder) service);
mIsBound = true;
try {
//设置死亡代理
service.linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
Log.d(TAG, "onServiceConnected: ");
}
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
mIsBound = false;
Log.d(TAG, "onServiceDisconnected: ");
}
}
/**
* 监听Binder是否死亡
*/
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
if (mService == null) {
return;
}
mService.asBinder().unlinkToDeath(mDeathRecipient, 0);
mService = null;
//重新绑定
doBindService();
}
};
@Override
protected void onStop() {
super.onStop();
doUnbindService();
}
}
将远程服务的 binder 拿到之后,我们就可以调用相关方法实现自己的功能呢。
到这里,一个 AIDL 就被我们实现了。
具体实例代码见 :https://download.csdn.net/download/szengjiaqi/10613236
Android AIDL 实例的更多相关文章
- Android AIDL实例解析
AIDL这项技术在我们的开发中一般来说并不是很常用,虽然自己也使用新浪微博的SSO登录,其原理就是使用AIDL,但是自己一直没有动手完整的写过AIDL的例子,所以就有了这篇简单的文章. AIDL(An ...
- AIDL实例
转载声明:原文转自:http://www.cnblogs.com/xiezie/p/5658372.html 什么是AIDL Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进 ...
- android AIDL 语言用法
跨进程通信可以用AIDL语言 这里讲述下如何使用AIDL语言进行跨进程通信 文章参考 <设计模式>一书 demo结构参考 主要的文件类有:IBankAidl.aidl java文件:Aid ...
- AIDL/IPC Android AIDL/IPC 进程通信机制——超具体解说及使用方法案例剖析(播放器)
首先引申下AIDL.什么是AIDL呢?IPC? ------ Designing a Remote Interface Using AIDL 通常情况下,我们在同一进程内会使用Binder.Broad ...
- (转载)你真的理解Android AIDL中的in,out,inout么?
前言 这其实是一个很小的知识点,大部分人在使用AIDL的过程中也基本没有因为这个出现过错误,正因为它小,所以在大部分的网上关于AIDL的文章中,它都被忽视了——或者并没有,但所占篇幅甚小,且基本上都是 ...
- Android AIDL使用详解_Android IPC 机制详解
一.概述 AIDL 意思即 Android Interface Definition Language,翻译过来就是Android接口定义语言,是用于定义服务器和客户端通信接口的一种描述语言,可以拿来 ...
- Android HTTP实例 使用GET方法和POST方法发送请求
Android HTTP实例 使用GET方法和POST方法发送请求 Web程序:使用GET和POST方法发送请求 首先利用MyEclispe+Tomcat写好一个Web程序,实现的功能就是提交用户信息 ...
- Android HTTP实例 发送请求和接收响应
Android HTTP实例 发送请求和接收响应 Android Http连接 实例:发送请求和接收响应 添加权限 首先要在manifest中加上访问网络的权限: <manifest ... & ...
- Android图像处理实例教程
Android图像处理实例教程 原始出处 http://vaero.blog.51cto.com/4350852/856750
随机推荐
- fromdata上传多个文件
function upload_single_file(value){ if(value==''){ layer.msg('请添加文件',{time:1500}) }else{ var formDat ...
- 1004 Counting Leaves 对于树的存储方式的回顾
一种新的不使用左右子树递归进行树高计算的方法,使用层次遍历 树的存储方式: 1.本题提供的一种思路: 使用(邻接表的思想)二维数组(vector[n])表示树,横坐标表示 父节点,每一行表示孩子. 能 ...
- mongoDB根据_id进行查询
var ObjectID = require('mongodb').ObjectID; whereStr = {_id:ObjectID(req.body._id)}
- Day08 (黑客成长日记) 命名空间和作用域
Day08:命名空间和作用域: 1.命名空间: (1)内置命名空间(python解释器): 就是python解释器一旦启动就可以使用的名字储存在内置命名空间中: eg: len() print() a ...
- 20155205 郝博雅 Exp5 MSF基础应用
20155205 郝博雅 Exp5 MSF基础应用 一.实验目标 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 1.一个主动攻击实践,如ms08_0 ...
- SSRF
SSRF 关于SSRF SSRF(Server-Side Request Forgery:服务器端请求伪造),攻击者通过伪造服务器端发起的请求,获取客户端所不能得到的数据.一般情况下,SSRF攻击的目 ...
- Appium之xpath定位元素
原文:http://www.cnblogs.com/cnkemi/p/9180525.html appium也是以webdriver为基的,对于元素的定位也基本一致,只是增加一些更适合移动平台的独特方 ...
- 入门SQL操作
结构化查询语言:SQL:Structured Query Language 分类: 针对的操作对象不同.分成不同的语言: 1.数据操作(管理)语言( DML) 查询:获得数据.(DQL) 管理:增加. ...
- 关于Podfile,某个第三方指定源
项目中有个指定了源,摸索好久Podfile编写方式,网上都没有 pod 'SDK名字', :source => '指定源' 其他的直接按原来的就可以了
- 浅析http缓存
1.什么是缓存 将服务器上的静态资源,保存在本地,当发送web请求的时候,如果本地有“已缓存”的静态资源,则从使用本地保存的静态资源,而不是从源原服务器再次请求. 2.缓存的优点 缓存减少冗余的数据传 ...