最近從新溫習AIDL,發現技術這玩意就跟女人一樣,你過久沒去了解就會對它陌生卻又充滿新鮮感,然後查看網上的多半是胡扯,粘貼,我這裏整合下,裏面如果有錯誤望大家及時指出。廢話不多說,進入主題
首先來了解幾點常識:
1,一個Android應用程序對應一個進程;
2,Android應用程序進程間需要藉助IPC輕量級通訊協議;
3,切勿把線程和進程的概念搞混亂。一個進程可以包含多個線程,但是一個線程只會附屬於一個進程,可以理解成1對多的關係;
4,我們常見的Handler它是運行在UI主線程的,它負責的是異步處理數據,執行也是父線程和子線程;所以別把它和進程的概念混在一起。
進入主題,Android進程間的通訊:AIDL
這裏我以爲大家比較熟悉的C/S模式來講解整個通訊過程;但是我並沒有去新建立兩個項目了,就一個項目中,模擬進程通訊。不多說,先上項目圖
第一步,首先建立兩個aidl文件,forActivity.adil,forService.aidl 先來看看它們內部實現
package com.aidl;
interface forActivity{
void perAction();
void showString(int count);
}
package com.aidl;
import com.aidl.forActivity;
interface forService{
void registerTestCall(forActivity fa);
void callBack();
}
一看,哎喲,這裏面的編碼規則和java文件一樣,但是這個時候,我其他地方要調用怎麼辦?彆着急編譯器會默認在gen文件中生成對應.java文件
打開其中一個文件查看下其中源碼,先不詳細分析,慢慢來,就好比追女生一樣,要慢慢來,急不得
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: F:\\workspace\\AndroidAIDL\\src\\com\\example\\androidaidl\\aidl\\forActivity.aidl
*/
package com.example.androidaidl.aidl;
public interface forActivity extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.example.androidaidl.aidl.forActivity
{
private static final java.lang.String DESCRIPTOR = "com.example.androidaidl.aidl.forActivity";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.androidaidl.aidl.forActivity interface,
* generating a proxy if needed.
*/
public static com.example.androidaidl.aidl.forActivity asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.androidaidl.aidl.forActivity))) {
return ((com.example.androidaidl.aidl.forActivity)iin);
}
return new com.example.androidaidl.aidl.forActivity.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_performAction:
{
data.enforceInterface(DESCRIPTOR);
this.performAction();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.androidaidl.aidl.forActivity
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public void performAction() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_performAction, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_performAction = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void performAction() throws android.os.RemoteException;
}
第二步,新建mAIDLActivity.java文件,它模擬Client , 新建mAIDLService.java文件,它模擬Server;
先看看mAIDLActivity.java文件;
public class mAIDLActivity extends Activity {
private static final String TAG = "AIDLActivity";
private Button btnOk;
private Button btnCancel;
private Button btnCallBack;
private void Log(String str) {
android.util.Log.d(TAG, "------ " + str + "------");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnOk = (Button) findViewById(R.id.btn_ok);
btnCancel = (Button) findViewById(R.id.btn_cancel);
btnCallBack = (Button) findViewById(R.id.btn_callback);
btnOk.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
//綁定服務
Intent intent = new Intent(mAIDLActivity.this,mAIDLService.class);
bindService(intent, mcConnection, Context.BIND_AUTO_CREATE);
//startService(intent);
}
});
btnCancel.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
//取消綁定
unbindService(mcConnection);
/*unbindService(mConnection);
// stopService(intent);
*/ }
});
btnCallBack.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
//進程數據交互通訊
mService.callBack();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
forService mService;
forActivity mActivity = new forActivity.Stub() {
@Override
public void perAction() throws RemoteException {
Log("執行了啦");
}
@Override
public void showString(int count) throws RemoteException {
Log(count+"");
}
};
ServiceConnection mcConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = forService.Stub.asInterface(service);
try {
mService.registerTestCall(mActivity);
} catch (RemoteException e) {
}
}
};
}
這三個按鈕的作用我就不用說了吧,那麼明白的解釋在那裏還不懂的話,那你就別繼續看了,好好看看片,擼一管撤退吧。
先分析下上述文件
ServiceConnection mcConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = forService.Stub.asInterface(service);
try {
mService.registerTestCall(mActivity);
} catch (RemoteException e) {
}
}
};
ServiceConnection的使用和介紹我上一篇博文已經說了,大家可以去看看,說實在的就是如果不是研究AIDL,這傢伙我估計都不會看到.
看這句代碼
mService = forService.Stub.asInterface(service);
如果直接看的話不看源碼,我第一想到的就是實例化?強轉,?一大堆不靠譜的邏輯,作爲一個裝逼程序猿,如果遇到不知道的情況,別瞎猜,看源碼纔是王道.來打開forService.文件public interface forService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.aidl.forService
{
private static final java.lang.String DESCRIPTOR = "com.aidl.forService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.aidl.forService interface,
* generating a proxy if needed.
*/
public static com.aidl.forService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.aidl.forService))) {
return ((com.aidl.forService)iin);
}
return new com.aidl.forService.Stub.Proxy(obj);
}
這裏我們發現,Stub是forService的內部靜態抽象類,並且是繼承Binder和實例化了接口forService. 查看方法adInterface中的實現,它分三步來判斷
1,如果是空,直接給你空,讓你一邊玩去
2,如果傳入的Ibinder對象就是com.aidl.forService,因爲forService的繼承的IInterface,看IInterface的介紹Base class for Binder interfaces. When
defining a new interface, you must derive it from IInterface.那得列直接強轉成forService對象返回去,萬事大吉;
3.如果爲空,那就new一個新的,對象嘛.程序猿從來不缺.
下面繼續分析mAIDLService文件.不多說,先看源碼
public class mAIDLService extends Service {
@Override
public IBinder onBind(Intent intent) {
return mIBinder;
}
forActivity mActivity;
int count=0;
forService.Stub mIBinder = new forService.Stub() {
@Override
public void registerTestCall(forActivity fa) throws RemoteException {
mActivity = fa;
}
@Override
public void callBack() throws RemoteException {
mActivity.perAction();
mActivity.showString(++count);
}
};
}
它這裏相對就簡單了,基本不用多說了吧,這裏要注意的就是
public IBinder onBind(Intent intent) {
return mIBinder;
}
它返回的是當前new出來的forService對象.也就是我們前面ServiceConnection回調拿到的IBinder,
那這裏就慢慢明朗了,整個相互間的通訊也就清楚了,當按下btnCallBack按鈕的時候,首先會調用forService中的callBack方法,而callBack方法的實現中又調用了forActivity的perAction.通過forActivity和forService的這次握手,就達到了mAIDLActivity和mAIDLService一直及時通訊
說到這裏有朋友跟我說ContentProvider就可以直接實現兩個應用間的數據傳遞了啊,爲什麼還要用AIDL,我轉頭一聲呵呵,我列出下面幾個區分點估計大家就明白了
1.ContentProvider是單向性的,不及時的,而AIDL是雙向性,及時的。就這麼來說吧。ContentProvider就好比你看到一個漂亮的妹子,你一直看着她,但是她卻對你無視,你看不清楚她身體的變化;AIDL就是你看到那個漂亮的妹子,她也看着,你下面的異樣,立即反饋給了她,而你也看到了她嘴邊的異樣,這比喻好理解嗎?哈哈哈
好了中間有些地方如果有錯或者大家要補充的直接留言吧,然後懇請轉載的指明地址,不然又是一堆廢文到處跑。
下篇博文準備分析下IBinder和Binder!
參考網友論文
http://blog.csdn.net/saintswordsman/article/details/5130947
源碼下載