您好,登錄后才能下訂單哦!
Android中 AIDL如何使用,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
一般創建的服務并不能被其他的應用程序訪問。為了使其他的應用程序也可以訪問本應用程序提供的服務,Android系統采用了遠程過程調用(Remote Procedure Call,RPC)方式來實現。與很多其他的基于RPC的解決方案一樣,Android使用一種接口定義語言(Interface Definition Language,IDL)來公開服務的接口。因此,可以將這種可以跨進程訪問的服務稱為AIDL(Android Interface Definition Language)服務。
AIDL使用簡單的語法來聲明接口,描述其方法以及方法的參數和返回值。這些參數和返回值可以是任何類型,甚至是其他AIDL生成的接口。
其中對于Java編程語言的基本數據類型 (int, long, char, boolean,String,CharSequence)集合接口類型List和Map,不需要import 語句。
而如果需要在AIDL中使用其他AIDL接口類型,需要import,即使是在相同包結構下。AIDL允許傳遞實現Parcelable接口的類,需要import
需要特別注意的是,對于非基本數據類型,也不是String和CharSequence類型的,需要有方向指示,包括in、out和inout,in表示由客戶端設置,out表示由服務端設置,inout是兩者均可設置。
AIDL只支持接口方法,不能公開static變量。
文件內容:
package du.pack;
interface IMyService{
//只有一個接口
String getValue();
}
public class MyService extends Service {
@Override
public IBinder onBind(Intent arg0) {
// 把內部類的對象返回給客戶端使用
return new MyServiceImpl();
}
// 創建一個繼承自IMyService.Stub的內部類
public class MyServiceImpl extends IMyService.Stub {
// 必須實現AIDL文件中的接口
public String getValue() throws RemoteException {
return null;
}
}
}
<service android:name=".MyService" >
<intent-filter>
<action android:name="du.pack.IMyService" />
</intent-filter>
</service>
上面的"du.pack.IMyService"是客戶端用于訪問AIDL服務的ID。
public class AidlClientTestActivity extends Activity {
// 遠程服務端的對象
IMyService mIMyService;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
// 綁定成功,得到遠程服務端的對象,目標完成!!!
mIMyService = IMyService.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName name) {
// 解除綁定
mIMyService = null;
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 綁定遠程服務端服務
Intent serviceIntent = new Intent("du.pack.IMyService");
bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
}
}
四、Framework中使用AIDL
Framework中使用AIDL我們通過ITelephonyRegistry這個SystemService進行分析。該服務的主要作用就是對通話相關的事件進行監聽,我們重心放在AIDL的實現結構上,不去關注ITelephonyRegistry具體的實現。
先來看一下這個服務的AIDL文件:
@ITelephonyRegistry.aidl
interface ITelephonyRegistry {
void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
void notifyCallState(int state, String incomingNumber);
void notifyServiceState(in ServiceState state);
void notifySignalStrength(in SignalStrength signalStrength);
void notifyMessageWaitingChanged(boolean mwi);
}
再來看這個服務的真正實現:
@TelephonyRegistry.java
class TelephonyRegistry extends ITelephonyRegistry.Stub {
TelephonyRegistry(Context context) {
......
}
void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow){
......
}
void notifyCallState(int state, String incomingNumber){
......
}
void notifyServiceState(in ServiceState state){
......
}
void notifySignalStrength(in SignalStrength signalStrength){
......
}
void notifyMessageWaitingChanged(boolean mwi){
......
}
}
上面的兩個文件是這個服務的核心部分,aidl文件規定了這個服務的功能,而java文件是對功能的具體實現。但是,此時的TelephonyRegistry并沒有繼承Service的類,也就是說,當前他并不具備作為一個Service的資格。那么他是如何變成一個服務的呢?
在SystemService中可以找到答案。
@SystemServer.java
class ServerThread extends Thread {
@Override
public void run() {
try {
telephonyRegistry = new TelephonyRegistry(context);
ServiceManager.addService("telephony.registry", telephonyRegistry);
}
}
}
我們看到,在這一步中,把telephonyRegistry對象(也就是ITelephonyRegistry.Stub的子類對象)作為一個Service注冊給了ServiceManager。并且注冊的名字是“telephony.registry”
有了這一步,TelephonyRegistry就可以作為服務提供者向客戶端開放了。也就是說,有了這一步,TelephonyRegistry才算上是一個真正的Service,可以接受客戶端的連接申請。
那么接下來,我們怎么得到這個Service呢?
既然通過ServiceManager注冊了服務,我們就需要再次通過ServiceManager得到它的服務對象。
private ITelephonyRegistry sRegistry;
sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService("telephony.registry"));
通過這樣的方法,我們就得到了ITelephonyRegistry.aidl的對象sRegistry。
關于Android中 AIDL如何使用問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。