Android中非aidl实现进程间通信(编写顺序的parcel写入与读出)

在android中进程间通信(IPC)的基石是Binder系统,Binder系统的核心Binder驱动是C来实现的,对于应用开发人员来说无疑晦涩难懂,而整个android框架是基于面向对象思想的,对于底层Binder驱动的操作细节全部隐藏,framework层提供了一个牛逼无比的Binder对象, 所以我们要实现进程间通信(IPC)只需玩转Binder对象即可。

在android源码中基于Binder对象的通信随处可见,几乎可以认定为以 I 打头的class,都具有进程间通信能力,如:IServiceManager,IContentProvider等。

在源码中实现的方式也可概括为两种:

1. 通过aidl来生成对Binder的操作。

2.手动调用IBinder.transact编写按照顺序写入与读出的parcel代码实现。

第一种方法网上案例较多,不多说。第二种方法实现源码参考:ActivityManagerNative,ActivityManagerProxy

关于第二种方法的实现本人做了一个demo,请看以下代码。


package dw.test;

import java.util.HashMap;

import android.os.Binder;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
/**
 * 负责接收指令({@link CmdCode}),并将指令派发到相应的处理器({@link CmdDispatcher.Callback})
 */
public final class CmdDispatcher extends Binder implements IInterface{
 
	private static final String LOG_TAG = CmdDispatcher.class.getSimpleName();

	public static final String DESCRIPTOR = CmdDispatcher.class.getName();
	/**
	 * 存储所有指令处理器
	 * map.key = {@link CmdCode}
	 */
	private HashMap<Integer,Callback> mCallbacks = new HashMap<Integer, Callback>();
	/**
	 * 针对某个指令的处理
	 * @see #addCallback
	 * @see #removeCallback
	 */
	public interface Callback {
		/**
		 * @param code 请求指令集{@link CmdCode.Request},响应 指令集{@link CmdCode.Response}
		 * @param data 数据 {@link Parcel}
		 * @param reply 处理data的结果 {@link Parcel}
		 * @return
		 */
		public boolean onTransact(int code, Parcel data, Parcel reply);
	}
	/**
	 * 当client端调用 {@link IBinder#transact(int, Parcel, Parcel, int)}时,将会回调本方法。
	 */
	@Override
	protected boolean onTransact(int code, Parcel data, Parcel reply,
			int flags) throws RemoteException {

		dispatch(code,data,reply);

		return true;
	}
	/**
	 * 得到某个指令处理器并调用
	 */
	private void dispatch(int code, Parcel data, Parcel reply) {
		Log.i(LOG_TAG, "dispatch reply enter");

		Callback callback = mCallbacks.get(code);

		if(callback!=null){
			callback.onTransact(code, data, reply);
		}

		Log.i(LOG_TAG, "dispatch reply exit");
	}

	@Override
	public IBinder asBinder() {
		return this;
	}

	@Override
	public String getInterfaceDescriptor() {
		return DESCRIPTOR;
	}

	@Override
	public IInterface queryLocalInterface(String descriptor) {
		return this;
	}
	/**
	 * 针对某一个指令,如:请求指令集{@link CmdCode.Request},响应 指令集{@link CmdCode.Response}
	 * 添加回调处理
	 * @param code 指令编码
	 * @param callback 针对某一个指定的处理 {@link Callback}
	 */
	public void addCallback(int code,Callback callback) {
		mCallbacks.put(code, callback);
	}

	public void removeCallback(int code) {
		mCallbacks.remove(code);
	}

}
package dw.test;
/**
 * 定义指令集
 */
public interface CmdCode {

	public interface BaseCode {
		/**
		 * 每个parcel的头
		 */
		public static final int PARCEL_HEAD = 0xffff;
		public static final int RESULT_SUCCESS = 0x0001;
		public static final int RESULT_ERROR = 0x0002;
	}
	/**
	 * 请求指令集
	 */
	public interface Request extends BaseCode{
		public static final int REQUEST = 0x0001;
	}
	/**
	 * 响应指令集
	 */
	public interface Response extends BaseCode {
		public static final int RESPONSE = 0x0001;
	}

}
package dw.test;

