Android Studio Service AIDL 詳解
公司產品之前IM這塊存在很多問題,訊息到達率低,加上協議上有些問題,丟訊息頻繁,所以需要重構IM,AIDL不能解決以上問題。好吧!那AIDL可以解決什麼問題?什麼是AIDL?
什麼是AIDL?
AIDL
是 Android Interface definition language
的縮寫,它是一種Android
內部程式通訊介面的描述語言,通過它我們可以定義程式間的通訊介面
AIDL可以解決什麼問題?
- 可以實現多個應用程式共享同一個Service的功能,比如:IM服務可以提供給多個APP使用,先在推送基本都是採取這種方案
- 可以跨程式呼叫服務裡的方法
Android Studio AIDL 實戰
大部分文章介紹都是在eclipse下介紹的,現在 Android Studio 作為開發工具比較普及了,所以我在Android Studio 下介紹(其實區別不大)。
言歸正傳,我們需要使用Android Studio實現一個遠端Service,並且建立AIDL進行通訊。
搭建了簡單的Service框架
1.繼承Service
package name.quanke.aidldemo; import android.app.Service; import android.content.Intent; import android.os.IBinder; /** * * Created by http://quanke.name on 16/7/23. */ public class PushService extends Service { public PushService() { } @Override public IBinder onBind(Intent intent) { return new LibHandler(); } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } }
2.在AndroidManifest.xml裡註冊
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="name.quanke.aidldemo"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:name=".App" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <service android:name=".PushService" android:enabled="true" android:process=":push" android:exported="true"> </service> </application> </manifest>
建立AIDL
1.建立AIDL資料夾
1.建立AIDL資料夾
2.建立AIDL檔案
2.建立AIDL檔案
3.編寫AIDL檔案
// IHandler.aidl package name.quanke.aidldemo; // Declare any non-default types here with import statements interface IHandler { void connect(); }
4.AIDL檔案 生成介面
4.AIDL檔案 生成介面
生成後的樣子
4.AIDL檔案 生成後的樣子
5.編寫客戶端 ServiceConnection
package name.quanke.aidldemo; import android.app.Application; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; /** * Created by quanke on 16/7/23. */ public class PushManager { private static final String TAG = "PushManager.class"; private IHandler iHandler; private static PushManager ourInstance = new PushManager(); public static PushManager getInstance() { return ourInstance; } private PushManager() { } public void init(Application app){ Intent binderIntent = new Intent(app,PushService.class); app.bindService(binderIntent, serviceConnection, Context.BIND_AUTO_CREATE); } public void connect(){ try { //通過AIDL遠端呼叫 Log.d(TAG,"++start Remote++"); iHandler.connect(); } catch (RemoteException e) { e.printStackTrace(); } } private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { iHandler = IHandler.Stub.asInterface(service); //連線成功調動 } @Override public void onServiceDisconnected(ComponentName name) { //斷開連線呼叫 } }; }
6.編寫服務端實現connect方法
package name.quanke.aidldemo; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; /** * * Created by quanke on 16/7/23. */ public class LibHandler extends IHandler.Stub{ @Override public void connect() throws RemoteException { Log.d("","connect()"); } @Override public IBinder asBinder() { return null; } }
以上實現了簡單的連線,接下來我們實現傳遞自定義型別
傳遞自定義的型別
AIDL預設支援的型別包括Java基本型別(int、long、boolean等),和(String、List、Map、CharSequence),如果要傳遞自定義的型別需要實現android.os.Parcelable介面。自己寫了一個實體類public class Message implements Parcelable。
package name.quanke.aidldemo.model; import android.os.Parcel; import android.os.Parcelable; /** * * Created by quanke on 16/7/23. */ public class Message implements Parcelable { private long id; private String content; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } @Override public String toString() { return "Message{" + "id=" + id + ", content='" + content + '\'' + '}'; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(this.id); dest.writeString(this.content); } public Message() { } protected Message(Parcel in) { this.id = in.readLong(); this.content = in.readString(); } public static final Creator<Message> CREATOR = new Creator<Message>() { @Override public Message createFromParcel(Parcel source) { return new Message(source); } @Override public Message[] newArray(int size) { return new Message[size]; } }; }
修改IHandler
// IHandler.aidl package name.quanke.aidldemo; // Declare any non-default types here with import statements import name.quanke.aidldemo.model.Message; interface IHandler { void connect(); void sendMessage(Message message); }
編譯專案,報錯
/Users/quanke/Dev/android/src/AIDLDemo/app/src/main/aidl/name/quanke/aidldemo/IHandler.aidl Error:(6) couldn't find import for class name.quanke.aidldemo.model.Message Error:Execution failed for task ':app:compileDebugAidl'. > java.lang.RuntimeException: com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/Users/quanke/Dev/android/tools/android-sdks/build-tools/23.0.3/aidl'' finished with non-zero exit value 1 Information:BUILD FAILED
因為自定義型別不僅要定義實現android.os.Parcelable介面的類,還得為該實現類定義一個aidl檔案,如下:
自定義類aidl檔案
// IHandler.aidl package name.quanke.aidldemo.model; // Declare any non-default types here with import statements import name.quanke.aidldemo.model.Message; parcelable Message ;
切記
自定型別aidl檔名字、路徑需要和自定義類名字、路徑保持一致,
編譯專案,還是報錯
parameter 1: 'Message message' can be an out parameter, so you must declare it as in, out or inout.
AIDL
不是 Java。它是真的很接近,但它不是 Java。
Java 引數沒有方向的概念,AIDL 引數有方向,引數可以從客戶端傳到服務端,再返回來。
如果sendMessage
方法的message
引數是純粹的輸入引數—這意味著是從客戶端到伺服器的資料,你需要在AIDL宣告:
void sendMessage(in Message message);
如果sendMessage
方法的message
引數是純粹的輸出-這意味著它的資料是通過從伺服器到客戶端,使用:
void sendMessage(out Message message);
如果sendMessage
方法的message
引數是輸入也是輸出-客戶端的值在服務可能會修改,使用:
void sendMessage(inout Message message);
總結
Android Studio Service AIDL 詳解 就到這裡,現在應該可以使用AIDL實現想要的功能了,實現簡答的AIDL很簡單,主要是在自定義型別的時候,有幾個坑注意就好。
原始碼地址:
https://github.com/quanke/AIDLDemo.git
有什麼問題歡迎留言。
如果喜歡請關注我,讚我,來撫平我虛榮的心
相關文章
- Android AIDL SERVICE 雙向通訊 詳解AndroidAI
- Android AIDL使用詳解AndroidAI
- Android:Service詳解Android
- android service詳解Android
- Android下AIDL機制詳解AndroidAI
- Android 程式間通訊 AIDL詳解AndroidAI
- Android Service詳解(二)Android
- Android Service詳解(一)Android
- Android-Service詳解Android
- Android Studio 新特性詳解Android
- Service詳解
- Android Service生命週期 Service裡面的onStartCommand()方法詳解Android
- Android Studio Gradle 常用配置詳解AndroidGradle
- Angular service 詳解Angular
- Android Studio 建立aidl檔案,用於程式間通訊AndroidAI
- Android Studio ndk-Jni開發詳解Android
- Android Studio匯入github專案詳解AndroidGithub
- Android AIDL原理AndroidAI
- 四大元件之Service_AIDL元件AI
- 4-AIII–Service跨程式通訊:aidlAI
- k8s之Service詳解-Service使用K8S
- Service生命週期詳解
- Service Mesh技術詳解
- Android IPC 之AIDLAndroidAI
- AIDL 講解AI
- Visual Studio中的Android模擬器使用詳解Android
- Laravel Service Provider 概念詳解LaravelIDE
- Android探索之旅 | AIDL原理和例項講解AndroidAI
- konga新增service和rouce詳解
- Android aidl Binder框架淺析AndroidAI框架
- Android Studio 超詳細安裝教程Android
- Visual Studio 使用GIT詳解Git
- 藉助 AIDL 理解 Android Binder 機制——AIDL 的使用和原理分析AIAndroid
- puppet進階指南——service資源詳解
- Android ServiceAndroid
- Android點將臺:金科玉律[-AIDL-]AndroidAI
- Android程式間通訊之AIDLAndroidAI
- Android Service 服務(一)—— ServiceAndroid