我们知道一般的Service写法为:
1.实现一个子类继承自Service
2.复写一个onBind事件,里面返回一个我们自定义的Binder子类对象
3.在Binder子类中我们实现其他程序调用的相关接口
其实AIDL服务端的实现也是按照这一流程走的:
首先我们看一下服务端的所有的code:
package com.qs.aidldemo;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;
import android.widget.Toast;
//自己实现的AIDL方法:
//技术博客考:http://blog.csdn.net/hitlion2008/article/details/9824009
public class MyAIDLService extends Service {
private Handler mHandler = new Handler();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private MyPrinterInterfaceStub mBinder = new MyPrinterInterfaceStub() {
@Override
public void print(String msg) throws RemoteException {
MyAIDLService.this.print(msg);
}
@Override
public String add(String a, String b) throws RemoteException {
return MyAIDLService.this.add(a,b);
}
};
public void print(String msg)
{
try{
System.out.println("Preparing printer...");
Thread.sleep(1000);
System.out.println("Connecting printer...");
Thread.sleep(1000);
System.out.println("Printing.... " + msg);
Thread.sleep(1000);
System.out.println( "Done");
}catch(Exception e)
{
}
mHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(MyAIDLService.this, "MyService printing is donw", 0).show();
}
});
}
//这个是服务器实现的add函数的功能
public String add(String a,String b)
{
int sum =0;
try{
System.out.println("a="+a+" b="+b);
sum = Integer.valueOf(a)+Integer.valueOf(b);
System.out.println("Printing.... " + sum);
}catch(Exception e)
{
}
return String.valueOf(sum);
}
//定义我们需要实现的两个接口函数
public interface MyPrinterInterface extends IInterface {
public void print(String msg) throws android.os.RemoteException;
public String add(String a,String b) throws android.os.RemoteException;
}
//这个又是Binder的封装类 也就是我们私有的Binder类的实现
abstract class MyPrinterInterfaceStub extends Binder implements MyPrinterInterface{
private static final String DESCRIPTOR="MyPrinterInterface";
private static final String TAG="MyPrinterInterfaceStub";
public MyPrinterInterfaceStub(){
attachInterface(this, DESCRIPTOR);
}
//这个函数似乎就没有被调用过
@Override
public IBinder asBinder() {
System.out.println("Server asBinder");
return this;
}
//data表示客户端传送过来的值 code表示的是调用的函数,我们发现客户端调用的函数是:mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
//这里和我们的这个函数传残一模一样 因此我们服务器的code和客户端的code是需要一一对应的
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
System.out.println("onTransact,code is "+code);
switch(code)
{
case INTERFACE_TRANSACTION:
System.out.println("MyPrinterInterfaceStub onTransact,code is "+code+" ,when this happens");
reply.writeString(DESCRIPTOR);
return true;
case TRANSACTION_print:
data.enforceInterface(DESCRIPTOR);
String _arg0;
_arg0 = data.readString();
System.out.println("MyPrinterInterfaceStub ontransact, arg is "+_arg0+" , when this happened?");
this.print(_arg0);
reply.writeNoException();
return true;
case TRANSACTION_add:
data.enforceInterface(DESCRIPTOR);
String _arg2;
_arg2 = data.readString();
String _arg3;
_arg3= data.readString();
String _result = this.add(_arg2, _arg3);
reply.writeNoException();
reply.writeString(_result);
return true;
}
return super.onTransact(code, data, reply, flags);
}
static final int TRANSACTION_print = (IBinder.FIRST_CALL_TRANSACTION+0);
static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION+1);
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("start myAidl Service------");
}
}
上面我们首先看到了依然是Service onBind 并且mBinder 是new的带有两个接口函数对象,因此我们肯定MyPrinterInterfaceStub一定是继承自Binder
private MyPrinterInterfaceStub mBinder = new MyPrinterInterfaceStub() {
@Override
public void print(String msg) throws RemoteException {
MyAIDLService.this.print(msg);
}
@Override
public String add(String a, String b) throws RemoteException {
return MyAIDLService.this.add(a,b);
}
};
然后我们再看MyPrinterInterfaceStub这个类的实现:
abstract class MyPrinterInterfaceStub extends Binder implements MyPrinterInterface{
public MyPrinterInterfaceStub(){
attachInterface(this, DESCRIPTOR);
}
}
可以看到我们确实是实现了一个接口,这个类是一个抽象类,因此接口实现是在刚才我们看到的new出这个对象的时候实现的两个接口函数,并且我们还能看到我们在上一节讲到的为了关联远程连接服务器的client,我们通过DESCRIPTOR关联两者,因此我们的构造函数中调用了attachInterface(this, DESCRIPTOR); 为了能让client明确的指明需要调用服务器的那个接口函数,我们仍然去复写实现了一个这样的函数:
//data表示客户端传送过来的值 code表示的是调用的函数,我们发现客户端调用的函数是:mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
//这里和我们的这个函数传残一模一样 因此我们服务器的code和客户端的code是需要一一对应的
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
System.out.println("onTransact,code is "+code);
switch(code)
{
case INTERFACE_TRANSACTION:
System.out.println("MyPrinterInterfaceStub onTransact,code is "+code+" ,when this happens");
reply.writeString(DESCRIPTOR);
return true;
case TRANSACTION_print:
data.enforceInterface(DESCRIPTOR);
String _arg0;
_arg0 = data.readString();
System.out.println("MyPrinterInterfaceStub ontransact, arg is "+_arg0+" , when this happened?");
this.print(_arg0);
reply.writeNoException();
return true;
case TRANSACTION_add:
data.enforceInterface(DESCRIPTOR);
String _arg2;
_arg2 = data.readString();
String _arg3;
_arg3= data.readString();
String _result = this.add(_arg2, _arg3);
reply.writeNoException();
reply.writeString(_result);
return true;
}
return super.onTransact(code, data, reply, flags);
}
static final int TRANSACTION_print = (IBinder.FIRST_CALL_TRANSACTION+0);
static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION+1);
同样的是由code去区分调用哪个函数,最后我们通过Service中的onBind方法返回一个Binder对象,这样,当client拿到我们服务器的Binder对象的时候就可以调用我们服务器提供出去的两个方法了!这里我们是不是感觉到了服务器的code,这样写总感觉有些蛋疼,虽然Eclipse给我们生成的Service端的函数貌似也是这样写的,先定义出了接口,然后让Binder子类继承接口,然后在new的时候实现接口,其实这样写貌似没什么必要(我们自己定义的没有不对外公开接口,因此没必要引入这个interface增加代码的封装性),我们完全可以直接的不要这个接口的定义与实现!
package com.qs.aidldemo;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;
import android.widget.Toast;
//自己实现的AIDL方法:
//技术博客参考:http://blog.csdn.net/hitlion2008/article/details/9824009
public class MyAIDLService extends Service {
private Handler mHandler = new Handler();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private MyPrinterInterfaceStub mBinder = new MyPrinterInterfaceStub();
public void print(String msg)
{
try{
System.out.println("Preparing printer...");
Thread.sleep(1000);
System.out.println("Connecting printer...");
Thread.sleep(1000);
System.out.println("Printing.... " + msg);
Thread.sleep(1000);
System.out.println( "Done");
}catch(Exception e)
{
}
mHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(MyAIDLService.this, "MyService printing is done", 0).show();
}
});
}
//这个是服务器实现的add函数的功能
public String add(String a,String b)
{
int sum =0;
try{
System.out.println("a="+a+" b="+b);
sum = Integer.valueOf(a)+Integer.valueOf(b);
System.out.println("Printing.... " + sum);
}catch(Exception e)
{
}
return String.valueOf(sum);
}
//这个又是Binder的封装类 也就是我们私有的Binder类的实现
class MyPrinterInterfaceStub extends Binder implements IInterface{
private static final String DESCRIPTOR="MyPrinterInterface";
private static final String TAG="MyPrinterInterfaceStub";
public MyPrinterInterfaceStub(){
attachInterface(this, DESCRIPTOR);
}
//这个函数似乎就没有被调用过
@Override
public IBinder asBinder() {
System.out.println("Server asBinder");
return this;
}
//data表示客户端传送过来的值 code表示的是调用的函数,我们发现客户端调用的函数是:mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
//这里和我们的这个函数传残一模一样 因此我们服务器的code和客户端的code是需要一一对应的
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
System.out.println("onTransact,code is "+code);
switch(code)
{
case INTERFACE_TRANSACTION:
System.out.println("MyPrinterInterfaceStub onTransact,code is "+code+" ,when this happens");
reply.writeString(DESCRIPTOR);
return true;
case TRANSACTION_print:
data.enforceInterface(DESCRIPTOR);
String _arg0;
_arg0 = data.readString();
System.out.println("MyPrinterInterfaceStub ontransact, arg is "+_arg0+" , when this happened?");
print(_arg0);
reply.writeNoException();
return true;
case TRANSACTION_add:
data.enforceInterface(DESCRIPTOR);
String _arg2;
_arg2 = data.readString();
String _arg3;
_arg3= data.readString();
String _result = add(_arg2, _arg3);
reply.writeNoException();
reply.writeString(_result);
return true;
}
return super.onTransact(code, data, reply, flags);
}
static final int TRANSACTION_print = (IBinder.FIRST_CALL_TRANSACTION+0);
static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION+1);
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("start myAidl Service------");
}
}
这样我们就直接省略了interface的定义以及实现过程 。下面我们来看一下客户端的实现:
package com.qs.aidlclientdemo;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
public interface MyPrinterInterface extends android.os.IInterface{
//这两个是我们自己需要实现的函数,而asBinder函数是android.os.IInterface中需要实现的接口
public void print(String msg) throws android.os.RemoteException;
public String add(String a ,String b) throws android.os.RemoteException;
//创建一个抽象类去封装我们的Binder
public abstract class Stub extends Binder implements MyPrinterInterface
{
private static final String DESCRIPTOR="MyPrinterInterface";//这个描述符的定义必须与服务器的一致,不然无法得到想要的结果
private static final String TAG="MyPrinterInterface.Stub";
public Stub(){
attachInterface(this, DESCRIPTOR);
}
public static MyPrinterInterface asInterface(IBinder obj)
{
if(obj==null)return null;
System.out.println("we are talking to a remote one, we must use a proxy object to wrapper binder");
return new Stub.Proxy(obj); //Proxy对象是MyPrinterInterface子类
}
static final int TRANSACTION_print =(IBinder.FIRST_CALL_TRANSACTION+0);
static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION+1);
//Stub 中的抽象的函数在这里面都一一实现了
//这里面会把我们客户端发送的数据传输给服务器,然后服务器会把结果回填到我们的reply 通过函数mRemote.transact(Stub.TRANSACTION_print, _data, _reply, 0);
//同时我们发现我们创建的里面的IBinder对象就是当客户端脸上之后服务器返回给客户端的IBinder对象,因此我们里面的mRemote操作的是服务器的函数
//我们client调用的函数其实都是通过发送数据到服务器,然后通过服务器的binder返回数据给我们完成一个进程间通讯交互
private static class Proxy implements MyPrinterInterface
{
private IBinder mRemote;
Proxy(IBinder remote)
{
mRemote = remote;
}
@Override
public IBinder asBinder() {
return mRemote;
}
@Override
public void print(String msg) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply =Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(msg);
mRemote.transact(Stub.TRANSACTION_print, _data, _reply, 0);//这里实际上是调用服务器的onTransact函数
} catch (Exception e) {
}finally{
_data.recycle();
_reply.recycle();
}
}
@Override
public String add(String a, String b) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply =Parcel.obtain();
String _result = null;
try {
_data.writeInterfaceToken(DESCRIPTOR);
//写入我们要传入的两个值
_data.writeString(a);
_data.writeString(b);
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
//这里特别注意,如果我们需要服务器的返回值,那么下面必须这样写
_reply.readException();//这个必须得带上不然没有值
_result = _reply.readString();//这个是服务器返回给我们的值
System.out.println("service client result ="+_result);
} catch (Exception e) {
}finally{
_data.recycle();
_reply.recycle();
}
return _result;//最后返回我们从服务器上面拿到的值
}
}
}
}
首先是一个大的interface 提供client调用的两个接口,这个对应服务器提供出来的两个API
public interface MyPrinterInterface extends android.os.IInterface{
//这两个是我们自己需要实现的函数,而asBinder函数是android.os.IInterface中需要实现的接口
public void print(String msg) throws android.os.RemoteException;
public String add(String a ,String b) throws android.os.RemoteException;
然后定义了一个Binder的抽象类实现这个接口并且里面有一个asInterface函数返回的是一个相当于服务器的代理
对象
private static class Proxy implements MyPrinterInterface
{
private IBinder mRemote;
Proxy(IBinder remote)
{
mRemote = remote;
}
@Override
public IBinder asBinder() {
return mRemote;
}
@Override
public void print(String msg) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply =Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(msg);
mRemote.transact(Stub.TRANSACTION_print, _data, _reply, 0);//这里实际上是调用服务器的onTransact函数
} catch (Exception e) {
}finally{
_data.recycle();
_reply.recycle();
}
}
@Override
public String add(String a, String b) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply =Parcel.obtain();
String _result = null;
try {
_data.writeInterfaceToken(DESCRIPTOR);
//写入我们要传入的两个值
_data.writeString(a);
_data.writeString(b);
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
//这里特别注意,如果我们需要服务器的返回值,那么下面必须这样写
_reply.readException();//这个必须得带上不然没有值
_result = _reply.readString();//这个是服务器返回给我们的值
System.out.println("service client result ="+_result);
} catch (Exception e) {
}finally{
_data.recycle();
_reply.recycle();
}
return _result;//最后返回我们从服务器上面拿到的值
}
}
很明显看到代理类中我们实现了怎样通过服务器的binder对象来调用服务器的api去做相关操作:
private IBinder mRemote; 这个是我们调用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
person = IPerson.Stub.asInterface(service);
}
函数之后传进来的远程的binder对象,我们通过这个对象就可以直接调用服务器给我们提供的方法:
mRemote.transact(Stub.TRANSACTION_print, _data, _reply, 0);//这里实际上是调用服务器的onTransact函数
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
同理,里面想要调用什么的时候传入的第一个参数就是我们服务器端的switch中的code
也就是:
static final int TRANSACTION_print =(IBinder.FIRST_CALL_TRANSACTION+0);
static final int TRANSACTION_add = (IBinder.FIRST_CALL_TRANSACTION+1);
_data是client传入的数据,_reply是我们服务器处理的结果返回的
因此这个客户端中的code调用我们也做完了:
最后贴一下客户端中MainActivity调用的code:
package com.qs.aidlclientdemo;
import java.util.Date;
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.view.View;
import android.widget.Toast;
import com.qs.aidl.IPerson;
public class MainActivity extends Activity {
private IPerson person;
private MyPrinterInterface myInterface;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
person = IPerson.Stub.asInterface(service);
}
};
private ServiceConnection myconn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("myconn connected");
myInterface = MyPrinterInterface.Stub.asInterface(service);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//首先要拉起服务器的service程序然后才能调用远程服务器提供的api
Intent intent = new Intent("android.intent.action.AIDLService");
String time = new Date().toLocaleString();
intent.putExtra("time", time);//这里我们还可以给服务器发送数据,在服务器的onBind函数中它的参数接收这个数据
bindService(intent, conn, Context.BIND_AUTO_CREATE);
doBindService();
}
public void greet(View v)
{
try {
Toast.makeText(this,person.greet("qiusen "),0).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void add(View v)
{
try {
Toast.makeText(this,person.add("1","2"),0).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void printmsg(View v)
{
try {
if(myInterface==null){
System.out.println("myInterface is not success");
return;
}
myInterface.print("this is a client msg");
System.out.println("MyClient = "+myInterface.add("1", "4"));
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if(conn!=null)
unbindService(conn);
if(myconn!=null)
unbindService(myconn);
}
private void doBindService()
{
Intent intent = new Intent("com.qs.MyAIDLService");
bindService(intent, myconn, Context.BIND_AUTO_CREATE);
}
}
上面的code是系统实现和自定义实现的混合,code的demo:
代码下载