android IPC 機(jī)制

p, li { white-space: pre-wrap; }

IPC即Inter-Process Communication,含義為進(jìn)程間的通信或者跨進(jìn)程通信摹迷,是指兩個(gè)進(jìn)程之間進(jìn)行數(shù)據(jù)交換的過程涯呻。

android 中使用多進(jìn)程

android中使用多進(jìn)程很“簡單”搬味,簡單到只需要一行代碼就可以開啟一個(gè)進(jìn)程撑蚌。但是真正要用好多進(jìn)程還是不簡單的。android中使用進(jìn)程只需要在manfiest中進(jìn)行申明有巧,形式如下:

<activity
android:name="com.reoger.cc.hello"
android:process = "com.reoger.cc.hello.word"/>

當(dāng)然所宰,也可以process的屬性也可以設(shè)為以":"開始,例如

android:process =":remote"

表示運(yùn)行在當(dāng)前activity或者service的包名+.remote够傍。

Binder基礎(chǔ)

什么是binder甫菠?

Binder是Android中的一種跨進(jìn)程通信方式,Binder還可以理解為一種虛擬的物理設(shè)備冕屯,他的設(shè)備驅(qū)動(dòng)是/dev/binder寂诱,該通信方式在Linux中沒有。從Android Framework角度說安聘,Binder是ManagerService的橋梁痰洒。從Android應(yīng)用層角度來說,Binder是客戶端和服務(wù)端調(diào)用的Binder對(duì)象浴韭,通過這個(gè)Binder對(duì)象丘喻,客戶端就可以獲取服務(wù)端提供的服務(wù)或者數(shù)據(jù),這里的服務(wù)包括普通服務(wù)和基于AIDL的服務(wù)念颈。

使用基礎(chǔ)

本例將用aidl實(shí)現(xiàn)進(jìn)程間的通信泉粉,同時(shí)服務(wù)端將會(huì)每隔5s給訂閱圖書信息的人發(fā)一條信息,同時(shí)客戶端也可以其進(jìn)行訂閱和取消訂閱操作。
首先先給出使用實(shí)例的整體框架視圖嗡靡,如圖:

11-00-49.jpg

首先新建一個(gè)序列化的bean對(duì)象跺撼,命名為Book.java。

public class Book implements Parcelable {

private int id;
private String bookName;

public Book(int id, String bookName) {
this.id = id;
this.bookName = bookName;
}

@Override
public String toString() {
return "Book{" +
"id=" + id +
", bookName='" + bookName + '\'' +
'}';
}

protected Book(Parcel in) {
id = in.readInt();
bookName = in.readString();
}

public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}

@Override
public Book[] newArray(int size) {
return new Book[size];
}
};

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(bookName);
}
}

然后新建aidl文件夾叽躯,并在里面添加Book.aidl文件财边,代碼為:

// Book.aidl.aidl
package reoger.hut.test2;
parcelable Book;

記住一點(diǎn),在aidl中点骑,無論代碼是否存在于同一個(gè)包中,都需要進(jìn)行導(dǎo)入谍夭。
IBookManager.aidl的邏輯代碼如下:

// IBookManager.aidl
package reoger.hut.test2;

import reoger.hut.test2.Book;
import reoger.hut.test2.IOnNewBookArrivedArrivedListener;

interface IBookManager {
List<Book> getBookList();
void addBook(in Book book);

void registerListener(IOnNewBookArrivedArrivedListener listener);
void unRegisterListener(IOnNewBookArrivedArrivedListener listener);
}

然后是IOnNewBookArrivedArrivedListener.aidl的代碼黑滴,如下:

// IOnNewBookArrivedArrivedListener.aidl
package reoger.hut.test2;

import reoger.hut.test2.Book;

interface IOnNewBookArrivedArrivedListener {
void onNewBookArrived(in Book newBook);
}

接下來是我們服務(wù)端的實(shí)現(xiàn),這里我采用的是通過一個(gè)service來實(shí)現(xiàn)紧索,
BookManagerService.java的代碼如下袁辈。

public class BookManagerService extends Service {

private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<Book>();
private RemoteCallbackList<IOnNewBookArrivedArrivedListener> mListeners = new RemoteCallbackList<>();

private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);

