Android中非aidl實現(xiàn)進程間通信(編寫順序的parcel寫入與讀出)

在android中進程間通信(IPC)的基石是Binder系統(tǒng),Binder系統(tǒng)的核心Binder驅(qū)動是C來實現(xiàn)的,對于應(yīng)用開發(fā)人員來說無疑晦澀難懂,而整個android框架是基于面向?qū)ο笏枷氲?,對于底層Binder驅(qū)動的操作細節(jié)全部隱藏,framework層提供了一個牛逼無比的Binder對象, 所以我們要實現(xiàn)進程間通信(IPC)只需玩轉(zhuǎn)Binder對象即可。

成都創(chuàng)新互聯(lián)堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站設(shè)計、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的珙縣網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

在android源碼中基于Binder對象的通信隨處可見,幾乎可以認定為以 I 打頭的class,都具有進程間通信能力,如:IServiceManager,IContentProvider等。

在源碼中實現(xiàn)的方式也可概括為兩種:

1. 通過aidl來生成對Binder的操作。 

2.手動調(diào)用IBinder.transact編寫按照順序?qū)懭肱c讀出的parcel代碼實現(xiàn)。

第一種方法網(wǎng)上案例較多,不多說。第二種方法實現(xiàn)源碼參考:ActivityManagerNative,ActivityManagerProxy

關(guān)于第二種方法的實現(xiàn)本人做了一個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}),并將指令派發(fā)到相應(yīng)的處理器({@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},響應(yīng) 指令集{@link CmdCode.Response}
		 * @param data 數(shù)據(jù) {@link Parcel}
		 * @param reply 處理data的結(jié)果 {@link Parcel}
		 * @return
		 */
		public boolean onTransact(int code, Parcel data, Parcel reply);
	}
	/**
	 * 當client端調(diào)用 {@link IBinder#transact(int, Parcel, Parcel, int)}時,將會回調(diào)本方法。
	 */
	@Override
	protected boolean onTransact(int code, Parcel data, Parcel reply,
			int flags) throws RemoteException {
		
		dispatch(code,data,reply);

		return true;
	}
	/**
	 * 得到某個指令處理器并調(diào)用
	 */
	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},響應(yīng) 指令集{@link CmdCode.Response}
	 * 添加回調(diào)處理
	 * @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;
	}
	/**
	 * 響應(yīng)指令集
	 */
	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);
    }
    
	/**
     * 連接并調(diào)用遠程服務(wù)
     */
    private void testRemote(){
    	Intent intent = new Intent(MainActivity.this,RemoteCmdService.class);
    	//綁定遠程服務(wù)
    	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);
		//寫入要發(fā)送的字符數(shù)據(jù)
		data.writeString("serviceConnected");
		
		//當然你也可以傳遞一個binder對象過去作為callback,這樣兩個進程間就可以交互了。
//		data.writeStrongBinder(IBinder binder); 
		
		try {
			//調(diào)用遠程MESSAGE_REQUEST服務(wù)
			service.transact(REQUEST, data, reply,0);
		} catch (RemoteException e) {
			//ignore
		}
		
		//MESSAGE_REQUEST服務(wù)所返回的結(jié)果 
		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

網(wǎng)站標題:Android中非aidl實現(xiàn)進程間通信(編寫順序的parcel寫入與讀出)
標題URL:http://muchs.cn/article40/phoseo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營銷推廣、商城網(wǎng)站、網(wǎng)站制作、App設(shè)計、云服務(wù)器、標簽優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名