日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android之使用AIDL时的跨进程回调—Server回调Client

發(fā)布時(shí)間:2023/12/4 Android 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android之使用AIDL时的跨进程回调—Server回调Client 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

首先建立在server端建立兩個(gè)aidl文件

ITaskCallback.aidl 用于存放要回調(diào)client端的方法

package com.cmcc.demo.server; interface ITaskCallback { void actionPerformed(int actionId); }
ITaskBinder.aidl 用于存放供給client端調(diào)用的方法

package com.cmcc.demo.server; import com.cmcc.demo.server.ITaskCallback; interface ITaskBinder { boolean isTaskRunning(); void stopRunningTask(); void registerCallback(ITaskCallback cb); void unregisterCallback(ITaskCallback cb); }

接著建立服務(wù)端,要實(shí)現(xiàn)回調(diào),需要新建RemoteCallbackList對(duì)象(一個(gè)存儲(chǔ)回調(diào)對(duì)象的列表),通過(guò)類似發(fā)送廣播的形式來(lái)實(shí)現(xiàn)回調(diào)

MyService.java

package com.cmcc.demo.server; import com.cmcc.demo.server.ITaskBinder; import com.cmcc.demo.server.ITaskCallback; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.Log; public class MyService extends Service { private static final String TAG = "aidltest"; @Override public void onCreate() { printf("service create"); } @Override public void onStart(Intent intent, int startId) { printf("service start id=" + startId); callback(startId); } @Override public IBinder onBind(Intent t) { printf("service on bind"); return mBinder; } @Override public void onDestroy() { printf("service on destroy"); super.onDestroy(); } @Override public boolean onUnbind(Intent intent) { printf("service on unbind"); return super.onUnbind(intent); } public void onRebind(Intent intent) { printf("service on rebind"); super.onRebind(intent); } private void printf(String str) { Log.v(TAG, "###################------ " + str + "------"); } void callback(int val) { final int N = mCallbacks.beginBroadcast(); for (int i=0; i<N; i++) { try { mCallbacks.getBroadcastItem(i).actionPerformed(val); } catch (RemoteException e) { // The RemoteCallbackList will take care of removing // the dead object for us. } } mCallbacks.finishBroadcast(); } private final ITaskBinder.Stub mBinder = new ITaskBinder.Stub() { public void stopRunningTask() { } public boolean isTaskRunning() { return false; } public void registerCallback(ITaskCallback cb) { if (cb != null) { mCallbacks.register(cb); } } public void unregisterCallback(ITaskCallback cb) { if(cb != null) { mCallbacks.unregister(cb); } } }; final RemoteCallbackList <ITaskCallback>mCallbacks = new RemoteCallbackList <ITaskCallback>(); } 最后建立客戶端,使用aidl,實(shí)現(xiàn)回調(diào)方法。

MyActivity.java

package com.cmcc.demo; 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.RemoteException; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import com.cmcc.demo.server.*; public class MyActivity extends Activity { private static final String TAG = "aidltest"; private Button btnOk; private Button btnCancel; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.test_service); btnOk = (Button)findViewById(R.id.btn_ok); btnCancel = (Button)findViewById(R.id.btn_cancel); btnOk.setText("Start Service"); btnCancel.setText("Stop Service"); btnCancel.setEnabled(false); btnOk.setOnClickListener(new OnClickListener() { public void onClick(View v) { onOkClick(); } }); btnCancel.setOnClickListener(new OnClickListener() { public void onClick(View v) { onCancelClick(); } }); } void onOkClick() { printf("send intent to start"); Bundle args = new Bundle(); Intent intent = new Intent("com.cmcc.demo.IMyService"); intent.putExtras(args); startService(intent); //bindService(intent, mConnection, Context.BIND_AUTO_CREATE); btnCancel.setEnabled(true); } void onCancelClick() { printf("send intent to stop"); //unbindService(mConnection); Intent intent = new Intent("com.cmcc.demo.IMyService"); stopService(intent); btnCancel.setEnabled(false); } private void printf(String str) { Log.v(TAG, "###################------ " + str + "------"); } ITaskBinder mService; private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mService = ITaskBinder.Stub.asInterface(service); try { mService.registerCallback(mCallback); } catch (RemoteException e) { } } public void onServiceDisconnected(ComponentName className) { mService = null; } }; private ITaskCallback mCallback = new ITaskCallback.Stub() { public void actionPerformed(int id) { printf("callback id=" + id); } }; }
總結(jié)一下aidl的使用

AIDL的創(chuàng)建方法:?
AIDL語(yǔ)法很簡(jiǎn)單,可以用來(lái)聲明一個(gè)帶一個(gè)或多個(gè)方法的接口,也可以傳遞參數(shù)和返回值。由于遠(yuǎn)程調(diào)用的需要, 這些參數(shù)和返回值并不是任何類型.下面是些AIDL支持的數(shù)據(jù)類型:?
1. 不需要import聲明的簡(jiǎn)單Java編程語(yǔ)言類型(int,boolean等)?
2. String, CharSequence不需要特殊聲明?

3. List, Map和Parcelables類型, 這些類型內(nèi)所包含的數(shù)據(jù)成員也只能是簡(jiǎn)單數(shù)據(jù)類型, String等其他比支持的類型.?
(?
(另外: 我沒(méi)嘗試Parcelables, 在Eclipse+ADT下編譯不過(guò), 或許以后會(huì)有所支持).?
下面是AIDL語(yǔ)法:?
// 文件名: SomeClass.aidl // 文件可以有注釋, 跟java的一樣 // 在package以前的注釋, 將會(huì)被忽略. // 函數(shù)和變量以前的注釋, 都會(huì)被加入到生產(chǎn)java代碼中. package com.cmcc.demo;?
// import 引入語(yǔ)句 import com.cmcc.demo.ITaskCallback;?

interface ITaskBinder {?
//函數(shù)跟java一樣, 可以有0到多個(gè)參數(shù) ,可以有一個(gè)返回值 boolean isTaskRunning();?
void stopRunningTask(); //參數(shù)可以是另外的一個(gè)aidl定義的接口 void registerCallback(ITaskCallback cb);?
void unregisterCallback(ITaskCallback cb);?
//參數(shù)可以是String, 可以用in表入輸入類型, out表示輸出類型.?
int getCustomerList(in String branch, out String customerList);?
}?

實(shí)現(xiàn)接口時(shí)有幾個(gè)原則:?
.拋出的異常不要返回給調(diào)用者. 跨進(jìn)程拋異常處理是不可取的.?
.IPC調(diào)用是同步的如果你知道一個(gè)IPC服務(wù)需要超過(guò)幾毫秒的時(shí)間才能完成地話,你應(yīng)該避免在Activity的主線程中調(diào)用。 也就是IPC調(diào)用會(huì)掛起應(yīng)用程序?qū)е陆缑媸ロ憫?yīng). 這種情況應(yīng)該考慮單起一個(gè)線程來(lái)處理.?
.不能在AIDL接口中聲明靜態(tài)屬性。?

IPC的調(diào)用步驟:?
1. 聲明一個(gè)接口類型的變量,該接口類型在.aidl文件中定義。?
2. 實(shí)現(xiàn)ServiceConnection。?
3. 調(diào)用ApplicationContext.bindService(),并在ServiceConnection實(shí)現(xiàn)中進(jìn)行傳遞.?
4. 在ServiceConnection.onServiceConnected()實(shí)現(xiàn)中,你會(huì)接收一個(gè)IBinder實(shí)例(被調(diào)用的Service). 調(diào)用 YourInterfaceName.Stub.asInterface((IBinder)service)將參數(shù)轉(zhuǎn)換為YourInterface類型。?
5. 調(diào)用接口中定義的方法。 你總要檢測(cè)到DeadObjectException異常,該異常在連接斷開(kāi)時(shí)被拋出。它只會(huì)被遠(yuǎn)程方法拋出。?
6. 斷開(kāi)連接,調(diào)用接口實(shí)例中的ApplicationContext.unbindService()?




總結(jié)

以上是生活随笔為你收集整理的Android之使用AIDL时的跨进程回调—Server回调Client的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。