首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网络技术 > 网络基础 >

aidl过程间的通信

2012-07-16 
aidl进程间的通信欢迎阅读本文,你能关注本文,你知道你需要进程间通信、需要AIDL(以及Binder),那么可以默认

aidl进程间的通信
   欢迎阅读本文,你能关注本文,你知道你需要进程间通信、需要AIDL(以及Binder),那么可以默认你对这些概念已经有了一些了解,你(大致)知道它们是什么,它们有什么用,所以为了节约大家的眼力和时间,在此我不复制粘贴网上泛滥的博客或者翻译冗长的android文档。

      关于AIDL的介绍在文档:docs/guide/developing/tools/aidl.html

      关于IBinder的介绍在文档:docs/reference/android/os/IBinder.html

      以及Binder:docs/reference/android/os/Binder.html

      在后文中,我将以我自己的理解向你介绍相关的概念。以我目前粗浅的经验,应用程序使用AIDL的地方,几乎都和Service有关,所以你也需要知道一些关于Service的知识。日后得闲我也会继续写一些关于Service的贴。

      本文将以一个例子来和你分享使用AIDL的基础技能,这个例子里有:

1、一个类mAIDLActivity,继承Activity。里面有三个按钮,text分别为StartService,StopService,CallbackTest。

2、一个类mAIDLService,继承Service。为了充分展示ADIL的功能,它做以下工作:当用户点击CallbackTest按钮时,从mAIDLActivity调用mAIDLService中的Stub 对象的一个方法invokCallBack(),而这个方法又会调用mAIDLActivity中Stub 对象的一个方法performAction(),这个方法在屏幕上显示一个toast。没什么意义,只是展示一下AIDL如何使用。

3、两个AIDL文件:forService.aidl和forActivity.aidl。对应名字,在Service和Activity中分别有对象需要用到它们定义的接口。

4、相关XML文件,略过。关于manifest中Service的语法,见docs/guide/topics/manifest/service-element.html。你也可以简单地在<application></application>中加入

     <service android:name=".mAIDLService" android:process=":remote"> </service>

开发环境为Eclipse。

拣重要的先说,来看看aidl文件的内容:

文件:forActivity.aidl

[java] view plaincopyprint?
01.package com.styleflying.AIDL; 
02.interface forActivity { 
03.    void performAction(); 
04.    } 
package com.styleflying.AIDL;
interface forActivity {
void performAction();
}  

文件:forService.aidl

[java] view plaincopyprint?
01.package com.styleflying.AIDL; 
02.import com.styleflying.AIDL.forActivity; 
03.interface forService { 
04.    void registerTestCall(forActivity cb); 
05.    void invokCallBack(); 
06.} 
package com.styleflying.AIDL;
import com.styleflying.AIDL.forActivity;
interface forService {
void registerTestCall(forActivity cb);
void invokCallBack();
}  

这两个文件和Java文件放置的地方一样,看包名。

在Eclipse中它们将被自动编译为forActivity.java和forService.java,它们存放在gen目录下。为了方便手头无法演练的读者,代码贴上,不用细看。

文件forActivity.java:

