在android中進(jìn)程間通信(IPC)的基石是Binder系統(tǒng),Binder系統(tǒng)的核心Binder驅(qū)動是C來實(shí)現(xiàn)的,對于應(yīng)用開發(fā)人員來說無疑晦澀難懂,而整個android框架是基于面向?qū)ο笏枷氲?,對于底層Binder驅(qū)動的操作細(xì)節(jié)全部隱藏,framework層提供了一個牛逼無比的Binder對象, 所以我們要實(shí)現(xiàn)進(jìn)程間通信(IPC)只需玩轉(zhuǎn)Binder對象即可。
成都創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的珙縣網(wǎng)站設(shè)計(jì)、移動媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
在android源碼中基于Binder對象的通信隨處可見,幾乎可以認(rèn)定為以 I 打頭的class,都具有進(jìn)程間通信能力,如:IServiceManager,IContentProvider等。
在源碼中實(shí)現(xiàn)的方式也可概括為兩種:
1. 通過aidl來生成對Binder的操作。
2.手動調(diào)用IBinder.transact編寫按照順序?qū)懭肱c讀出的parcel代碼實(shí)現(xiàn)。
第一種方法網(wǎng)上案例較多,不多說。第二種方法實(shí)現(xiàn)源碼參考:ActivityManagerNative,ActivityManagerProxy
關(guān)于第二種方法的實(shí)現(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; /** * 負(fù)責(zé)接收指令({@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); } /** * 當(dāng)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作為一個獨(dú)立進(jìn)程存在. */ 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)用遠(yuǎn)程服務(wù) */ private void testRemote(){ Intent intent = new Intent(MainActivity.this,RemoteCmdService.class); //綁定遠(yuǎn)程服務(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"); //當(dāng)然你也可以傳遞一個binder對象過去作為callback,這樣兩個進(jìn)程間就可以交互了。 // data.writeStrongBinder(IBinder binder); try { //調(diào)用遠(yuǎn)程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)站標(biāo)題:Android中非aidl實(shí)現(xiàn)進(jìn)程間通信(編寫順序的parcel寫入與讀出)
標(biāo)題URL:http://m.rwnh.cn/article40/phoseo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營銷推廣、商城網(wǎng)站、網(wǎng)站制作、App設(shè)計(jì)、云服務(wù)器、標(biāo)簽優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)