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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 跨进程通信: AIDL

發布時間:2024/9/30 Android 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 跨进程通信: AIDL 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概念

在Android上一個進程通常是無法訪問另一個進程的內存,而AIDL翻譯過來就是Android 接口定義語言,你可以你利用它定義客戶端和服務端進程間通信相互認可的編程接口。

適用范圍

只有允許不同應用的客戶端用IPC方式訪問服務,并且想要在服務中處理多線程問題時,才有必要適用AIDL。如果想執行IPC,但不需要處理多線程,可以考慮使用Messenger類實現。如果不需要執行跨不同應用的并發IPC,可以通過實現一個Binder來實現。

使用

考慮這樣一個場景:client 客戶端跨進程訪問 server 客戶端,流程如下

server 客戶端接受請求通知,訪問遠程服務器返回數據,并將數據通知給client 客戶端 , 下面我們來看看如何一步步實現該功能

創建server 客戶端

1、創建.aidl文件

新建一個名為server的工程,這里面我們創建三個aidl文件
IRomteService.aidl 定義請求接口
ICallBack.aidl 自定義回調接口
MyBean.aidl 自定義的對象
MyBean.java 自定義對象類(必須實現Parcelable接口)

注意:MyBean.aidl和MyBean.java要保證在同一個包路徑下

// IRomteService.aidl package com.aidlserver.myaidl; import com.aidlserver.myaidl.MyBean; import com.aidlserver.myaidl.ICallBack; // Declare any non-default types here with import statementsinterface IRemoteService {void requestServer(in MyBean param, in ICallBack callback); } // MyBean.aidl package com.aidlserver.myaidl; import com.aidlserver.myaidl.MyBean; // Declare any non-default types here with import statementsparcelable MyBean; // ICallBack.aidl package com.aidlserver.myaidl; // Declare any non-default types here with import statementsinterface ICallBack {/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/void onResult(String result); } package com.aidlserver.myaidl;import android.os.Parcel; import android.os.Parcelable;public class MyBean implements Parcelable {public int mId;public String mName;public MyBean() {}protected MyBean(Parcel in) {readFromParcel(in);}public static final Creator<MyBean> CREATOR = new Creator<MyBean>() {@Overridepublic MyBean createFromParcel(Parcel in) {return new MyBean(in);}@Overridepublic MyBean[] newArray(int size) {return new MyBean[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeInt(mId);dest.writeString(mName);}public void readFromParcel(Parcel in) {mId = in.readInt();mName = in.readString();}@Overridepublic String toString() {return "id:" + mId + " name:" + mName;} }

2、創建Service(關鍵部分)

創建一個RemoteService服務,它是連接外部應用和遠程服務器的樞紐,代碼如下