[java] view plaincopyprint?
01./*
02. * This file is auto-generated.  DO NOT MODIFY.
03. * Original file: D://workspace//AIDLTest//src//com//styleflying//AIDL//forActivity.aidl
04. */ 
05.package com.styleflying.AIDL; 
06.import java.lang.String; 
07.import android.os.RemoteException; 
08.import android.os.IBinder; 
09.import android.os.IInterface; 
10.import android.os.Binder; 
11.import android.os.Parcel; 
12.public interface forActivity extends android.os.IInterface 
13.{ 
14./** Local-side IPC implementation stub class. */ 
15.public static abstract class Stub extends android.os.Binder implements com.styleflying.AIDL.forActivity 
16.{ 
17.private static final java.lang.String DESCRIPTOR = "com.styleflying.AIDL.forActivity"; 
18./** Construct the stub at attach it to the interface. */ 
19.public Stub() 
20.{ 
21.this.attachInterface(this, DESCRIPTOR); 
22.} 
23./**
24. * Cast an IBinder object into an forActivity interface,
25. * generating a proxy if needed.
26. */ 
27.public static com.styleflying.AIDL.forActivity asInterface(android.os.IBinder obj) 
28.{ 
29.if ((obj==null)) { 
30.return null; 
31.} 
32.android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR); 
33.if (((iin!=null)&&(iin instanceof com.styleflying.AIDL.forActivity))) { 
34.return ((com.styleflying.AIDL.forActivity)iin); 
35.} 
36.return new com.styleflying.AIDL.forActivity.Stub.Proxy(obj); 
37.} 
38.public android.os.IBinder asBinder() 
39.{ 
40.return this; 
41.} 
42.@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException 
43.{ 
44.switch (code) 
45.{ 
46.case INTERFACE_TRANSACTION: 
47.{ 
48.reply.writeString(DESCRIPTOR); 
49.return true; 
50.} 
51.case TRANSACTION_performAction: 
52.{ 
53.data.enforceInterface(DESCRIPTOR); 
54.this.performAction(); 
55.reply.writeNoException(); 
56.return true; 
57.} 
58.} 
59.return super.onTransact(code, data, reply, flags); 
60.} 
61.private static class Proxy implements com.styleflying.AIDL.forActivity 
62.{ 
63.private android.os.IBinder mRemote; 
64.Proxy(android.os.IBinder remote) 
65.{ 
66.mRemote = remote; 
67.} 
68.public android.os.IBinder asBinder() 
69.{ 
70.return mRemote; 
71.} 
72.public java.lang.String getInterfaceDescriptor() 
73.{ 
74.return DESCRIPTOR; 
75.} 
76.public void performAction() throws android.os.RemoteException 
77.{ 
78.android.os.Parcel _data = android.os.Parcel.obtain(); 
79.android.os.Parcel _reply = android.os.Parcel.obtain(); 
80.try { 
81._data.writeInterfaceToken(DESCRIPTOR); 
82.mRemote.transact(Stub.TRANSACTION_performAction, _data, _reply, 0); 
83._reply.readException(); 
84.} 
85.finally { 
86._reply.recycle(); 
87._data.recycle(); 
88.} 
89.} 
90.} 
91.static final int TRANSACTION_performAction = (IBinder.FIRST_CALL_TRANSACTION + 0); 
92.} 
93.public void performAction() throws android.os.RemoteException; 
94.} 
/*
* This file is auto-generated.  DO NOT MODIFY.
* Original file: D://workspace//AIDLTest//src//com//styleflying//AIDL//forActivity.aidl
*/
package com.styleflying.AIDL;
import java.lang.String;
import android.os.RemoteException;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Binder;
import android.os.Parcel;
public interface forActivity extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.styleflying.AIDL.forActivity
{
private static final java.lang.String DESCRIPTOR = "com.styleflying.AIDL.forActivity";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an forActivity interface,
* generating a proxy if needed.
*/
public static com.styleflying.AIDL.forActivity asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.styleflying.AIDL.forActivity))) {
return ((com.styleflying.AIDL.forActivity)iin);
}
return new com.styleflying.AIDL.forActivity.Stub.Proxy(obj);
}
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_performAction:
{
data.enforceInterface(DESCRIPTOR);
this.performAction();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.styleflying.AIDL.forActivity
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
public void performAction() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_performAction, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_performAction = (IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void performAction() throws android.os.RemoteException;
}


文件forService.java:

[java:collapse:showcolumns] + expand sourceview plaincopyprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150/*
* This file is auto-generated.  DO NOT MODIFY.
* Original file: D://workspace//AIDLTest//src//com//styleflying//AIDL//forService.aidl
*/ 
package com.styleflying.AIDL; 
import java.lang.String; 
import android.os.RemoteException; 
import android.os.IBinder; 
import android.os.IInterface; 
import android.os.Binder; 
import android.os.Parcel; 
public interface forService extends android.os.IInterface 

/** Local-side IPC implementation stub class. */ 
public static abstract class Stub extends android.os.Binder implements com.styleflying.AIDL.forService 

private static final java.lang.String DESCRIPTOR = "com.styleflying.AIDL.forService"; 
/** Construct the stub at attach it to the interface. */ 
public Stub() 

this.attachInterface(this, DESCRIPTOR); 

/**
* Cast an IBinder object into an forService interface,
* generating a proxy if needed.
*/ 
public static com.styleflying.AIDL.forService asInterface(android.os.IBinder obj) 

if ((obj==null)) { 
return null; 

android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR); 
if (((iin!=null)&&(iin instanceof com.styleflying.AIDL.forService))) { 
return ((com.styleflying.AIDL.forService)iin); 

return new com.styleflying.AIDL.forService.Stub.Proxy(obj); 

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_registerTestCall: 

data.enforceInterface(DESCRIPTOR); 
com.styleflying.AIDL.forActivity _arg0; 
_arg0 = com.styleflying.AIDL.forActivity.Stub.asInterface(data.readStrongBinder()); 
this.registerTestCall(_arg0); 
reply.writeNoException(); 
return true; 

case TRANSACTION_invokCallBack: 

data.enforceInterface(DESCRIPTOR); 
this.invokCallBack(); 
reply.writeNoException(); 
return true; 


return super.onTransact(code, data, reply, flags); 

private static class Proxy implements com.styleflying.AIDL.forService 

private android.os.IBinder mRemote; 
Proxy(android.os.IBinder remote) 

mRemote = remote; 

public android.os.IBinder asBinder() 

return mRemote; 

public java.lang.String getInterfaceDescriptor() 

return DESCRIPTOR; 

public void registerTestCall(com.styleflying.AIDL.forActivity cb) 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.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null))); 
mRemote.transact(Stub.TRANSACTION_registerTestCall, _data, _reply, 0); 
_reply.readException(); 

