您的位置:首页 > 移动开发 > Android开发

android进程间通信:使用AIDL

2010-10-08 10:25 507 查看
感谢-谭瑞ID:saintswordsman

欢迎阅读本文,你能关注本文,你知道你需要进程间通信、需要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

view plain
copy to clipboard
print
?

package
com.styleflying.AIDL;

interface
forActivity {

void
performAction();

}

package com.styleflying.AIDL;
interface forActivity {
void performAction();
}


文件:forService.aidl

view plain
copy to clipboard
print
?

package
com.styleflying.AIDL;

import
com.styleflying.AIDL.forActivity;

interface
forService {

void
registerTestCall(forActivity cb);

void
invokCallBack();

}

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:

view plain
copy to clipboard
print
?

/*

* 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;

}

/*
* 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:

+ expand source
view plain
copy to clipboard
print
?

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

view plain
copy to clipboard
print
?

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();

}

}

});

}

}

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:

view plain
copy to clipboard
print
?

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;

}

};

}

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)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: