1.說到AIDL,就會聯想到Binder機制,
Binder 是一種行程間通信機制
整個app屬于客戶端,系統是服務端,他們之間的通訊就是通過IPC互動,中間服務就是serviceSystem
優點:性能,穩定性,安全性
設計:Client/Server/ServiceManager/驅動
實作:AIDL
二、核心代碼處
1.可以通過AndroidStudio創建:
1.1選中一個包進行新建一個aidl,系統會自動生成一個aidl的檔案夾
1.2手動創建檔案夾,創建包名,然后在包內創建aidl檔案,


1.3我們創建兩個AIDL檔案 IMsgManager.aidl,IReceiverMsgListener

IMsgManager:訊息管理類,提供訊息的介面
IReceiverMsgListener:訊息接收類,做轉發使用
1.4Msg是物件,aidl常見的引數只支持簡單的資料型別,物件需要通過Parcelable序列化處理,
1.4.1 先定義一個Msg 實作 Parcelable介面,,注意這個類的包名一定要與aidl檔案下的包名一致,因為我們要定義一個空的Msg.aidl檔案,這樣Msg.aidl檔案才會與Msg.Java檔案關聯起來
Msg.aidl檔案:洗掉interface Msg,將Msg申明為 parcelable;

這樣就就可以了,
IMsgManager:

由于aidl檔案不能關聯,使用類都需要手動匯入包名,
IReceiveMsgListener:

定義好AIDL檔案,我們要生成對應的java檔案:點擊

將專案編譯一下,aidl檔案對應的java檔案出現在這個下方,

這個時候有人會發現少了一個Msg的java檔案,由于我們將Msg.aidl申明為 parcelable,將會關聯Parcelable的物體,和java檔案已關聯起來,