finally { 
_reply.recycle(); 
_data.recycle(); 


public void invokCallBack() throws android.os.RemoteException 

android.os.Parcel _data = android.os.Parcel.obtain(); 
android.os.Parcel _reply = android.os.Parcel.obtain(); 
try { 
_data.writeInterfaceToken(DESCRIPTOR); 
mRemote.transact(Stub.TRANSACTION_invokCallBack, _data, _reply, 0); 
_reply.readException(); 

finally { 
_reply.recycle(); 
_data.recycle(); 



static final int TRANSACTION_registerTestCall = (IBinder.FIRST_CALL_TRANSACTION + 0); 
static final int TRANSACTION_invokCallBack = (IBinder.FIRST_CALL_TRANSACTION + 1); 

public void registerTestCall(com.styleflying.AIDL.forActivity cb) throws android.os.RemoteException; 
public void invokCallBack() throws android.os.RemoteException; 

/*
* This file is auto-generated.  DO NOT MODIFY.
* Original file: D://workspace//AIDLTest//src//com//styleflying//AIDL//forService.aidl
*/
package com.styleflying.AIDL;
import java.lang.String;
import android.os.RemoteException;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Binder;
import android.os.Parcel;
public interface forService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.styleflying.AIDL.forService
{
private static final java.lang.String DESCRIPTOR = "com.styleflying.AIDL.forService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an forService interface,
* generating a proxy if needed.
*/
public static com.styleflying.AIDL.forService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.styleflying.AIDL.forService))) {
return ((com.styleflying.AIDL.forService)iin);
}
return new com.styleflying.AIDL.forService.Stub.Proxy(obj);
}
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_registerTestCall:
{
data.enforceInterface(DESCRIPTOR);
com.styleflying.AIDL.forActivity _arg0;
_arg0 = com.styleflying.AIDL.forActivity.Stub.asInterface(data.readStrongBinder());
this.registerTestCall(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_invokCallBack:
{
data.enforceInterface(DESCRIPTOR);
this.invokCallBack();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.styleflying.AIDL.forService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
public void registerTestCall(com.styleflying.AIDL.forActivity cb) 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.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null)));
mRemote.transact(Stub.TRANSACTION_registerTestCall, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public void invokCallBack() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_invokCallBack, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_registerTestCall = (IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_invokCallBack = (IBinder.FIRST_CALL_TRANSACTION + 1);
}
public void registerTestCall(com.styleflying.AIDL.forActivity cb) throws android.os.RemoteException;
public void invokCallBack() throws android.os.RemoteException;
}


