多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > AIDL簡單使用

AIDL簡單使用

來源:程序員人生   發布時間:2016-11-20 16:41:28 閱讀次數:3317次

AIDL是Android Interface Definition Language, 顧名思義,它主要就是用來定義接口的1種語言。Android提供AIDL主要用來進程間通訊。

AIDL的功能來看,它主要的利用場景就是IPC。雖然同1個進程中的client-service也能夠通過AIDL定義接口來進行通訊,但這并沒有發揮AIDL的主要功能。 概括來講:

  1. 如果不需要IPC,那就直接實現通過繼承Binder類來實現客戶端和服務端之間的通訊。
  2. 如果確切需要IPC,但是無需處理多線程,那末就應當通過Messenger來實現。Messenger保證了消息是串行處理的,其內部其實也是通過AIDL來實現。
  3. 在有IPC需求,同時服務端需要并發處理多個要求的時候,使用AIDL才是必要的

AIDL的簡單使用步驟以下:

  1. 編寫.AIDL文件,定義需要的接口
  2. 實現定義的接口
  3. 將接口暴露給客戶端調用

下面在AS上創建1個工程來使用1下:

創建Aidl文件:

創建完后,可以看到aidl接口文件里面已為我們提供了案例:

// IMyAidlInterface.aidl package com.example.aidltest; // Declare any non-default types here with import statements interface IMyAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); }
這里先說下AIDL支持以下所述的數據類型:

  • 所有的基本類型(int、float等)
  • String
  • CharSequence
  • List
  • Map

如果要使用自定義的類型,必須實現Parcelable接口才能進行進程間通訊。

下面自定義HelloMsg類:

public class HelloMsg implements Parcelable { private String name; private int age; public HelloMsg(String name, int age) { this.name = name; this.age = age; } protected HelloMsg(Parcel in) { name = in.readString(); age = in.readInt(); } public static final Creator<HelloMsg> CREATOR = new Creator<HelloMsg>() { @Override public HelloMsg createFromParcel(Parcel in) { return new HelloMsg(in); } @Override public HelloMsg[] newArray(int size) { return new HelloMsg[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeInt(age); } @Override public String toString() { return "HelloMsg{" + "name='" + name + '\'' + ", age=" + age + '}'; } }

定義好HelloMsg.java以后,還需要新增1個與其對應的AIDL文件。那末一樣依照剛才的步驟右鍵src文件夾,添加1個名為IHelloMsgInterface的AIDL文件。

// IHelloMsgInterface.aidl package com.example.aidltest; parcelable HelloMsg;

注意到parcelable的首字母是小寫的,這算是AIDL1個特殊的地方。
接下來還需要修改IMyAidlInterface.aidl文件,以下:

// IMyAidlInterface.aidl package com.example.aidltest; import com.example.aidltest.HelloMsg; interface IMyAidlInterface { HelloMsg sayHello(); }


 即使IMyAidlInterface.aidl和IHelloMsgInterface.aidl位于同1個包下,這里的import是必須要有的。這也是AIDL1個特殊的地方。


 注意:build以后發現會報錯,將IHelloMsgInterfece.aidl重命名為HelloMsg.aidl便可。


build成功以后會在build/generated/souce/aidl/debug目錄下生成IMyAidlInterface文件??梢源笾率炝曄略撐募膬热?,對掌握android binder機制很有幫助

public interface IMyAidlInterface extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.example.aidltest.IMyAidlInterface { private static final java.lang.String DESCRIPTOR = "com.example.aidltest.IMyAidlInterface"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.example.aidltest.IMyAidlInterface interface, * generating a proxy if needed. */ public static com.example.aidltest.IMyAidlInterface asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.example.aidltest.IMyAidlInterface))) { return ((com.example.aidltest.IMyAidlInterface)iin); } return new com.example.aidltest.IMyAidlInterface.Stub.Proxy(obj); }


這里有個內部類Stub,它繼承系統Binder類和實現IMyAidlInterface接口。另外還提供了asInterface()接口,這個方法接受1個遠端Binder對象,并將其轉化成Stub對應的接口對象并返回。在構造方法調用Binder中的attachInterface方法把當前服務對象和描寫符進行關聯。在asInterface方法中會調用queryLocalInterface查詢,如果不在同1進程就返回null,這個時候就返回Proxy對象。

