AIDL(Android Interface Definition Language)
程序員可以利用AIDL自定義編程接口喊衫,在客戶(hù)端和服務(wù)端之間實(shí)現(xiàn)進(jìn)程間通信(IPC)。在Android平臺(tái)上糯而,一個(gè)進(jìn)程通常不能訪(fǎng)問(wèn)另外一個(gè)進(jìn)程的內(nèi)存空間,因此谅河,Android平臺(tái)將這些跨進(jìn)程訪(fǎng)問(wèn)的對(duì)象分解成操作系統(tǒng)能夠識(shí)別的簡(jiǎn)單對(duì)象框都。并為跨應(yīng)用訪(fǎng)問(wèn)而特殊編排和整理這些對(duì)象。用于編排和整理這些對(duì)象的代碼編寫(xiě)起來(lái)十分冗長(zhǎng)霎箍,所以Android的AIDL提供了相關(guān)工具來(lái)自動(dòng)生成這些代碼寻狂。
例子:創(chuàng)建兩個(gè)apk,一個(gè)作為服務(wù)提供方朋沮,一個(gè)作為AIDL服務(wù)調(diào)用方。
android studio
AIDL服務(wù)方代碼
一共4步
1.先進(jìn)入服務(wù)方的工程缀壤,在com.rust.aidl
包內(nèi)創(chuàng)建IMyService.aidl
文件
// IMyService.aidl
package com.rust.aidl;
// Declare any non-default types here with import statements
interface IMyService {
/**
* 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);
String helloAndroidAIDL(String name);// 此次使用的方法
}
2.在com.rust.service
包內(nèi)創(chuàng)建MyService.java
文件樊拓;有一個(gè)內(nèi)部類(lèi)MyServiceImpl
實(shí)現(xiàn)接口的功能
package com.rust.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
import com.rust.aidl.IMyService;
public class MyService extends Service {
public class MyServiceImpl extends IMyService.Stub {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString) throws RemoteException {
}
public String helloAndroidAIDL(String name) throws RemoteException {
Log.d("aidl", "helloAndroidAIDL heard from : " + name);
return "Rust: Service01 return value successfully!";
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new MyServiceImpl();// 返回內(nèi)部類(lèi)實(shí)例
}
}
3.實(shí)現(xiàn)了MyService類(lèi)后,對(duì)此AIDL服務(wù)進(jìn)行配置塘慕;在AndroidManifest.xml
文件中配置
<service android:name="com.rust.service.MyService">
<intent-filter>
<action android:name="com.rust.aidl.IMyService" />
</intent-filter>
</service>
service寫(xiě)實(shí)現(xiàn)類(lèi)MyService
筋夏;action里面寫(xiě)上AIDL文件
4.發(fā)布運(yùn)行此apk
AIDL調(diào)用方代碼
建立(或進(jìn)入)AIDL調(diào)用方的工程,這里是MyAIDLTest工程图呢。有如下3個(gè)步驟:
1.將AIDL服務(wù)端生成的Java文件復(fù)制到調(diào)用方工程里条篷,盡量保持這個(gè)Java文件的路徑與服務(wù)端的一致,便于識(shí)別
2.寫(xiě)代碼綁定服務(wù)蛤织,獲取AIDL服務(wù)對(duì)象
3.通過(guò)AIDL服務(wù)對(duì)象完成AIDL接口調(diào)用
本例中赴叹,生成的Java文件路徑為:服務(wù)端/app/build/generated/source/aidl/debug/com/rust/aidl/IMyService.java
將其復(fù)制到調(diào)用方工程下:MyAIDLTest/app/src/main/java/com/rust/aidl/IMyService.java
編寫(xiě)調(diào)用方MainActivity.java
代碼
package rust.myaidltest;
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.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.rust.aidl.IMyService;
public class MainActivity extends AppCompatActivity {
Button aidlBtn;
IMyService myService;// 服務(wù)
String appName = "unknown";
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myService = IMyService.Stub.asInterface(service);// 獲取服務(wù)對(duì)象
aidlBtn.setEnabled(true);
}// 連接服務(wù)
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
aidlBtn = (Button) findViewById(R.id.aidl_1_btn);
appName = getPackageName();
// 我們沒(méi)辦法在構(gòu)造Intent的時(shí)候就顯式聲明.
Intent intent = new Intent("com.rust.aidl.IMyService");
// 既然沒(méi)有辦法構(gòu)建有效的component,那么給它設(shè)置一個(gè)包名也可以生效的
intent.setPackage("com.rust.aboutview");// the service package
// 綁定服務(wù),可設(shè)置或觸發(fā)一些特定的事件
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
aidlBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
// AIDL服務(wù)調(diào)用代碼如下:
String msg = myService.helloAndroidAIDL(appName);
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
}
效果
點(diǎn)擊調(diào)用端的按鈕指蚜,彈出Toast:Rust: Service01 return value successfully!
服務(wù)端apk打印log:helloAndroidAIDL heard from : rust.myaidltest
其中乞巧,rust.myaidltest
就是調(diào)用端傳入的自身的包名
服務(wù)端更新后,如果aidl文件沒(méi)改動(dòng)摊鸡,不需要更新生成的Java文件
如果服務(wù)端apk被卸載绽媒,調(diào)用端使用此服務(wù)時(shí)會(huì)出錯(cuò)