两段代码差不多,前面基本一样,从后面看,最后跟着我们在AIDL中自定义的方法,没有实现。两个文件各定义一个了接口,这两个接口分别会在Activity和Service中使用,在那里我们将实现自定义的方法。两个接口中都定义了一个抽象类Stub,实现所在的接口。Stub中又有一个类Proxy。Stub中有一个static的asInterface()方法,里面有很多return语句,在mAIDLActivity中调用它时,它返回一个新创建的内部类Proxy对象。

这个Stub对我们来说很有用,它继承了Binder。Binder有什么用呢?一个类,继承了Binder,那么它的对象就可以被远程的进程使用了(前提是远程进程获取了这个类的对象【对象的引用】,至于如如何获得看下文),在本例中就是说,如果一个Service中有一个继承了Stub的类的对象,那么这个对象中的方法就可以在Activity中使用,对Activity也是这样。至于Binder的细节,网上有很多贴介绍,看不明白也不影响我们完成这个例子。

再看mAIDLActivity.java:

[java] view plaincopyprint?
01.package com.styleflying.AIDL; 
02.import android.app.Activity; 
03.import android.content.ComponentName; 
04.import android.content.Context; 
05.import android.content.Intent; 
06.import android.content.ServiceConnection; 
07.import android.os.Bundle; 
08.import android.os.IBinder; 
09.import android.os.RemoteException; 
10.import android.util.Log; 
11.import android.view.View; 
12.import android.view.View.OnClickListener; 
13.import android.widget.Button; 
14.import android.widget.Toast; 
15.public class mAIDLActivity extends Activity { 
16.    private static final String TAG = "AIDLActivity"; 
17.    private Button btnOk; 
18.    private Button btnCancel; 
19.    private Button btnCallBack; 
20.     
21.    private void Log(String str) { 
22.        Log.d(TAG, "------ " + str + "------"); 
23.        } 
24.     
25.    private forActivity mCallback = new forActivity.Stub() { 
26.        public void performAction() throws RemoteException 
27.        { 
28.            Toast.makeText(mAIDLActivity.this, "this toast is called from service", 1).show(); 
29.        } 
30.        }; 
31.         
32.    forService mService; 
33.    private ServiceConnection mConnection = new ServiceConnection() { 
34.        public void onServiceConnected(ComponentName className, 
35.                IBinder service) { 
36.            mService = forService.Stub.asInterface(service); 
37.            try { 
38.                mService.registerTestCall(mCallback);} 
39.            catch (RemoteException e) { 
40.                 
41.            } 
42.            } 
43.        public void onServiceDisconnected(ComponentName className) { 
44.            Log("disconnect service"); 
45.            mService = null; 
46.            } 
47.        }; 
48.    @Override 
49.    public void onCreate(Bundle icicle) { 
50.        super.onCreate(icicle); 
51.        setContentView(R.layout.main); 
52.        btnOk = (Button)findViewById(R.id.btn_ok); 
53.        btnCancel = (Button)findViewById(R.id.btn_cancel); 
54.        btnCallBack = (Button)findViewById(R.id.btn_callback); 
55.        btnOk.setOnClickListener(new OnClickListener() { 
56.            public void onClick(View v) { 
57.                Bundle args = new Bundle(); 
58.                Intent intent = new Intent(mAIDLActivity.this, mAIDLService.class); 
59.                intent.putExtras(args); 
60.                bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 
61.                startService(intent); 
62.                } 
63.            }); 
64.        btnCancel.setOnClickListener(new OnClickListener() { 
65.            public void onClick(View v) { 
66.                unbindService(mConnection); 
67.                //stopService(intent);  
68.                } 
69.            }); 
70.        btnCallBack.setOnClickListener(new OnClickListener() { 
71.             
72.            @Override 
73.            public void onClick(View v) 
74.            { 
75.                try 
76.                { 
77.                    mService.invokCallBack(); 
78.                } catch (RemoteException e) 
79.                { 
80.                    // TODO Auto-generated catch block  
81.                    e.printStackTrace(); 
82.                } 
83.            } 
84.        }); 
85.        } 
86.} 
package com.styleflying.AIDL;
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 android.widget.Toast;
public class mAIDLActivity extends Activity {
private static final String TAG = "AIDLActivity";
private Button btnOk;
    private Button btnCancel;
    private Button btnCallBack;
   