package com.aidlserver.service;import android.app.Service; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; import android.support.annotation.Nullable; import android.util.Log;import com.aidlserver.myaidl.ICallBack; import com.aidlserver.myaidl.IRemoteService.Stub; import com.aidlserver.myaidl.MyBean;public class RemoteService extends Service {private static final String TAG = RemoteService.class.getSimpleName();private static final String CLIENT_PACKAGE_NAME = "com.client";private static final String MYSELF_PACKAGE_NAME = "com.aidlserver";private Object mLock = new Object();@Overridepublic void onCreate() {super.onCreate();Log.d(TAG, TAG + "onCreate");}private Stub mBinder = new Stub() {@Overridepublic void requestServer(MyBean param, final ICallBack callback) throws RemoteException {synchronized (mLock) {//模擬耗時請求開啟線程請求服務端Log.d(TAG, "requestServer param:" + param.toString());new Thread(new Runnable() {@Overridepublic void run() {if (callback != null) {try {callback.onResult("I was server response . hello client");} catch (RemoteException e) {e.printStackTrace();}}}}).start();}}//該方法可以對外部應用做認證@Overridepublic boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {String[] stringArray = RemoteService.this.getPackageManager().getPackagesForUid(getCallingUid());String packageName = null;if (stringArray != null && stringArray.length > 0) {packageName = stringArray[0];}boolean result = false;//只有"com.client"應用及其自己能訪問if (!CLIENT_PACKAGE_NAME.equals(packageName)&& !MYSELF_PACKAGE_NAME.equals(packageName)) {result = false;} else {result = super.onTransact(code, data, reply, flags);}Log.d(TAG, "packageName:" + packageName + " result:" + result);return result;}};@Nullable@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG, "=====onBind=====");//返回自定義的IRemoteService的存根(Sub)return mBinder;}@Overridepublic void unbindService(ServiceConnection conn) {super.unbindService(conn);Log.d(TAG, "=====unbindService=====");}@Overridepublic void onDestroy() {super.onDestroy();Log.d(TAG, "=====onDestroy=====");} }

3、注冊Service

在清單文件加入如下代碼

<application><serviceandroid:name=".service.RemoteService"android:enabled="true"android:exported="true"android:process=":remote"></service> </application>

4、編寫客戶端調用代碼

新建一個Activity,
完整Activity代碼如下,

package com.aidlserver;import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView;import com.aidlserver.myaidl.ICallBack; import com.aidlserver.myaidl.IRemoteService; import com.aidlserver.myaidl.MyBean; import com.aidlserver.service.RemoteService;public class MainActivity extends AppCompatActivity {private static final String TAG = MainActivity.class.getSimpleName();private Button mBtnBindService;private Button mBtnUnbindService;private TextView mTextView;private ServiceConnection mServiceConnection;private boolean mIsBinded = false;private IRemoteService mRomteService;/*** 請求回調存根*/private ICallBack.Stub mCallBack = new ICallBack.Stub() {//回調通知結果@Overridepublic void onResult(final String result) throws RemoteException {Log.d(TAG, "client onResult function run in " + Process.myPid() + " Process" + "thread:" + Thread.currentThread().getName());mTextView.post(new Runnable() {@Overridepublic void run() {mTextView.setText(result);}});}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//綁定服務按鈕mBtnBindService = (Button) findViewById(R.id.btn_bind_service);mBtnBindService.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//綁定服務Intent intent = new Intent(MainActivity.this, RemoteService.class);bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);//5.0以后必須都是顯式綁定,隱式綁定會報錯,如果是外部應用調用可以使用下面注釋代碼,綁定服務/**Intent intent = new Intent();intent.setComponent(new ComponentName("com.aidlserver", "com.aidlserver.service.RemoteService"));bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);*/}});//解綁服務按鈕mBtnUnbindService = (Button) findViewById(R.id.btn_unbind);mBtnUnbindService.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (mIsBinded && mRomteService != null) {//解綁服務unbindService(mServiceConnection);mIsBinded = false;mTextView.setText("unbinded");}}});mTextView = (TextView) findViewById(R.id.tv_content);mServiceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, final IBinder service) {Log.d(TAG, "service connected");mTextView.setText("onServiceConnected");mIsBinded = true;mRomteService = IRemoteService.Stub.asInterface(service);MyBean param = new MyBean();param.mId = 123;param.mName = "I was android client";try {//開始請求mRomteService.requestServer(param, mCallBack);} catch (RemoteException e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {mIsBinded = false;mRomteService = null;mTextView.setText("unBind");Log.d(TAG, "onServiceDisconnected");}};} }


現在我們運行server app 效果如下:

創建Client 客戶端

client客戶端代碼就比較簡單了,
我們只要把server工程里面
ICallBack.aidl
IRemoteService.aidl
MyBean.aidl
MyBean.java移到和server同一個包路徑就可以了,
client客戶端調用的activity和server客戶端的activity幾乎一樣

源碼下載:
AIDL Demo

總結

以上是生活随笔為你收集整理的Android 跨进程通信: AIDL的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。