Android AIDL 使用

AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。官方文档特别提醒我们何时使用AIDL是必要的:只有你允许客户端从不同的应用程序为了进程间的通信而去访问你的service,以及想在你的service处理多线程。

对于实现AIDL接口,官方还提醒我们:
    1. 调用者是不能保证在主线程执行的,所以从一调用的开始就需要考虑多线程处理,以及确保线程安全;
    2. IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。也就是IPC调用会挂起应用程序导致界面失去响应,这种情况应该考虑单独开启一个线程来处理。
    3. 抛出的异常是不能返回给调用者(跨进程抛异常处理是不可取的)。

工作中用到了一个service为多个app提供服务的情况,每个app都有自己的aidl定义,这里用简单的demo展示aidl的调用过程

首先看app1,app1定义了一套详细的aidl,service需要根据aidl完成接口。app1的aidl

interface AidlDcService{
	
	/** 获取串口测试操作实例  */
	IBinder getDcSystem();

}
import com.dc.pos.aidl.CommTestObserver;
//系统设备
interface AidlDcSystem{
	//结束测试
	void endCommTest();
	//开始测试
	void startCommTest(int type,CommTestObserver observer);
}
interface CommTestObserver{
	//成功
	void onTestFinished();
	//错误
	void onTestError(int errorCode);
}

三个aidl文件已经创建完毕,在app和service端均要保证报名和文件的一致。

app1的activity1和app2的activity2里面在onResume里面绑定不同的服务,activity1绑定DcSetvice,activity2绑定DeviceService;两者仅仅是setAction不同。

//绑定服务
	public void bindService(){
		Intent intent = new Intent();
		intent.setAction(DC_SERVICE_ACTION);
		boolean flag = bindService(intent, conn, Context.BIND_AUTO_CREATE);
		if(flag){
			Debug.d(LOG_TAG, "服务绑定成功");
		}else{
			Debug.d(LOG_TAG, "服务绑定失败");
		}
	}

这里没用直接使用service的class作为绑定参数,而是以setAction的方式。在service里可以针对不同的action绑定不同的服务

<service android:name=".DeviceService" >
            <intent-filter>
                <action android:name="lkl_cloudpos_device_service" />
            </intent-filter>
        </service>
        <service android:name=".DcService" >
            <intent-filter>
                <action android:name="dc_pos_device_service" />
            </intent-filter>
        </service>
activict1里面完成绑定结果的监听

private ServiceConnection conn = new ServiceConnection(){

		@Override
		public void onServiceConnected(ComponentName name, IBinder serviceBinder) {
			Debug.d(LOG_TAG, "AidlService服务连接成功");
			if(serviceBinder != null){	//绑定成功
				AidlDcService serviceManager = AidlDcService.Stub.asInterface(serviceBinder);
				onDeviceConnected(serviceManager);
			}
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			Debug.d(LOG_TAG, "AidlService服务断开");
		}
	};
同样的activity2里面也是如此

//设别服务连接桥
	private ServiceConnection conn = new ServiceConnection(){

		@Override
		public void onServiceConnected(ComponentName name, IBinder serviceBinder) {
			Debug.d("aidlService服务连接成功");
			if(serviceBinder != null){	//绑定成功
				AidlDeviceService serviceManager = AidlDeviceService.Stub.asInterface(serviceBinder);
				onDeviceConnected(serviceManager);
			}
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			Debug.d("AidlService服务断开了");
		}
	};
在这里调用了onDeviceConnected创建对应的AidlDcSystem对象systemInf

public void onDeviceConnected(AidlDcService serviceManager) {
		try {
			systemInf = AidlDcSystem.Stub.asInterface(serviceManager
					.getDcSystem());
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
AidlDcSystem对象创建好之后,就可以通过systemInf调用AidlDcSystem.aidl中定义的接口文件。

同样在activiry2中调用了onDeviceConnected创建对应的AidlSystem对象isys
通过isys调用AidlDeviceService.aidl中定义的接口文件。


下面再来看service中的实现



首先创建两个service,分别针对app1和app2的绑定

这里贴出DcService

public class DcService extends Service {

	public static final boolean needAuthorize = false;

	private final static String TAG = "DcService";

	private final static int CMD_INIT_OK = 0;

	private final static int CMD_INIT_FAIL = 1;
	
	private Context context;

	private IDevice dcpos = null;

	private CommTestImpl commTestImpl = new CommTestImpl(this);

	@SuppressLint("HandlerLeak")
	private Handler handler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			switch (msg.what) {
			case CMD_INIT_OK:
				DeviceInstance.setInstance(dcpos);
				break;
			case CMD_INIT_FAIL:
				DeviceInstance.setInstance(null);
				Toast.makeText(DcService.this, "init SDK Fail", Toast.LENGTH_SHORT).show();
				break;

			default:
				break;
			}
			super.handleMessage(msg);
		}

	};

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		// acquireWakeLock();
		initSdk();
		super.onCreate();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		flags = START_STICKY;
		return super.onStartCommand(intent, flags, startId);
	}

	private void initSdk() {
		//这里是绑定后的进一步操作,和本文无关,隐去
	}


	@Override
	public void onDestroy() {

		super.onDestroy();
	}

	@Override
	public IBinder onBind(Intent intent) {
		Debug.e(TAG, "onBind()");
		return new AidlDcServiceImpl();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Service#onUnbind(android.content.Intent)
	 */
	@Override
	public boolean onUnbind(Intent intent) {
		// TODO Auto-generated method stub
		Debug.e(TAG, "onUnbind()");
		return super.onUnbind(intent);
	}

	private class AidlDcServiceImpl extends AidlDcService.Stub {

		@Override
		public IBinder getDcSystem() throws RemoteException {
			// TODO Auto-generated method stub
			return commTestImpl;
		}

	}

}

DcService在绑定时通过new AidlDcServiceImpl()创建对象返回给绑定的app1的activity1,这时activity1就可以根据此对象来调用相应的接口完成需要的功能。

同样的app2也可以绑定相应的DeviceService。

这样一个后台服务就可以通过不同的aidl与不同的app绑定。对于app来说互相之间是完全屏蔽的。

aidl中使用java类,需要实现Parcelable接口,并且在定义类相同包下面对类进行声明,此问题将在下一篇中讲述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android AIDLAndroid Interface Definition Language)是一种用于定义客户端和服务之间通信接口的语言。AIDL 是一个 Android 特有的 RPC(远程过程调用)机制。 下面是使用 AIDL 的基本步骤: 1. 定义 AIDL 接口 在服务端创建一个 AIDL 文件,定义服务的接口方法。例如,创建一个名为 IMyService.aidl 的文件,其中包含以下内容: ``` interface IMyService { void sayHello(); } ``` 2. 实现 AIDL 接口 在服务端实现 AIDL 接口,例如: ``` public class MyService extends Service { private final IMyService.Stub binder = new IMyService.Stub() { @Override public void sayHello() throws RemoteException { Log.i("MyService", "Hello World"); } }; @Nullable @Override public IBinder onBind(Intent intent) { return binder; } } ``` 3. 绑定服务 在客户端绑定服务,例如: ``` private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { IMyService myService = IMyService.Stub.asInterface(service); try { myService.sayHello(); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; private void bindService() { Intent intent = new Intent(this, MyService.class); bindService(intent, connection, Context.BIND_AUTO_CREATE); } ``` 通过上述步骤,就可以实现客户端与服务端之间的通信。需要注意的是,AIDL 接口中定义的方法必须是可序列化的。如果方法参数或返回值类型不支持序列化,可以通过 Parcelable 接口实现序列化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值