在文章《在Android系统中实现AIDL功能》中实现了aidl的接口调用,但是有时候客户端调用完接口函数后希望服务端有数据返回,这时候就需要定义回调函数。在《在Android系统中实现AIDL功能》的基础上实现接口的回调。还是分三个项目实现,如下图:
├── SimpleJar
├── SimpleJarClient
└── SimpleJarService
一、定义回调需要的aidl接口
在SimpleJar项目中添加用于实现回调的aidl文件IVoiceCallBackInterface.aidl,
SimpleJar项目项目结构:
├── Android.mk
└── src
└── com
└── china
└── jar
├── IVoiceCallBackInterface.aidl
├── IVoiceClientInterface.aidl
├── VoiceChangedListener.java
└── VoiceManager.java
IVoiceCallBackInterface.aidl中只有一个方法,如下:
package com.china.jar;
interface IVoiceCallBackInterface{
void openAppByVoice(in String packagename);
}
二、在 IVoiceClientInterface.aidl中注册(registerCallBack)或注销(unRegisterCallBack)IVoiceCallBackInterface接口,如下:
package com.china.jar;
import com.china.jar.IVoiceCallBackInterface;
interface IVoiceClientInterface{
void face();
void registerCallBack(IVoiceCallBackInterface callback);
void unRegisterCallBack(IVoiceCallBackInterface callback);
}
三、添加接口VoiceChangedListener以便客户端回调使用,接口VoiceChangedListener里面的方法要跟IVoiceCallBackInterface.aidl保持一致。如下:
package com.china.jar;
public interface VoiceChangedListener {
void openAppByVoice(String packagename);
}
四、 在VoiceManager.java中添加VoiceChangedListener的接口监听及在VoiceManager构造方法中实现跟服务端的链接getService(),具体实现如下:
package com.china.jar;
import java.util.ArrayList;
import java.util.List;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
public class VoiceManager {
private static final String TAG = "VoiceManager";
private static VoiceManager mVoiceManager;
private static IVoiceClientInterface mService = null;
public static final String NAME = "simple_jar";
public static final boolean DEBUG_DATA = true;
private final HandlerThread mWorkThread;
private final Handler mWorkHander;
private static final int MSG_INIT_SERVICE = 0x01;
private CallBack mCallBack;
private List<VoiceChangedListener> listeners = new ArrayList<VoiceChangedListener>();
//单例模式
public static synchronized VoiceManager getInstance(){
if (null == mVoiceManager){
synchronized (VoiceManager.class) {
if (null == mVoiceManager){
mVoiceManager = new VoiceManager();
}
}
}
return mVoiceManager;
}
//该构造函数主要调用getService()方法,以便客户端在调用VoiceManager.getInstance()方法时可以跟服务端建立链接
private VoiceManager(){
Log.d(TAG, "VoiceManager...begin");
mWorkThread = new HandlerThread("simple_manager");
mWorkThread.start();
mWorkHander = new Handler(mWorkThread.getLooper()){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_INIT_SERVICE:
removeMessages(MSG_INIT_SERVICE);
getService();
break;
default:
break;
}
}
};
mWorkHander.sendEmptyMessage(MSG_INIT_SERVICE);
}
//获取服务端注册的NAME服务并跟服务端建立连接
private synchronized IVoiceClientInterface getService(){
Log.d(TAG, "getService...begin");
if (null == mService){
Log.e(TAG, "IVocieService init");
mService = IVoiceClientInterface.Stub.asInterface(ServiceManager
.getService(NAME));
if (mService != null){
try {
mCallBack = new CallBack(listeners);
mService.registerCallBack(mCallBack);
} catch (Exception e) {
e.printStackTrace();
mService = null;
}
}
}
if (null == mService){
Log.e(TAG, "jar service is null");
mWorkHander.removeMessages(MSG_INIT_SERVICE);
mWorkHander.sendEmptyMessageDelayed(MSG_INIT_SERVICE, 100);
}
return mService;
}
public void face(){
Log.d(TAG, "face");
mService = getService();
if (null == mService){
Log.e(TAG, "face mService is null!");
return ;
}
try{
mService.face();
}catch(RemoteException e){
e.printStackTrace();
}
}
//注册监听
public void addVoiceChangedListener(final VoiceChangedListener aListener){
if (DEBUG_DATA){
Log.v(TAG, "addVoiceChangedListener..." + aListener + " ,before list size = " + listeners.size());
}
if (aListener != null && !listeners.contains(aListener)){
listeners.add(aListener);
if (DEBUG_DATA){
Log.v(TAG, "addVoiceChangedListener... after list size = " + listeners.size());
}
}
}
//注销监听
public void removeVoiceChangedListener(final VoiceChangedListener aListener){
if (DEBUG_DATA){
Log.v(TAG, "removeVoiceChangedListener..." + aListener + " ,before list size = " + listeners.size());
}
if (aListener != null && !listeners.contains(aListener)){
listeners.add(aListener);
if (DEBUG_DATA){
Log.v(TAG, "removeVoiceChangedListener... after list size = " + listeners.size());
}
}
}
//回调接口实现
private static final class CallBack extends IVoiceCallBackInterface.Stub{
private Handler mHandler = null;
private List<VoiceChangedListener> mListeners;
public CallBack(List<VoiceChangedListener> listeners) {
mHandler = new Handler(Looper.getMainLooper());
this.mListeners = listeners;
}
@Override
public void openAppByVoice(final String packagename) throws RemoteException {
Log.d(TAG, "packagename = " + packagename);
this.mHandler.post(new Runnable() {
@Override
public void run() {
for (VoiceChangedListener v : mListeners){
v.openAppByVoice(packagename);
}
}
});
}
}
}
五、到第四步,项目 SimpleJar中的代SimpleJarService码就实现完了,编译SimpleJar项目就可以到得服务端跟客户端都需要用到的jar包simple.jar。将simple.jar导入项目SimpleJarService中,然后在SimpleService.java中实现registerCallBack跟unRegisterCallBack方法,并且使用RemoteCallbackList来实现调用。
SimpleJarService项目结构
├── AndroidManifest.xml
├── Android.mk
├── libs
│ ├── android-support-v4.jar
│ ├── fw.jar
│ └── simple.jar
├── res
│ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ ├── drawable-ldpi
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── layout
│ ├── values
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── values-v11
│ │ └── styles.xml
│ └── values-v14
│ └── styles.xml
└── src
└── com
└── china
└── service
├── BootReceiverBroadcast.java
├── Logger.java
├── SimpleControl.java
└── SimpleService.java
SimpleService.java具体实现,如下:
package com.china.service;
import com.china.jar.IVoiceCallBackInterface;
import com.china.jar.IVoiceClientInterface;
import com.china.jar.VoiceChangedListener;
import com.china.jar.VoiceManager;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
public class SimpleService extends Service{
private static VoiceClientInterfaceImpl mBinder;
@Override
public IBinder onBind(Intent intent) {
Logger.d();
return mBinder;//跟客户端绑定
}
@Override
public void onCreate() {
super.onCreate();
Logger.d();
if (null == mBinder){
initService();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Logger.d();
if (null == mBinder){
initService();
}
return START_STICKY;
}
//实现AIDL的接口
private class VoiceClientInterfaceImpl extends IVoiceClientInterface.Stub{
protected RemoteCallbackList<IVoiceCallBackInterface> mRemoteCallbackList =
new RemoteCallbackList<IVoiceCallBackInterface>();
private SimpleControl control;
public VoiceClientInterfaceImpl(){
control = new SimpleControl(voiceChangedListener);
}
@Override
public void face() throws RemoteException {
Logger.d("face----excute!");//客户端调用face方法时这里会执行,会打印face----excute!
}
//注册回调
@Override
public void registerCallBack(IVoiceCallBackInterface arg0)
throws RemoteException {
Logger.d();
mRemoteCallbackList.register(arg0);
}
//注销回调
@Override
public void unRegisterCallBack(IVoiceCallBackInterface arg0)
throws RemoteException {
Logger.d();
mRemoteCallbackList.unregister(arg0);
}
//调用回调方法
private VoiceChangedListener voiceChangedListener = new VoiceChangedListener() {
@Override
public void openAppByVoice(String arg0) {
Logger.d("arg0 = " + arg0);
int len = mRemoteCallbackList.beginBroadcast();
for (int i = 0; i <len; i++) {
try {
mRemoteCallbackList.getBroadcastItem(i).openAppByVoice(arg0);
} catch (RemoteException e) {
e.printStackTrace();
}
}
mRemoteCallbackList.finishBroadcast();
}
};
}
//初始化服务,主要是向系统注册服务
private void initService(){
Logger.d();
if (null == mBinder){
synchronized (SimpleService.class) {
if (null == mBinder){
try {
mBinder = new VoiceClientInterfaceImpl();
ServiceManager.addService(VoiceManager.NAME, mBinder);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
六、 SimpleControl.java是用于获取步骤五中的voiceChangedListener回调接口,具体实现如下:
package com.china.service;
import com.china.jar.VoiceChangedListener;
public class SimpleControl {
private static VoiceChangedListener changedListener;
public SimpleControl(VoiceChangedListener voiceChangedListener){
changedListener = voiceChangedListener;
}
//获取初始化后的回调实例
public static VoiceChangedListener getVoiceCallBack(){
return changedListener;
}
}
7、通过发送接收广播的方式来模拟调用SimpleService.java类中的openAppByVoice(String arg0)方法 ,具体实现在BootReceiverBroadcast.java类中,如下:
package com.china.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootReceiverBroadcast extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Logger.d();
Intent service = new Intent(context, SimpleService.class);//开机启动会拉起服务SimpleService
context.startService(service);
if(intent.getAction().equals("android.intent.gunder.SimpleJar")){
//android.intent.gunder.SimpleJar属于自定义action
Logger.d(intent.getAction());
SimpleControl.getVoiceCallBack().openAppByVoice("nihao");//这里模拟调用penAppByVoice方法
}
}
}
android.intent.gunder.SimpleJar是AndroidManifest.xml中自定义的action,如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.chinatsp.service"
android:versionCode="1"
android:versionName="1.0"
android:sharedUserId="android.uid.system"
>
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<service android:name="com.china.service.SimpleService"></service>
<receiver android:name="com.china.service.BootReceiverBroadcast">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<!-- <category android:name="android.intent.category.LAUNCHER"/> -->
<action android:name="android.intent.gunder.SimpleJar" />
</intent-filter>
</receiver>
</application>
</manifest>
到这里服务端的功能就实现完了,接下看客户端的调用。
八、客户端的调用是在 SimpleJarClient项目中实现,SimpleJarClient项目结构如下:
.
├── AndroidManifest.xml
├── Android.mk
├── libs
│ └── simple.jar
├── res
│ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ ├── drawable-ldpi
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ │ └── ic_launcher.png
│ ├── layout
│ │ ├── activity_main.xml
│ │ ├── activity_tss.xml
│ │ ├── test.xml
│ │ └── version.xml
│ ├── menu
│ ├── values
│ │ ├── dimens.xml
│ │ └── strings.xml
│ ├── values-v11
│ ├── values-v14
│ └── values-w820dp
│ └── dimens.xml
└── src
└── com
└── example
└── helloworld
├── TestVoice.java
└── util
└── Logger.java
从项目的目录可以看出,TestVoice.java是实现主要功能的类,该类的具体实现如下:
package com.example.helloworld;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import com.china.jar.VoiceChangedListener;
import com.china.jar.VoiceManager;
import com.example.helloworld.util.Logger;
public class TestVoice extends Activity{
VoiceManager voiceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.version);
voiceManager = VoiceManager.getInstance();
if (voiceManager != null){
voiceManager.addVoiceChangedListener(new VoiceChangedListener() {//客户端的监听及实现
@Override
public void openAppByVoice(String arg0) {
Logger.d("packageName = " + arg0);
}
});
}
}
public void startVoice(View view){
Logger.d();
}
public void stopVoice(View view){
Logger.d();
VoiceManager.getInstance().face();
}
public void finishVoice(View view){
Logger.d();
finish();
}
}
在onCreate方法中进行了回调接口的监听addVoiceChangedListener,当服务端接送到广播android.intent.gunder.SimpleJar时就会调用SimpleService.java类中的openAppByVoice(String arg0)方法,客户端的接口VoiceChangedListener类里面的openAppByVoice(String arg0)方法也会被调用。
九、安装服务端跟客户端的apk然后运行,运行结果如果如下:
代码参考路径:https://github.com/gunder1129/android-tool/tree/master/AIDLdemo