private Binder mBinder = new IBookManager.Stub() {

@Override
public List<Book> getBookList() throws RemoteException {
return mBookList;
}

@Override
public void addBook(Book book) throws RemoteException {
mBookList.add(book);
}

/**
* 注冊(cè)監(jiān)聽
* @param listener 監(jiān)聽對(duì)象
* @throws RemoteException
*/
@Override
public void registerListener(IOnNewBookArrivedArrivedListener listener) throws RemoteException {
mListeners.register(listener);
Log.d("TAG", "增添監(jiān)聽成功");
}

@Override
public void unRegisterListener(IOnNewBookArrivedArrivedListener listener) throws RemoteException {
mListeners.unregister(listener);
Log.d("TAG", "增添監(jiān)聽成功");
}
};

@Override
public void onCreate() {
super.onCreate();
mBookList.add(new Book(1, "android"));
mBookList.add(new Book(2, "ios"));

new Thread(new ServiceWorker()).start();

}

public BookManagerService() {
}

@Override
public IBinder onBind(Intent intent) {
int check = checkCallingOrSelfPermission("reoger.hut.test2.permission.ACCESS_BOOK_SERVICE");
if(check == PackageManager.PERMISSION_DENIED){
Log.e("TAG","沒有對(duì)應(yīng)的權(quán)限,無法啟動(dòng)service");
return null;
}
return mBinder;
}

private class ServiceWorker implements Runnable {

@Override
public void run() {
while (!mIsServiceDestoryed.get()) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}

int bookId = mBookList.size() + 1;
Book book = new Book(bookId, "new Book# " + bookId);
onNewBookArrived(book);
}
}
}

private void onNewBookArrived(Book book) {

mBookList.add(book);
final int N = mListeners.beginBroadcast();
for (int i = 0; i < N; i++) {
IOnNewBookArrivedArrivedListener listener = mListeners.getBroadcastItem(i);
Log.d("TAG", "onNew Book Arrived ,notify listener :");
try {
if (listener != null) {
listener.onNewBookArrived(book);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
mListeners.finishBroadcast();
}
}

在manfiest文件中對(duì)service進(jìn)行申明珠漂,并將其設(shè)置在一個(gè)單獨(dú)的線程中運(yùn)行晚缩,代碼如下:

<service
android:name=".BookManagerService"
android:enabled="true"
android:exported="true"
android:process=":remote">
</service>

最后是我們的客戶端代碼,如下:

public class MainActivity extends AppCompatActivity {

private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {

switch (msg.what){
case 0x66:
Log.d("TAG","普天同慶 奔走相告"+msg.obj);
break;
default:
super.handleMessage(msg);
}
}
};

private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
bookManager = IBookManager.Stub.asInterface(service);

List<Book> list = null;
try {
list = bookManager.getBookList();
for (Book book : list) {
Log.d("TAG",book.toString());
}

Book book = new Book(3,"android 開發(fā)藝術(shù)探索");
bookManager.addBook(book);
List<Book> list2 = bookManager.getBookList();
for (Book book1 : list2) {
Log.d("TAG","--- "+book1.toString());
}

bookManager.registerListener(mOnNewBookArrivedListener);
} catch (RemoteException e) {
e.printStackTrace();
}

}

@Override
public void onServiceDisconnected(ComponentName name) {

}
};
private IBookManager bookManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,BookManagerService.class);
bindService(intent,connection, Context.BIND_AUTO_CREATE);
}