    private void Log(String str) {
        Log.d(TAG, "------ " + str + "------");
        }
   
    private forActivity mCallback = new forActivity.Stub() {
public void performAction() throws RemoteException
{
Toast.makeText(mAIDLActivity.this, "this toast is called from service", 1).show();
}
};

forService mService;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
mService = forService.Stub.asInterface(service);
try {
mService.registerTestCall(mCallback);}
catch (RemoteException e) {

}
}
public void onServiceDisconnected(ComponentName className) {
Log("disconnect service");
mService = null;
}
};
    @Override
    public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
        setContentView(R.layout.main);
        btnOk = (Button)findViewById(R.id.btn_ok);
        btnCancel = (Button)findViewById(R.id.btn_cancel);
        btnCallBack = (Button)findViewById(R.id.btn_callback);
        btnOk.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            Bundle args = new Bundle();
                Intent intent = new Intent(mAIDLActivity.this, mAIDLService.class);
                intent.putExtras(args);
                bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
                startService(intent);
                }
            });
        btnCancel.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            unbindService(mConnection);
            //stopService(intent);
            }
            });
        btnCallBack.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v)
{
try
{
mService.invokCallBack();
} catch (RemoteException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
        }
}



很短,相信大家很容易看明白。注意mConnection,它的onServiceConnected()中有一句mService = forService.Stub.asInterface(service);给mService赋值了,这个mService是一个forService,而service是onServiceConnected()传进来的参数,onServiceConnected()会在连接Service的时候被系统调用,这个service参数的值来自哪里呢?看mAIDLService.java:

[java] view plaincopyprint?
01.package com.styleflying.AIDL; 
02.import android.app.Service; 
03.import android.content.Intent; 
04.import android.os.IBinder; 
05.import android.os.RemoteCallbackList; 
06.import android.os.RemoteException; 
07.import android.util.Log; 
08.public class mAIDLService extends Service { 
09.    private static final String TAG = "AIDLService";   
10.    private forActivity callback; 
11.    private void Log(String str) { 
12.        Log.d(TAG, "------ " + str + "------"); 
13.    } 
14.    @Override 
15.    public void onCreate() { 
16.        Log("service create"); 
17.    } 
18.    @Override 
19.    public void onStart(Intent intent, int startId) { 
20.        Log("service start id=" + startId); 
21.    } 
22.     
23.    @Override 
24.    public IBinder onBind(Intent t) { 
25.        Log("service on bind"); 
26.        return mBinder; 
27.    } 
28.    @Override 
29.    public void onDestroy() { 
30.        Log("service on destroy"); 
31.        super.onDestroy(); 
32.    } 
33.    @Override 
34.    public boolean onUnbind(Intent intent) { 
35.        Log("service on unbind"); 
36.        return super.onUnbind(intent); 
37.    } 
38.    public void onRebind(Intent intent) { 
39.        Log("service on rebind"); 
40.        super.onRebind(intent); 
41.    } 
42.    private final forService.Stub mBinder = new forService.Stub() { 
43.        @Override 
44.        public void invokCallBack() throws RemoteException 
45.        { 
46.            callback.performAction(); 
47.             
48.        } 
49.        @Override 
50.        public void registerTestCall(forActivity cb) throws RemoteException 
51.        { 
52.            callback = cb; 
53.             
54.        } 
55.         
56.    }; 
57.} 
package com.styleflying.AIDL;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;
public class mAIDLService extends Service {
    private static final String TAG = "AIDLService"; 
    private forActivity callback;
    private void Log(String str) {
        Log.d(TAG, "------ " + str + "------");
    }
    @Override
    public void onCreate() {
        Log("service create");
    }
    @Override
    public void onStart(Intent intent, int startId) {
        Log("service start id=" + startId);
    }
   