import dw.test.CmdDispatcher.Callback;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Parcel;
import android.util.Log;

/**
 * RemoteService作为一个独立进程存在.
 */
public class RemoteCmdService extends Service implements Callback,CmdCode.Request{

	private static final String LOG_TAG = RemoteCmdService.class.getSimpleName();

	private final CmdDispatcher mCmdDispatcher = new CmdDispatcher();

	@Override
	public IBinder onBind(Intent intent) {
		mCmdDispatcher.addCallback(REQUEST, this);
		return mCmdDispatcher;
	}

	@Override
	public void onCreate() {
		super.onCreate();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {

		Log.i(LOG_TAG, "onStartCommand enter");

		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public boolean onTransact(int code, Parcel data, Parcel reply) {
		Log.i(LOG_TAG, "remove service handle Reply enter");
		data.enforceInterface(CmdDispatcher.DESCRIPTOR);
		//读取包头
		int head = data.readInt();
		if(head==PARCEL_HEAD) {
			String handeResult = data.readString();
			reply.writeInt(RESULT_SUCCESS);
			Log.i(LOG_TAG, handeResult);
		} else {
			reply.writeInt(RESULT_ERROR); 
		}
		Log.i(LOG_TAG, "remove service handle Reply exit");
		return true;
	}

}
package dw.test.activity;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import dw.test.CmdCode;
import dw.test.CmdDispatcher;
import dw.test.R;
import dw.test.RemoteCmdService;

public class MainActivity extends Activity implements OnClickListener , CmdCode.Request,CmdCode.Response{

	private static final String LOG_TAG = MainActivity.class.getSimpleName();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.findViewById(R.id.test_remote_binder_btn).setOnClickListener(this);
    }
    
	/**
     * 连接并调用远程服务
     */
    private void testRemote(){
    	Intent intent = new Intent(MainActivity.this,RemoteCmdService.class);
    	//绑定远程服务
    	bindService(intent, new ServiceConnection() {

			@Override
			public void onServiceDisconnected(ComponentName name) {

			}

			@Override
			public void onServiceConnected(ComponentName name, IBinder service) {

				replyTo(service);

			}
		}, BIND_AUTO_CREATE);
    }
    
	private void replyTo(IBinder service) {
		Parcel data = Parcel.obtain();
		Parcel reply = Parcel.obtain();

		data.writeInterfaceToken(CmdDispatcher.DESCRIPTOR);
		//写入包头
		data.writeInt(PARCEL_HEAD);
		//写入要发送的字符数据
		data.writeString("serviceConnected");

		//当然你也可以传递一个binder对象过去作为callback,这样两个进程间就可以交互了。
//		data.writeStrongBinder(IBinder binder); 

		try {
			//调用远程MESSAGE_REQUEST服务
			service.transact(REQUEST, data, reply,0);
		} catch (RemoteException e) {
			//ignore
		}

		//MESSAGE_REQUEST服务所返回的结果 
		int result = reply.readInt();

		if(RESULT_SUCCESS==result) {
			Log.i(LOG_TAG, "ok");
		}

		data.recycle();
		reply.recycle();
	}

	@Override
	public void onClick(View v) {
		int id = v.getId();
		if(R.id.test_remote_binder_btn==id){
			testRemote();
		}
	}

    
}

代码工程:http://download.csdn.net/detail/hacker686ok/5810399

时间: 2024-10-05 16:50:21

Android中非aidl实现进程间通信(编写顺序的parcel写入与读出)的相关文章

Android开发之IPC进程间通信-AIDL介绍及实例解析

一.IPC进程间通信 IPC是进程间通信方法的统称,Linux IPC包括以下方法,Android的进程间通信主要采用是哪些方法呢? 1. 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信:   2. 信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身:linux除了支持Unix早期

Android Studio中使用AIDL进行进程间通信

什么是AIDL aidl是 Android Interface definition language的缩写,也就是安卓接口定义语言 为什么要有AIDL AIDL允许你定义客户端与服务端达成一致的程序接口使用进程间通信相互交流. 在Android上面,一个进程不能正常的访问另一个进程的内存. 所以说,他们需要分解他们的对象为操作系统可以理解的基本单位,然后为你把这些对象按次序跨越进程边界 ,书写这些代码是单调冗长的,所以android使用AIDL为你处理这个问题. 注意:使用AIDL只有在你允许

Android——Binder(AIDL)机制

1.Binder 1)IBinder和Binder? IBinder是远程对象的基本接口,是为了高性能而设计的轻量级远程调用机制的核心部分.但他不仅用于远程调用,也用于进程内调用.该接口定义了与远程对象间交互的协议.但不要直接实现这个接口,而是继承(extends)Binder. IBinder主要的API是transact(),与之对应的API是Binder.onTransact().通过前者,你能向远程IBinder对象发送发出调用,后者使你的远程对象能够响应接收到的调用.IBinder的A