@Override
protected void onDestroy() {
if(bookManager != null && bookManager.asBinder().isBinderAlive()){
try {
Log.d("TAG","正在停止服務(wù)...");
bookManager.unRegisterListener(mOnNewBookArrivedListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
unbindService(connection);
super.onDestroy();

}

private IOnNewBookArrivedArrivedListener mOnNewBookArrivedListener = new IOnNewBookArrivedArrivedListener.Stub(){

@Override
public void onNewBookArrived(Book newBook) throws RemoteException {
mHandler.obtainMessage(0x66,newBook).sendToTarget();
}
};
}

最后運(yùn)行的結(jié)果主要通過打印的日志來顯示媳危。

11-12-51.jpg

通過日志信息荞彼,可以明確看到我們的服務(wù)端和客服端的確進(jìn)行的數(shù)據(jù)交換,并且服務(wù)端每隔5s發(fā)送一個(gè)信息給客戶端待笑。

關(guān)于AIDL鸣皂,有以下的幾點(diǎn)需要特別的注意:

  • AIDL支持基本的數(shù)據(jù)類型(除short以外的數(shù)據(jù)類型),也支持String和CharSequence和Parcelable暮蹂。對(duì)于List只支持ArrayList寞缝,對(duì)于Map只支持HshMap.
  • 如果AIDL文件中用到了自定義的Parcelable對(duì)象,必須新建一個(gè)和它同名的AIDL文件仰泻,并在其中聲明它為Parcelable類型荆陆。可以參考上面的示例 集侯。
  • AIDL中除了基本的數(shù)據(jù)類型被啼,其他類型的參數(shù)必須標(biāo)上方向:in,out或者inout,in表示輸入型參數(shù)浅悉,out表示輸出型參數(shù)趟据,inout表示輸入輸出型參數(shù)。
  • 在AIDL中术健,只支持方法汹碱,不支持聲明靜態(tài)常量。
  • AIDL包結(jié)構(gòu)在服務(wù)端和客戶端必須保持一致荞估,否運(yùn)行會(huì)出錯(cuò)咳促,這是因?yàn)榭蛻舳诵枰葱蛄谢?wù)端中和AIDL接口相關(guān)的所有類稚新。
  • AIDL方法是執(zhí)行在服務(wù)端的Binder線程池中的。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末跪腹,一起剝皮案震驚了整個(gè)濱河市褂删,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌冲茸,老刑警劉巖屯阀,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異轴术,居然都是意外死亡难衰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門逗栽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盖袭,“玉大人,你說我怎么就攤上這事彼宠■” “怎么了?”我有些...
    開封第一講書人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵凭峡,是天一觀的道長拙已。 經(jīng)常有香客問我,道長想罕,這世上最難降的妖魔是什么悠栓? 我笑而不...
    開封第一講書人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮按价,結(jié)果婚禮上惭适,老公的妹妹穿的比我還像新娘。我一直安慰自己楼镐,他們只是感情好癞志,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著框产,像睡著了一般凄杯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上秉宿,一...
    開封第一講書人閱讀 50,021評(píng)論 1 291
  • 那天戒突,我揣著相機(jī)與錄音,去河邊找鬼描睦。 笑死膊存,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播隔崎,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼今艺,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了爵卒?” 一聲冷哼從身側(cè)響起虚缎,我...
    開封第一講書人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎钓株,沒想到半個(gè)月后实牡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡轴合,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年铲掐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片值桩。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖豪椿,靈堂內(nèi)的尸體忽然破棺而出奔坟,到底是詐尸還是另有隱情,我是刑警寧澤搭盾,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布咳秉,位于F島的核電站,受9級(jí)特大地震影響鸯隅,放射性物質(zhì)發(fā)生泄漏澜建。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一蝌以、第九天 我趴在偏房一處隱蔽的房頂上張望炕舵。 院中可真熱鬧,春花似錦跟畅、人聲如沸咽筋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奸攻。三九已至,卻和暖如春虱痕,著一層夾襖步出監(jiān)牢的瞬間睹耐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來泰國打工部翘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留硝训,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像捎迫,于是被迫代替她去往敵國和親晃酒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,851評(píng)論 25 707
  • 一窄绒、 什么是IPC贝次? IPC,全稱Inter-Process Communication彰导,字面意思就是進(jìn)程間通信或...
    kuwork閱讀 7,955評(píng)論 0 8
  • 相關(guān)概念 序列化 Serialization(序列化)是一種將對(duì)象以一連串的字節(jié)描述的過程蛔翅;反序列化deseria...
    朔野閱讀 6,054評(píng)論 0 19
  • 唐以豐滿為美,瓶花史袁弘道位谋。主要花器盤花山析,碗花缸花,藍(lán)花掏父,筒花笋轨,瓶花,陶劍山赊淑,防滑墊爵政,首先學(xué)盆花。繪畫學(xué)園林學(xué)色彩...
    萱萱丫頭閱讀 282評(píng)論 0 0
  • 疏格網(wǎng)落魚相贈(zèng)陶缺,勿盡于食味自更钾挟。 莫等禽絕方棄器,應(yīng)明獸幼且交觥饱岸。 居得沃地安十里掺出,凈守吾心慕一清。 便讓天真歸野...
    樹先森6閱讀 392評(píng)論 5 3