在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
網站標題:Android中非aidl實現進程間通信(編寫順序的parcel寫入與讀出)
標題URL:http://vcdvsql.cn/article40/phoseo.html
成都網站建設公司_創新互聯,為您提供全網營銷推廣、商城網站、網站制作、App設計、云服務器、標簽優化
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