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

成都創(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)時(shí)代的珙縣網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
在android源碼中基于Binder對(duì)象的通信隨處可見(jiàn),幾乎可以認(rèn)定為以 I 打頭的class,都具有進(jìn)程間通信能力,如:IServiceManager,IContentProvider等。
在源碼中實(shí)現(xiàn)的方式也可概括為兩種:
1. 通過(guò)aidl來(lái)生成對(duì)Binder的操作。
2.手動(dòng)調(diào)用IBinder.transact編寫按照順序?qū)懭肱c讀出的parcel代碼實(shí)現(xiàn)。
第一種方法網(wǎng)上案例較多,不多說(shuō)。第二種方法實(shí)現(xiàn)源碼參考:ActivityManagerNative,ActivityManagerProxy
關(guān)于第二種方法的實(shí)現(xiàn)本人做了一個(gè)demo,請(qǐng)看以下代碼。
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();
/**
* 存儲(chǔ)所有指令處理器
* map.key = {@link CmdCode}
*/
private HashMap<Integer,Callback> mCallbacks = new HashMap<Integer, Callback>();
/**
* 針對(duì)某個(gè)指令的處理
* @see #addCallback
* @see #removeCallback
*/
public interface Callback {
/**
* @param code 請(qǐng)求指令集{@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)}時(shí),將會(huì)回調(diào)本方法。
*/
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
dispatch(code,data,reply);
return true;
}
/**
* 得到某個(gè)指令處理器并調(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;
}
/**
* 針對(duì)某一個(gè)指令,如:請(qǐng)求指令集{@link CmdCode.Request},響應(yīng) 指令集{@link CmdCode.Response}
* 添加回調(diào)處理
* @param code 指令編碼
* @param callback 針對(duì)某一個(gè)指定的處理 {@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 {
/**
* 每個(gè)parcel的頭
*/
public static final int PARCEL_HEAD = 0xffff;
public static final int RESULT_SUCCESS = 0x0001;
public static final int RESULT_ERROR = 0x0002;
}
/**
* 請(qǐng)求指令集
*/
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作為一個(gè)獨(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)然你也可以傳遞一個(gè)binder對(duì)象過(guò)去作為callback,這樣兩個(gè)進(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://chinadenli.net/article40/phoseo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營(yíng)銷推廣、商城網(wǎng)站、網(wǎng)站制作、App設(shè)計(jì)、云服務(wù)器、標(biāo)簽優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)