亚洲欧美日韩熟女|做爱高潮视频网址|国产一区二区三级片|国产Av中文字幕www.性色av|亚洲婷婷永久免费|国产高清中文字幕|欧美变态网站久re视频精品|人妻AV鲁丝第一页|天堂AV一区二区在线观看|综合 91在线精品

Android Binder,AIDL跨進程通訊詳解與實現(xiàn),看一遍就懂

2023-04-12


1.說到AIDL,就會聯(lián)想到Binder機制,


Binder 是一種進程間通信機制
整個app屬于客戶端,系統(tǒng)是服務(wù)端,他們之間的通訊就是通過IPC交互,中間服務(wù)就是serviceSystem
優(yōu)點:性能,穩(wěn)定性,安全性
設(shè)計:Client/Server/ServiceManager/驅(qū)動
實現(xiàn):AIDL


二、核心代碼處

1.可以通過AndroidStudio創(chuàng)建:


1.1選中一個包進行新建一個aidl,系統(tǒng)會自動生成一個aidl的文件夾


1.2手動創(chuàng)建文件夾,創(chuàng)建包名,然后在包內(nèi)創(chuàng)建aidl文件。




1.3我們創(chuàng)建兩個AIDL文件 IMsgManager.aidl,IReceiverMsgListener



IMsgManager:消息管理類,提供消息的接口


IReceiverMsgListener:消息接收類,做轉(zhuǎn)發(fā)使用


1.4Msg是對象,aidl常見的參數(shù)只支持簡單的數(shù)據(jù)類型,對象需要通過Parcelable序列化處理。


1.4.1 先定義一個Msg 實現(xiàn) Parcelable接口,,注意這個類的包名一定要與aidl文件下的包名一致,因為我們要定義一個空的Msg.aidl文件,這樣Msg.aidl文件才會與Msg.Java文件關(guān)聯(lián)起來


Msg.aidl文件:刪除interface Msg,將Msg申明為 parcelable;



這樣就就可以了。


IMsgManager:



由于aidl文件不能關(guān)聯(lián),使用類都需要手動導入包名。




IReceiveMsgListener:





定義好AIDL文件,我們要生成對應(yīng)的java文件:點擊



將項目編譯一下,aidl文件對應(yīng)的java文件出現(xiàn)在這個下方。



這個時候有人會發(fā)現(xiàn)少了一個Msg的java文件,由于我們將Msg.aidl申明為parcelable,將會關(guān)聯(lián)Parcelable的實體,和java文件已關(guān)聯(lián)起來。



這樣,我們就可以通過aidl發(fā)送自定義對象。


2.Service的處理(C/S)


2.1我們需要創(chuàng)建一個Service,作為服務(wù)端在監(jiān)控




public class MySevice extends Service {
    //AIDL不支持正常的接口回調(diào),使用RemoteCallbackList實現(xiàn)接口回調(diào)
    private RemoteCallbackList mReceiveListener = new RemoteCallbackList();


    @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循環(huán)開始,返回size為實現(xiàn)mReceiveListener回調(diào)的個數(shù)
        final int size = mReceiveListener.beginBroadcast();
        msg.setMsg("我是服務(wù)器,我收到了:"+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循環(huán)結(jié)束
        mReceiveListener.finishBroadcast();
    }



}



2.2將service注冊到AndroidManifest






    
        
    



三、Service與Activity之間的通訊(在當前APP內(nèi))

3.1綁定服務(wù)




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) {
        //發(fā)送
        try {
            if (myIBinder != null) {
                if (editText_1.getText().toString().isEmpty())
                    return;
                Msg msg = new Msg("服務(wù)端發(fā)送:"+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的進程消失時接收回調(diào)的接口
    @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 {
             //消息分發(fā)
        textView.append("\n" + msg.getMsg());


    }
};



這樣就完成再App的消息分發(fā)


四、我們要在兩個App中實現(xiàn)消息傳遞,也就是跨進程IPC。


由于我們已完成了一個service端的開發(fā),我們在創(chuàng)建一個新的app,作為令一個進程。


4.1同樣把所service APP中的aidl復制到B的app中,Msg對象也要一同復制到對應(yīng)的包下(兩邊保持一致)



把Msg自定義的實體也復制過來。兩邊要保持包名一致。接下我們還是需要make一下項目。



執(zhí)行完,會生成一下



4.2 實現(xiàn)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("客戶端發(fā)送:"+edit_1.getText());
                myIBinder.sendMsg(msg);
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    } else if (v == button_3) {
        //解綁
        unbindService(connection);

    }

}


private void bindService() {
//綁定需要注意一下,由于我們啟動其他應(yīng)用的,需要知道包名和,filter-action
    Intent intent = new Intent();
    intent.setPackage("com.example.mydemoa");//包名,服務(wù)端的包名(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的進程消失時接收回調(diào)的接口
    @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沒有啟動,導致消息無法傳遞


五、結(jié)果:




這樣就完成了跨進程消息傳遞


注意:關(guān)于自定義對象,是先創(chuàng)建一個實體對象,實現(xiàn)Parcelable接口,再在aidl文件夾下的包內(nèi)創(chuàng)建一個aidl文件名為java一樣的。同事包名也一樣,刪除aidl文件內(nèi)接口代碼行,


interface Msg{
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */

}

然后改成申明為:parcelable Msg;即可。不然會報錯。網(wǎng)上大多數(shù)教程都沒有交會如何關(guān)聯(lián)自定義java文件與aidl文件。


*************************************************************************************************************


很感謝官方,今天剛整理好,就推上了領(lǐng)域內(nèi)容熱榜第八名。以后將會寫出更好的博客回饋大家。



本文僅代表作者觀點,版權(quán)歸原創(chuàng)者所有,如需轉(zhuǎn)載請在文中注明來源及作者名字。

免責聲明:本文系轉(zhuǎn)載編輯文章,僅作分享之用。如分享內(nèi)容、圖片侵犯到您的版權(quán)或非授權(quán)發(fā)布,請及時與我們聯(lián)系進行審核處理或刪除,您可以發(fā)送材料至郵箱:service@tojoy.com