最近参与了一个项目,其中有用到两个APK间进行通信,最终采用的是AIDL,于是自己小研究了下,如有错误,请大家指正。
1. 创建.aidl文件
首先,创建.aidl文件。这个文件类似于声明文件,对于服务器端而言,就是声明你需要对外提供什么接口;对于客户端来说,声明了自己将要用到的接口。所以,不仅服务器端要创建.aidl文件,客户端同样需要。而且是客户端的.aidl文件要和服务器端的一样。所以服务器端一旦公布了对外接口,最好就不要改啦,因为会有很多客户端将用。
下面这两个文件IEmilyService.aidl 是EmilyService.apk 里的定义的,IEmilyServiceCallBack.aidl 这个是EmilySecondClient.apk定义的,因为这个两个apk需要进行双向通信。
但是在两个apk中,这个两个文件是必须都具备的。说白了就是为了方便互相调接口...
IEmilyService.aidl
package com.example.fwk;
import com.example.fwk.IEmilyServiceCallBack;
interface IEmilyService {
void registerCallback(IEmilyServiceCallBack cb);
void unregisterCallback(IEmilyServiceCallBack cb);
void serviceShow();
}
IEmilyServiceCallBack.aidl
package com.example.fwk;
interface IEmilyServiceCallBack {
void serviceCallBackShow();
}
2. 实现接口并将接口暴露给客户端
这个两个文件在编译后会自动生成.java文件。额,因为我用的是eclipse, 一运行就自己生成了,也没仔细看里面具体都有啥。从文档里得知,里面东西还是很重要的。尤其是一个内部类Stub,它是父类接口的抽象实现,里面定义了.aidl中的所有方法。
mBinder是IEmilyService.Stub的对象,里面实现了IEmilyService.aidl里定义的所有方法。当有客户端连接的时候,也就是来onBind(), 客户端会得到mBinder这个实例。
EmilyService
package com.example.emilyservice;
import com.example.fwk.IEmilyService;
import com.example.fwk.IEmilyServiceCallBack;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.app.Service;
import android.content.Intent;
import android.util.Log;
public class EmilyService extends Service {
private static final String TAG = "EmilyService";
/*
* This is a list of callbacks that have been registered with the
* service.
*/
final RemoteCallbackList<IEmilyServiceCallBack> mCallbacks =
new RemoteCallbackList<IEmilyServiceCallBack>();
/*
* Implements the interface.
* 1. The mBinder is an instance of the Stub class (a Binder), which defines the RPC interface for the service.
* 2. This instance will be exposed to clients, so the clients can interact with the service.
* 3. If one service takes too much time to complete a request, you should avoid to call it from the main thread,
* you should call it from a separate thread in the client, in this way to avoid ANR.
*/
private final IEmilyService.Stub mBinder = new IEmilyService.Stub() {
public void registerCallback(IEmilyServiceCallBack cb) {
Log.i(TAG, "___________registerCallback()");
if (cb != null) mCallbacks.register(cb);
}
public void unregisterCallback(IEmilyServiceCallBack cb) {
Log.i(TAG, "___________unregisterCallback()");
if (cb != null) mCallbacks.unregister(cb);
}
public void serviceShow() throws RemoteException {
Log.i(TAG, "___________serviceShow()");
testClients(null);
}
};
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return mBinder;
}
/*
* Test the clients.
*/
public void testClients(IEmilyServiceCallBack cb) {
if (cb != null) {
Log.i(TAG, "cb != null");
try {
cb.serviceCallBackShow();
} catch (RemoteException e) {
}
} else {
// Broadcast to all clients the new value.
final int count = mCallbacks.beginBroadcast();
for (int i=0; i < count; i++) {
try {
Log.i(TAG, "onServiceShowFinished____i = " + i);
mCallbacks.getBroadcastItem(i).serviceCallBackShow();
} catch (RemoteException e) {
}
}
mCallbacks.finishBroadcast();
}
}
}
3. 当一个客户端调bindservice()去连接service的时候,客户端调用onServiceConected()回调方法。
Client
package com.example.emilysecondclient;
import com.example.fwk.IEmilyService;
import com.example.fwk.IEmilyServiceCallBack;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
private static String TAG = "EmilySecondClient";
private static String ACTION_START_EMILY_SERVICE = "android.intent.action.EMILY_SERVICE";
private IEmilyService mEmilyService = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// When the client call the bindService() to connect to Emily service,
// the client's onServiceConnected() callback receives IBinder that the
// client can use to communicate with the service.
Intent serviceIntent = new Intent(ACTION_START_EMILY_SERVICE);
bindService(serviceIntent, mEmilyServiceConnection, Context.BIND_AUTO_CREATE);
Button button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
serviceShowInClient();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
private final ServiceConnection mEmilyServiceConnection = new ServiceConnection() {
// Called when the connection with the service is established.
public void onServiceConnected(ComponentName className, IBinder service) {
Log.i(TAG, "service connected");
mEmilyService = IEmilyService.Stub.asInterface(service);
// We want to monitor the service for as long as we are
// connected to it.
try {
mEmilyService.registerCallback(mCallBack);
} catch (RemoteException e) {
}
}
public void onServiceDisconnected(ComponentName className) {
Log.i(TAG, "service disconnected");
mEmilyService = null;
}
};
private final IEmilyServiceCallBack.Stub mCallBack = new IEmilyServiceCallBack.Stub() {
public void serviceCallBackShow() throws RemoteException {
Log.i(TAG, "___________serviceCallBackShow()");
}
};
private void serviceShowInClient() {
try {
mEmilyService.serviceShow();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
以上只贴出来了一个Client的代码,另外一个client代码是类似的。
下面是运行出的log.
The log
I/EmilyFirstClient( 4163): service connected
I/EmilyService( 4084): Binder API: registerCallback()
I/EmilyService( 4084): ___________serviceShow()
I/EmilySecondClient( 4206): service connected
I/EmilyService( 4084): Binder API: registerCallback()
I/EmilyService( 4084): ___________serviceShow()
I/EmilyFirstClient( 6830): service connected
I/EmilyService( 6711): ___________registerCallback()
I/EmilyService( 6711): ___________serviceShow()
I/EmilyService( 6711): onServiceShowFinished____i = 0
I/EmilyFirstClient( 6830): ___________serviceCallBackShow()
I/EmilySecondClient( 6931): service connected
I/EmilyService( 6711): ___________registerCallback()
I/EmilyService( 6711): ___________serviceShow()
I/EmilyService( 6711): onServiceShowFinished____i = 0
I/EmilySecondClient( 6931): ___________serviceCallBackShow()
还是要好好研究下:
http://developer.android.com/guide/components/aidl.html