接口需求:
先來看AIDL的簡介:
“只有當你允許來自不同的客戶端訪問你的服務並且需要處理多線程問題時你才必須使用AIDL”,其他情況下你都可以選擇其他方法,如使用Messager,也能跨進程通訊。可見AIDL是處理多線程、多客戶端併發訪問的。而Messager是單線程處理。
一. 在參與源碼編譯的應用平臺項目中定義AIDL Server
1. 創建一個ADIL 接口文件
package com.asus.cnfindphone.service.persistentdata;
// Declare any non-default types here with import statements
interface IDataBlockService {
byte[] read();
int write(in byte[] data);
void wipe();
}
2. 創建AIDL Service實現類
package com.asus.cnfindphone.service.persistentdata; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.service.persistentdata.PersistentDataBlockManager; /** * Created by Qinghua_Liu on 2017-2-28. */ public class DataBlockService extends Service { private static String TAG = "Qinghua"; @Override public void onCreate() { super.onCreate(); } private boolean bInPSTList(String calling) { boolean bRes = false; if (calling.equalsIgnoreCase("asus.findmyphone")) { bRes = true; } Log.d(TAG, "bInPSTList==" + bRes); return bRes; } @Override public IBinder onBind(Intent intent) { //String callingApp = intent.getComponent().getPackageName(); return mBind; } private final IDataBlockService.Stub mBind = new IDataBlockService.Stub() { @Override public byte[] read() throws RemoteException { byte[] bytes = null; Log.d(TAG, "DataBlockService.read()"); String callingApp = getApplicationContext().getPackageManager().getNameForUid(Binder.getCallingUid()); Log.d(TAG, "callingApp==" + callingApp); if (bInPSTList(callingApp)) { PersistentDataBlockManager pdbManager = (PersistentDataBlockManager) getApplicationContext().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE); bytes = pdbManager.read(); //String id ="shenshiid"; //return id.getBytes(); } Log.d(TAG, "pdbManager.read()==" + new String(bytes)); return bytes; } @Override public int write(byte[] data) throws RemoteException { Log.d(TAG, "DataBlockService.write()" + new String(data)); String callingApp = getApplicationContext().getPackageManager().getNameForUid(Binder.getCallingUid()); Log.d(TAG, "callingApp==" + callingApp); if (bInPSTList(callingApp)) { if (data != null && data.length > 0) { PersistentDataBlockManager pdbManager = (PersistentDataBlockManager) getApplicationContext().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE); pdbManager.write(data); } } return 0; } @Override public void wipe() throws RemoteException { } }; }
3.Manifest 靜態註冊Service
<service android:name=".service.persistentdata.DataBlockService">
<intent-filter>
<action android:name="com.asus.cnfindphone.service.persistentdata.DataBlockService"/>
</intent-filter>
</service>
4. 過濾Service 調用者package:
@Override
public byte[] read() throws RemoteException {
byte[] bytes = null;
Log.d(TAG, "DataBlockService.read()");
String callingApp = getApplicationContext().getPackageManager().getNameForUid(Binder.getCallingUid());
Log.d(TAG, "callingApp==" + callingApp);
if (bInPSTList(callingApp)) {
PersistentDataBlockManager pdbManager = (PersistentDataBlockManager) getApplicationContext().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
bytes = pdbManager.read();
//String id ="shenshiid";
//return id.getBytes();
}
Log.d(TAG, "pdbManager.read()==" + new String(bytes));
return bytes;
}
private boolean bInPSTList(String calling) {
boolean bRes = false;
if (calling.equalsIgnoreCase("asus.findmyphone")) {
bRes = true;
}
Log.d(TAG, "bInPSTList==" + bRes);
return bRes;
}
代碼應該很好明白:只允許asus.findmyphone package 調用接口,如果需要讓多個包調用可以寫入config.xml 定義字串array
5.源碼編譯AIDL Android.mk的寫法:
LOCAL_SRC_FILES += \
src/com/asus/cnfindphone/service/persistentdata/IDataBlockService.aidl
6.源碼編譯安裝平臺應用。
二. 在Android Studio 中第三方應用調用AIDL接口
1. Android Studio如何正確導入aidl
2.Activity 類中調用接口:
import com.asus.cnfindphone.service.persistentdata.IDataBlockService;
private IDataBlockService dataBlockService;
private ServiceConnection conn;
private void initService(){
conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d("Qinghua","onServiceDisconnected! ");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
dataBlockService = IDataBlockService.Stub.asInterface((IBinder)service);
Log.d("Qinghua","bind success! ");
}
};
Intent i = new Intent("com.asus.cnfindphone.service.persistentdata.DataBlockService");
i.setPackage("com.asus.cnfindphone");
bindService(i, conn, Context.BIND_AUTO_CREATE);
}
protected void onCreate(Bundle paramBundle) {
super.onCreate(paramBundle);
setContentView(R.layout.activity_main);
initService();
this.location.setOnClickListener(new View.OnClickListener() {
public void onClick(View paramView) {
try {
dataBlockService.write("cissy".getBytes());
}catch (RemoteException e) {
e.printStackTrace();
}
}
});
this.test.setOnClickListener(new View.OnClickListener() {
public void onClick(View paramView) {
try {
byte[] bytes = dataBlockService.read();
Log.d("Qinghua","result:"+new String(bytes));
}catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
@Override protected void onDestroy()
{
super.onDestroy();
unbindService(conn);
dataBlockService = null;
}
三.調試與Log分析:
Log片斷及分析:
#往block 寫入數據 cissy
03-01 13:45:00.211 5655-5669/com.asus.cnfindphone D/Qinghua: DataBlockService.write()cissy
#調用者包名過濾
03-01 13:45:00.212 5655-5669/com.asus.cnfindphone D/Qinghua: callingApp==asus.findmyphone
03-01 13:45:00.212 5655-5669/com.asus.cnfindphone D/Qinghua: bInPSTList==true
#調用寫入成功,system 級權限允許
03-01 13:45:00.213 3001-3127/system_process E/Qinghua: mAllowedUid==1000callingUid==1000
#讀block 數據
03-01 13:45:04.315 5655-5668/com.asus.cnfindphone D/Qinghua: DataBlockService.read()
#調用者包名過濾
03-01 13:45:04.316 5655-5668/com.asus.cnfindphone D/Qinghua: callingApp==asus.findmyphone
03-01 13:45:04.316 5655-5668/com.asus.cnfindphone D/Qinghua: bInPSTList==true
#調用讀數據,system 級權限允許
03-01 13:45:04.316 3001-5234/system_process E/Qinghua: mAllowedUid==1000callingUid==1000
#讀取之前寫的數據成功
03-01 13:45:04.327 5655-5668/com.asus.cnfindphone D/Qinghua: pdbManager.read()==cissy
03-01 13:45:04.327 6488-6488/asus.findmyphone D/Qinghua: result:cissy