Android AIDL进阶
此篇继续详解Android AIDL知识
1.AIDL简介
AIDL:Android Interface Definition Language,即Android接口定义语言。
Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。
为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。
2.建立AIDL服务的步骤
(1)在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同。
(2)如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)。
(3)建立一个服务类(Service的子类)。
(4)实现由aidl文件生成的Java接口。
(5)在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。
实现AIDL接口的说明:
3.1.5.aidl 接口代码举例
package com.example.eventbusdemo.aidl.server;
interface MyAIDL{
boolean issuccess();
String getName();
String getAge();
}
3.2.自动生成的aidl文件代码如下
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: C:\\Users\\Administrator\\newworkspace\\EventBusDemo\\src\\com\\example\\eventbusdemo\\aidl\\server\\MyAIDL.aidl
*/
package com.example.eventbusdemo.aidl.server;
public interface MyAIDL extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.example.eventbusdemo.aidl.server.MyAIDL
{
private static final java.lang.String DESCRIPTOR = "com.example.eventbusdemo.aidl.server.MyAIDL";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.eventbusdemo.aidl.server.MyAIDL interface,
* generating a proxy if needed.
*/
public static com.example.eventbusdemo.aidl.server.MyAIDL asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.eventbusdemo.aidl.server.MyAIDL))) {
return ((com.example.eventbusdemo.aidl.server.MyAIDL)iin);
}
return new com.example.eventbusdemo.aidl.server.MyAIDL.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_issuccess:
{
data.enforceInterface(DESCRIPTOR);
boolean _result = this.issuccess();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
case TRANSACTION_getName:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _result = this.getName();
reply.writeNoException();
reply.writeString(_result);
return true;
}
case TRANSACTION_getAge:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _result = this.getAge();
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.eventbusdemo.aidl.server.MyAIDL
{
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;
}
@Override public boolean issuccess() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_issuccess, _data, _reply, 0);
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public java.lang.String getName() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public java.lang.String getAge() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getAge, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_issuccess = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_getAge = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
}
public boolean issuccess() throws android.os.RemoteException;
public java.lang.String getName() throws android.os.RemoteException;
public java.lang.String getAge() throws android.os.RemoteException;
}
自动生成的java代码比较多 也比较乱 不过 我们仔细看看主要的几个
Proxy,Stub和asInterface。
3.2.1.Proxy(类)实现了刚刚定义的aidl中的接口
private static class Proxy implements com.example.eventbusdemo.aidl.server.MyAIDL
{
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;
}
@Override public boolean issuccess() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_issuccess, _data, _reply, 0);
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public java.lang.String getName() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public java.lang.String getAge() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getAge, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
即此类实现了刚刚定义的aidl接口(interface MyAIDL) 重写实现了其中定义好的三个方法
boolean issuccess();
String getName();
String getAge();
3.2.Stub(抽象类)
public static abstract class Stub extends android.os.Binder implements com.example.eventbusdemo.aidl.server.MyAIDL{
}
详细代码
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.example.eventbusdemo.aidl.server.MyAIDL
{
private static final java.lang.String DESCRIPTOR = "com.example.eventbusdemo.aidl.server.MyAIDL";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.eventbusdemo.aidl.server.MyAIDL interface,
* generating a proxy if needed.
*/
public static com.example.eventbusdemo.aidl.server.MyAIDL asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.eventbusdemo.aidl.server.MyAIDL))) {
return ((com.example.eventbusdemo.aidl.server.MyAIDL)iin);
}
return new com.example.eventbusdemo.aidl.server.MyAIDL.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_issuccess:
{
data.enforceInterface(DESCRIPTOR);
boolean _result = this.issuccess();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
case TRANSACTION_getName:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _result = this.getName();
reply.writeNoException();
reply.writeString(_result);
return true;
}
case TRANSACTION_getAge:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _result = this.getAge();
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.eventbusdemo.aidl.server.MyAIDL
{
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;
}
@Override public boolean issuccess() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_issuccess, _data, _reply, 0);
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public java.lang.String getName() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public java.lang.String getAge() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getAge, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_issuccess = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_getAge = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
}
3.2.3.asInterface(方法)
public static com.example.eventbusdemo.aidl.server.MyAIDL asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.eventbusdemo.aidl.server.MyAIDL))) {
return ((com.example.eventbusdemo.aidl.server.MyAIDL)iin);
}
return new com.example.eventbusdemo.aidl.server.MyAIDL.Stub.Proxy(obj);
}
Proxy 这里是private权限的,外部是无法访问的,但这里是 Android 有意为之,抛出了 asInterface 方法,这样避免了对 Proxy可能的修改。即此方法公外部访问。
3.2.4总结
Proxy 是写入参数,读取值;Stub 是读取参数,写入值。正好是一对,即Proxy 和 Stub 操作的是一份数据。
3.3.创建服务
public class MyService extends Service{
@Override
public IBinder onBind(Intent arg0) {
return stub;
}
MyAIDL.Stub stub=new MyAIDL.Stub(){
@Override
public boolean issuccess() throws RemoteException {
return false;
}
@Override
public String getName() throws RemoteException {
return "张三";
}
@Override
public String getAge() throws RemoteException {
return "28";
}
};
}
3.4.java代码中使用
package com.example.eventbusdemo.aidl.client;
import android.app.Activity;
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.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.example.eventbusdemo.R;
import com.example.eventbusdemo.aidl.server.MyAIDL;
import com.example.eventbusdemo.aidl.server.MyService;
public class AIDLActivity extends Activity{
private Button btn;
private MyAIDL myService=null;
private ServiceConnection serviceConnection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aidl);
bindService();//绑定服务
btn=(Button) findViewById(R.id.activity_aidlbtn);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if(null!=myService){
try {
String name=myService.getName();
String age=myService.getAge();
boolean issuccess=myService.issuccess();
Log.d("AIDLActivity", "name----:"+name);
Log.d("AIDLActivity", "age----:"+age);
Log.d("AIDLActivity", "issuccess----:"+issuccess);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
}
//绑定服务
public void bindService(){
serviceConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
myService=MyAIDL.Stub.asInterface(arg1);
Log.d("AIDLActivity", "onServiceConnected!!!!!!!!!!!!");
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
Log.d("AIDLActivity", "onServiceDisconnected!!!!!!!!!!!!");
}
};
//可有可无
// bindService(new Intent("com.example.eventbusdemo.aidl.server.MyAIDL"), serviceConnection, Context.BIND_AUTO_CREATE);
Intent intent=new Intent(AIDLActivity.this,MyService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
}
3.5.结果