    @Override
    public IBinder onBind(Intent t) {
        Log("service on bind");
        return mBinder;
    }
    @Override
    public void onDestroy() {
        Log("service on destroy");
        super.onDestroy();
    }
    @Override
    public boolean onUnbind(Intent intent) {
        Log("service on unbind");
        return super.onUnbind(intent);
    }
    public void onRebind(Intent intent) {
        Log("service on rebind");
        super.onRebind(intent);
    }
    private final forService.Stub mBinder = new forService.Stub() {
@Override
public void invokCallBack() throws RemoteException
{
callback.performAction();

}
@Override
public void registerTestCall(forActivity cb) throws RemoteException
{
callback = cb;

}
       
    };
}

注意onBind(),它的返回类型为IBinder,返回了一个mBinder,看看mBinder的定义:

    private final forService.Stub mBinder = new forService.Stub() {

        @Override
        public void invokCallBack() throws RemoteException
        {
            callback.performAction();
         }

        @Override
        public void registerTestCall(forActivity cb) throws RemoteException
        {
            callback = cb;

        }

       };

它是实现了我们在AIDL中定义的方法,这个mBinder最终返回给了mAIDLActivity中的mService,于是在mAIDLActivity中可以使用mBinder中的方法了。在mAIDLActivity中也有一个类似mBinder的对象,看看定义:   

        private forActivity mCallback = new forActivity.Stub()

    {
        public void performAction() throws RemoteException
        {
            Toast.makeText(mAIDLActivity.this, "this toast is called from service", 1).show();
        }
      };

我们要在界面上显示一个toast,就是在这里实现的。这个对象,在mConnection的onServiceConnected()被调用时,通过调用mService(也就是远程的mAIDLService中的mBinder)的registerTestCall(),传递给了mAIDLService,于是在mAIDLService中可以调用performAction()了。

很啰嗦,只为了能把这个细节说清楚。请大家认真看,我尽量避免错别字、混乱的大小写和逻辑不清的语法,相信你会看明白。是不是很简单?再啰嗦一下,做一个大致总结,我们使用AIDL是要做什么呢:

让Acticity(或者说一个进程/一个类?)和Service(或者说远端进程/远端类/对象?)获取对方的一个Stub对象,这个对象在定义时实现了我们在AIDL中定义的方法,于是这些远程对象中的方法可以在本地使用了。如果这种使用(通信)是单向的,比如只是Activity需要通知Service做什么,那么只要Service中有一个Stub对象,并且传给Acticity就够了。

至于如何获得远程的Stub,参看上面的代码,看mConnection、registerTestCall、onRebind,它们展示了一种方法。

另外,有时候我们可能在一个类中有多个Stub对象,它们都要给远程交互的类的实例,这个时候可以考虑使用RemoteCallbackList<>(docs/reference/android/os/RemoteCallbackList.html)。

欢迎阅读、收藏本文。例子随手写的,功能只在演示AIDL的使用。您可以转载本文,但请勿盲目乱贴。不是我小气,我不权威,我怕它被贴到泛滥,以讹传讹,害了人。

热点排行