上面看完了Stub類以后,發現他實際上是遠端服務Binder對象的1個中間者,用來和客戶端進行交互的,下面再來看1下Proxy類:

private static class Proxy implements com.example.aidltest.IMyAidlInterface { 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; } /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(anInt); _data.writeLong(aLong); _data.writeInt(((aBoolean)?(1):(0))); _data.writeFloat(aFloat); _data.writeDouble(aDouble); _data.writeString(aString); mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public com.example.aidltest.HelloMsg sayHello() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); com.example.aidltest.HelloMsg _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_sayHello, _data, _reply, 0); _reply.readException(); if ((0!=_reply.readInt())) { _result = com.example.aidltest.HelloMsg.CREATOR.createFromParcel(_reply); }

可以看到里面有個mRemote對象,它是服務端傳遞過來的binder對象。調用transact方法后會調用上面Stub中的onTransact方法。這里其實用了靜態代理模式,Proxy就是遠端傳遞過來的binder的本地代理??梢岳斫鉃榭蛻粽鎮€中間者。

Stub類是服務真個中間者,1般是實現了AIDL接口類型和繼承了Binder類,具有將Binder對象轉化成原生對象的能力
Proxy類是客戶真個中間者,1般是實現了AIDL接口類型

下面實現服務真個接口,定義RemoteService.java

public class RemoteService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return new IMyAidlInterface.Stub() { @Override public HelloMsg sayHello() throws RemoteException { return new HelloMsg("wuliqing", 28); } }; } }

客戶端調用服務端接口代碼以下:

public class MainActivity extends AppCompatActivity { private IMyAidlInterface iMyAidlInterface = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override protected void onStart() { super.onStart(); Intent intent = new Intent(this, RemoteService.class); bindService(intent, serviceConnection, BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); unbindService(serviceConnection); } private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { iMyAidlInterface = null; } }; public void onClickToSayHello(View view) { if (iMyAidlInterface != null) { try { HelloMsg helloMsg = iMyAidlInterface.sayHello(); Toast.makeText(this, helloMsg.toString(), Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show(); } } } }

onServiceConnected()回調中,我們使用IMyAidlInterface.Stub.asInterface(service)方法返回我們的接口的援用。接著客戶端就能夠通過它來對服務端發送要求了。

在這里我為RemoteService設置了process屬性,讓它運行在與默許進程不同的進程中。

<service android:name="RemoteService" android:process=":remote" />

從上圖可看出客戶端和服務運行在兩個進程當中。

然后點擊按鈕,成功返回結果。

最后給出1張流程圖,加深印象:


關于AIDL和binder機制可參考下面文章:

Android中AIDL的基本用法

Binder機制和遠程服務調用機制分析

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 2018久久久国产精品 | 九色亚洲 | 欧美 日韩 中文字幕 | 国产欧美日韩一区 | 亚洲精品第一区二区三区 | 午夜理伦三级在线观看 | 高清完整视频在线播放 | 日韩中文视频 | 日本aa在线| 久久精品中文字幕极品 | 国产成人免费片在线视频观看 | 欧美亚洲另类在线 | 国产精品v欧美精品v日韩 | 自拍视频网 | 成人自拍网站 | 在线免费观看成年人视频 | 成人欧美一级毛片免费观看 | 亚洲 [12p] | 尤物视频最新网址 | 夜夜骑天天干 | 性色a∨人人爽网站 | 国产免费看网站v片不遮挡 国产免费全部免费观看 | 国产精品v在线播放观看 | 欧美网站色 | 怡红院免费的全部视频国产a | 羞羞网站在线观看 | 午夜dj视频在线高清免费 | 一级毛片视频在线观看 | 手机在线精品视频每日更新 | 综合色网站 | 日韩二区 | 亚洲最大成人 | 精品三级内地国产在线观看 | 日本无卡码高清免费观看 | 亚洲欧美韩日 | 精品日韩欧美一区二区三区在线播放 | 国产xxxxx片免费观看 | 亚洲狠狠狠一区二区三区 | 中文字幕乱码视频 | 亚洲欧美精品一中文字幕 | 欧美激情一区二区 |