Android之——AIDL小结

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47071683 AIDL (Android Interface Definition Language ) AIDL 适用于 进程间通信,并且与Service端多个线程并发的情况,如果只是单个线程 可以使用 Messenger ,如果不需要IPC 可以使用Binder AIDL语法:基础数据类型都可以适用,List Map等有限适用.static field 不适用. AIDL基本

Android Service AIDL 远程调用服务 简单音乐播放实例的实现

Android Service是分为两种: 本地服务(Local Service): 同一个apk内被调用 远程服务(Remote Service):被另一个apk调用 远程服务需要借助AIDL来完成. AIDL 是什么 AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码.如果在一个进程中(例如Activi

Android之——AIDL深入

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47071927 在上一篇博文<Android之--AIDL小结>中,我们简单介绍了一下Android AIDL的用法,而在这篇博文中,我们将深入讲解Android AIDL的用法,同样,在这里我们也通过一个小例子来学习Android 中 AIDL的用法. 好处:多个应用程序之间建立共同的服务机制,通过AIDL在不同应用程序之间达到数据的共享和数据相互操作, 本文包括: 1 .创建

Android中AIDL实现进程通信(附源码下载)

AIDL概述 之前的博客<Android中通过Messenger与Service实现进程间双向通信>演示了如何通过Messenger实现与Service进行跨进程通信,即IPC.但用Messenger实现的IPC存在一点不足:Service内部维护着一个Messenger,Messenger内部又维护着一个Hanlder,当多个client向该Service发送Message时,这些Message需要依次进入Hanlder的消息队列中,Hanlder只能处理完一个Message之后,再从消息队

android基础----&gt;aidl服务的使用

AIDL和其他的IDL类似,它允许你定义程序接口,以便客户端与服务器端通过IPC机制交互.在android上面,一个进程一般不能访问另外进程的内存.因此,Android平台将这些跨进程访问的对象分解成操作系统能够识别的简单对象.并为跨应用访问而特殊编排和整理这些对象.用于编排和整理这些对象的代码编写起来十分冗长,所以Android的AIDL提供了相关工具来自动生成这些代码.今天,我们开始AIDL的学习. 简单说明 一,AIDL的定义: 它是一种android内部进程通信接口的描述语言,通过它我们

android 客户端支付宝 php服务器端编写

生成私钥 输入"genrsa -out rsa_private_key.pem 1024"命令,回车后,在当前 bin 文件目 录中会新增一个 rsa_private_key.pem 文件,其文件为原始的商户私钥(请妥善保 存该文件,PHP 开发语言中需要使用该文件), 生成公钥 输入"rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem"命令回车 后,在当前 bin 文件目录中会新增一个 rsa_p