AIDL(Android Interface Definition Language)
程式員可以利用AIDL自定義程式設計接口,在用戶端和服務端之間實作程序間通信(IPC)。在Android平台上,一個程序通常不能通路另外一個程序的記憶體空間,是以,Android平台将這些跨程序通路的對象分解成作業系統能夠識别的簡單對象。并為跨應用通路而特殊編排和整理這些對象。用于編排和整理這些對象的代碼編寫起來十分冗長,是以Android的AIDL提供了相關工具來自動生成這些代碼。
例子:建立兩個apk,一個作為服務提供方,一個作為AIDL服務調用方。
android studio
AIDL服務方代碼
一共4步
1.先進入服務方的工程,在
com.rust.aidl
包内建立
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
MyService.java
檔案;有一個内部類
MyServiceImpl
實作接口的功能
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();// 傳回内部類執行個體
}
}
3.實作了MyService類後,對此AIDL服務進行配置;在
AndroidManifest.xml
檔案中配置
<service android:name="com.rust.service.MyService">
<intent-filter>
<action android:name="com.rust.aidl.IMyService" />
</intent-filter>
</service>
service寫實作類
MyService
;action裡面寫上AIDL檔案
4.釋出運作此apk
AIDL調用方代碼
建立(或進入)AIDL調用方的工程,這裡是MyAIDLTest工程。有如下3個步驟:
1.将AIDL服務端生成的Java檔案複制到調用方工程裡,盡量保持這個Java檔案的路徑與服務端的一緻,便于識别
2.寫代碼綁定服務,擷取AIDL服務對象
3.通過AIDL服務對象完成AIDL接口調用
本例中,生成的Java檔案路徑為:
服務端/app/build/generated/source/aidl/debug/com/rust/aidl/IMyService.java
将其複制到調用方工程下:
MyAIDLTest/app/src/main/java/com/rust/aidl/IMyService.java
編寫調用方
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;// 服務
String appName = "unknown";
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myService = IMyService.Stub.asInterface(service);// 擷取服務對象
aidlBtn.setEnabled(true);
}// 連接配接服務
@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();
// 我們沒辦法在構造Intent的時候就顯式聲明.
Intent intent = new Intent("com.rust.aidl.IMyService");
// 既然沒有辦法建構有效的component,那麼給它設定一個包名也可以生效的
intent.setPackage("com.rust.aboutview");// the service package
// 綁定服務,可設定或觸發一些特定的事件
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
aidlBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
// AIDL服務調用代碼如下:
String msg = myService.helloAndroidAIDL(appName);
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
}
效果
點選調用端的按鈕,彈出Toast:
Rust: Service01 return value successfully!
服務端apk列印log:
helloAndroidAIDL heard from : rust.myaidltest
其中,
rust.myaidltest
就是調用端傳入的自身的包名
服務端更新後,如果aidl檔案沒改動,不需要更新生成的Java檔案
如果服務端apk被解除安裝,調用端使用此服務時會出錯