做網(wǎng)站的工資無(wú)限制訪問(wèn)國(guó)外的瀏覽器
問(wèn)題描述
做一款音樂(lè)播放應(yīng)用,播放服務(wù)是通過(guò)AIDL形式對(duì)外暴露,允許跨進(jìn)程調(diào)用且多個(gè)App同時(shí)操作音樂(lè)播放,偶現(xiàn)android.os.DeadObjectException
問(wèn)題
12-15 09:28:12.371: W/System.err(5412): android.os.DeadObjectException
12-15 09:28:12.372: W/System.err(5412): at android.os.BinderProxy.transactNative(Native Method)
12-15 09:28:12.372: W/System.err(5412): at android.os.BinderProxy.transact(Binder.java:496)
問(wèn)題分析
在使用aidl進(jìn)行進(jìn)程間通信時(shí),有時(shí)候在客戶端調(diào)用服務(wù)端的接口會(huì)拋出DeadObjectException異常,原因一般是由于某種原因服務(wù)端程序崩潰重啟或者服務(wù)對(duì)象由于內(nèi)存緊張被回收導(dǎo)致的
問(wèn)題解決
方案1
針對(duì)應(yīng)用開(kāi)發(fā),可以在服務(wù)端進(jìn)程啟動(dòng)的時(shí)候發(fā)個(gè)消息給客戶端,客戶端收到消息的時(shí)候重新進(jìn)行綁定操作,目的是為了同步客戶端和服務(wù)端的連接,客戶端進(jìn)程啟動(dòng)的時(shí)候也要綁定一次(注:在已經(jīng)連接的情況下,服務(wù)端由于某種原因進(jìn)程重啟了,如果客戶端沒(méi)有收到回調(diào),客戶端保存的連接不為空,這時(shí)調(diào)用服務(wù)端接口就會(huì)拋出DeadObjectException異常)
方案2
調(diào)用的對(duì)象不存在,因?yàn)樗贏pp進(jìn)程不存在或進(jìn)程崩潰,此時(shí)在底層回調(diào)時(shí)報(bào)錯(cuò)。
那么在調(diào)用對(duì)象之前,建議檢查是否存在此進(jìn)程。DeadObjectException異常出現(xiàn)是因?yàn)锳pp進(jìn)程不存在或進(jìn)程崩潰因此在底層回調(diào)時(shí)報(bào)錯(cuò)。進(jìn)程不存在或者進(jìn)程崩潰需要查看其他日志來(lái)定位。對(duì)于進(jìn)程崩潰的情況,也有可能部分原因是由于操作系統(tǒng)考慮到內(nèi)存、CPU、優(yōu)先級(jí)等指標(biāo),選擇殺死一個(gè)進(jìn)程得到資源。
ActivityManager activityManager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> pidsTask = activityManager.getRunningAppProcesses();for(int i = 0; i < pidsTask.size(); i++) {nameList.add(pidsTask.get(i).processName);idList.add(pidsTask.get(i).uid);}If(nameList.contains(“processName”)){// 進(jìn)程存在}else{// 進(jìn)程不存在}
方案2
進(jìn)行死亡監(jiān)聽(tīng)
1)在調(diào)用服務(wù)端接口的時(shí)候先進(jìn)行判斷bind是否還活著
if (mIMyAidlInterface != null && mIMyAidlInterface.asBinder().isBinderAlive()) {try {mIMyAidlInterface.startRecord();} catch (Exception e) {Log.e(TAG, "Exception");e.printStackTrace();}
}
2)注冊(cè)死亡代理
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {@Overridepublic void binderDied() { // 當(dāng)綁定的service異常斷開(kāi)連接后,自動(dòng)執(zhí)行此方法Log.e(TAG,"binderDied " );if (mIMyAidlInterface != null){// 當(dāng)前綁定由于異常斷開(kāi)時(shí),將當(dāng)前死亡代理進(jìn)行解綁 mIMyAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);// 重新綁定服務(wù)端的servicebindService(new Intent("com.service.bind"),mMyServiceConnection,BIND_AUTO_CREATE); }}
};
3)在service綁定成功后,調(diào)用linkToDeath()注冊(cè)進(jìn)service,當(dāng)service發(fā)生異常斷開(kāi)連接后會(huì)自動(dòng)調(diào)用binderDied()
public void onServiceConnected(ComponentName name, IBinder service) { //綁定成功回調(diào)Log.d(TAG, "onServiceConnected");mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); //獲取服務(wù)端提供的接口try {// 注冊(cè)死亡代理if(mIMyAidlInterface != null){Log.d(TAG, mIMyAidlInterface.getName());service.linkToDeath(mDeathRecipient, 0); } } catch (RemoteException e) {e.printStackTrace();}
}