編輯:Android資訊
公司產品之前IM這塊存在很多問題,消息到達率低,加上協議上有些問題,丟消息頻繁,所以需要重構IM,AIDL不能解決以上問題。好吧!那AIDL可以解決什麼問題?什麼是AIDL?
AIDL是 Android Interface definition language的縮寫,它是一種Android內部進程通信接口的描述語言,通過它我們可以定義進程間的通信接口
大部分文章介紹都是在eclipse下介紹的,現在 Android Studio 作為開發工具比較普及了,所以我在Android Studio 下介紹(其實區別不大)。
言歸正傳,我們需要使用Android Studio實現一個遠程Service,並且建立AIDL進行通信。
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>

1.創建AIDL文件夾

2.創建AIDL文件
// IHandler.aidl
package name.quanke.aidldemo;
// Declare any non-default types here with import statements
interface IHandler {
void connect();
}

4.AIDL文件 生成接口
生成後的樣子

4.AIDL文件 生成後的樣子
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) {
//斷開連接調用
}
};
}
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 Studio 技巧匯總
這是從Philippe Breault的系列文章《Android Studio Tips Of the Day》中提取出來的自認為精華的部分。 這些技巧在實際應用
Android異步消息處理機制詳解及源碼分析
最近相對來說比較閒,加上養病,所以沒事干就撸些自己之前的知識點為博客,方便自己也方便別人。 1 背景 之所以選擇這個知識點來分析有以下幾個原因: 逛GitHub
Gradle for Android 第四篇( 構建變體 )
當你在開發一個app,通常你會有幾個版本。大多數情況是你需要一個開發版本,用來測試app和弄清它的質量,然後還需要一個生產版本。這些版本通常有不同的設置,例如不同
Android 沉浸式全屏的實現方法
Android 4.4 帶來了沉浸式全屏體驗, 在沉浸式全屏模式下, 狀態欄、 虛擬按鍵動態隱藏, 應用可 以使用完整的屏幕空間, 按照 Google 的說法,