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服务的步骤

建立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接口的说明:

 

(1)AIDL接口只支持方法,不能声明静态成员;
(2)不会有返回给调用方的异常。

 

 

3.具体实现demo(IDE Eclipse)
 
3.1.创建aidl文件
 
3.1.1.选择你要建立的aidl文件所在的包
 
3.1.2.然后File->New->File,弹出对话框 输入XXX.aidl(必须以aidl结尾)
 
3.1.3.最后,finish即可。
3.1.4.然后在aidl文件中给出正确的aidl接口代码,保存。系统会自动生成其实现类源文件:XXX.java(在gen下)
此时说明第一步创建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.结果

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值