在Android系统中实现AIDL接口回调

   在文章《在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

 

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值