這樣,我們就可以通過aidl發送自定義物件,
2.Service的處理(C/S)
2.1我們需要創建一個Service ,作為服務端在監控
public class MySevice extends Service {
//AIDL不支持正常的介面回呼,使用RemoteCallbackList實作介面回呼
private RemoteCallbackList<IReceiveMsgListener> mReceiveListener = new RemoteCallbackList<IReceiveMsgListener>();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new MyIBinder();
}
public class MyIBinder extends IMsgManager.Stub {
@Override
public void sendMsg(Msg msg) throws RemoteException {
receiveMsg(msg);
}
@Override
public void registerReceiveListener(IReceiveMsgListener receiveListener) throws RemoteException {
mReceiveListener.register(receiveListener);
}
@Override
public void unregisterReceiveListener(IReceiveMsgListener receiveListener) throws RemoteException {
boolean success = mReceiveListener.unregister(receiveListener);
if (success){
Log.d("tag","=== 解除注冊成功");
}else {
Log.d("tag","=== 解除注冊失敗 ");
}
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
return super.onTransact(code, data, reply, flags);
}
};
//收到訊息處理
public void receiveMsg(Msg msg) {
//通知Callback回圈開始,回傳size為實作mReceiveListener回呼的個數
final int size = mReceiveListener.beginBroadcast();
msg.setMsg("我是服務器,我收到了:"+msg.getMsg());
for (int i = 0; i < size; i++){
IReceiveMsgListener listener = mReceiveListener.getBroadcastItem(i);
if (listener != null){
try {
listener.onReceive(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
//通知通知Callback回圈結束
mReceiveListener.finishBroadcast();
}
}
2.2將service注冊到AndroidManifest
<service
android:name="com.example.mydemo.service.MySevice"
android:process=":remote"//同一應用內跨行程通信需
android:enabled="true"
android:exported="true" //暴露
>
<intent-filter>
<action android:name="com.test.aidl.action"/>
</intent-filter>
</service>
三、Service與Activity之間的通訊(在當前APP內)
3.1系結服務
IMsgManager myIBinder = null;
private TextView textView;
private Button button_1, button_2, button_3;
public static final String ACTIO_SERVICE = "com.test.aidl.action";
IMsgManager iMsgManager;
private EditText editText_1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
editText_1=findViewById(R.id.edit_1);
textView = findViewById(R.id.text_1);
button_1 = findViewById(R.id.btn_1);
button_2 = findViewById(R.id.btn_2);
button_3 = findViewById(R.id.btn_3);
button_1.setOnClickListener(this);
button_2.setOnClickListener(this);
button_3.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == button_1) {
//系結
bindService();
} else if (v == button_2) {
//發送
try {
if (myIBinder != null) {
if (editText_1.getText().toString().isEmpty())
return;
Msg msg = new Msg("服務端發送:"+editText_1.getText());
myIBinder.sendMsg(msg);
}
} catch (RemoteException e) {
e.printStackTrace();
}
} else if (v == button_3) {
//解綁
unbindService(connection);
}
}
private void bindService() {
//注冊service
Intent intent = new Intent(this, MySevice.class);
intent.setAction(ACTIO_SERVICE);
bindService(intent, connection, Service.BIND_AUTO_CREATE);
}
//service的鏈接
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myIBinder = IMsgManager.Stub.asInterface(service);
iMsgManager = IMsgManager.Stub.asInterface(service);
try {
//注冊binder連接
iMsgManager.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
try {
iMsgManager.registerReceiveListener(mReceiveMsgListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
//斷開連接
}
};
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
// //當承載IBinder的行程消失時接識訓呼的介面
@Override
public void binderDied() {
if (null == iMsgManager) {
return;
}
//解綁
iMsgManager.asBinder().unlinkToDeath(mDeathRecipient, 0);
iMsgManager = null;
}
};
private IReceiveMsgListener mReceiveMsgListener = new IReceiveMsgListener.Stub() {
@Override
public void onReceive(Msg msg) throws RemoteException {
//訊息分發
textView.append("\n" + msg.getMsg());
}
};
這樣就完成再App的訊息分發
四、我們要在兩個App中實作訊息傳遞,也就是跨行程IPC,
由于我們已完成了一個service端的開發,我們在創建一個新的app,作為令一個行程,
4.1同樣把所service APP中的aidl復制到B的app中,Msg物件也要一同復制到對應的包下(兩邊保持一致)

把Msg自定義的物體也復制過來,兩邊要保持包名一致,接下我們還是需要make一下專案,

執行完,會生成一下

4.2 實作service的系結,可以把A app的代碼復制過來,修改注冊service方法
IMsgManager myIBinder = null;
private TextView textView;
private Button button_1, button_2, button_3;
public static final String ACTIO_SERVICE = "com.test.aidl.action";
IMsgManager iMsgManager;
EditText edit_1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
edit_1=findViewById(R.id.edit_1);
textView = findViewById(R.id.text_1);
button_1 = findViewById(R.id.btn_1);
button_2 = findViewById(R.id.btn_2);
button_3 = findViewById(R.id.btn_3);
button_1.setOnClickListener(this);
button_2.setOnClickListener(this);
button_3.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v == button_1) {
//系結
bindService();
} else if (v == button_2) {
//接收
try {
if (myIBinder != null) {
if (edit_1.getText().toString().isEmpty())
return;
Msg msg = new Msg("客戶端發送:"+edit_1.getText());
myIBinder.sendMsg(msg);
}
} catch (RemoteException e) {
e.printStackTrace();
}
} else if (v == button_3) {
//解綁
unbindService(connection);
}
}
private void bindService() {
//系結需要注意一下,由于我們啟動其他應用的,需要知道包名和,filter-action
Intent intent = new Intent();
intent.setPackage("com.example.mydemoa");//包名,服務端的包名(service)
intent.setAction(ACTIO_SERVICE);//action
bindService(intent, connection, Service.BIND_AUTO_CREATE);
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myIBinder = IMsgManager.Stub.asInterface(service);
iMsgManager = IMsgManager.Stub.asInterface(service);
try {
iMsgManager.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
try {
iMsgManager.registerReceiveListener(mReceiveMsgListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private void showUI() throws RemoteException {
}
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
// //當承載IBinder的行程消失時接識訓呼的介面
@Override
public void binderDied() {
if (null == iMsgManager) {
return;
}
iMsgManager.asBinder().unlinkToDeath(mDeathRecipient, 0);
iMsgManager = null;
}
};
private IReceiveMsgListener mReceiveMsgListener = new IReceiveMsgListener.Stub() {
@Override
public void onReceive(Msg msg) throws RemoteException {
msg.setTime(System.currentTimeMillis());
textView.append("\n" + msg.getMsg());
}
};
4.4這樣基本完成,接下來開始測驗,測驗先啟動service的app,然后在打開b的,否則B打開,service沒有啟動,導致訊息無法傳遞
五、結果:


這樣就完成了跨行程訊息傳遞
注意:關于自定義物件,是先創建一個物體物件,實作Parcelable介面,再在aidl檔案夾下的包內創建一個aidl檔案名為java一樣的,同事包名也一樣,洗掉aidl檔案內介面代碼行,
interface Msg{
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
}
然后改成申明為:parcelable Msg;即可,不然會報錯,網上大多數教程都沒有交會如何關聯自定義java檔案與aidl檔案,
*************************************************************************************************************
很感謝官方,今天剛整理好,就推上了領域內容熱榜第八名,以后將會寫出更好的博客回饋大家,

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/397400.html
標籤:其他
上一篇:安卓應用hook測驗
