【Android】 通過AIDL實現的app之間通信

如果你閒着沒事兒幹,那麼你可以學習這個項目,自己可以玩的很開心。

    aidl.im.one 和 aidl.im.two這兩個module是利用aidl實現的兩個可以聊天的app,不過是裝在同一個手機上的
    適合超級無聊之人自己和自己聊天使用。

*二話不說,看我上圖*

聊天圖片

AIDL :Android interface definition language,Android 接口描述語言。
Android studio:新建一個項目,新建兩個application  module,目的是用這兩個app進行測試通信(以下稱
    app1  和  app2 )。

、兩個module中新建包名和文件名都一樣的aidl文件,本項目是IRemoteService.aidl,名稱和包名不一樣的話兩
邊都會找不到服務。
    
、如果要通過服務傳遞自定義對象的話,那麼也需要定義該對象的aidl文件,本項目定義了UserMessage.aidl,和IRemoteService.aidl一樣,在兩個module中包名和文件名都一樣。
    
三、兩個module 中新建UserMessage.java(也可以是其他語言對象,看你用的是什麼語言了,比如可以是UserMessage.kt),也需要時一樣的包名和文件名。
    
、接下來就是寫activity和service了,aidl.im.one中新建MainActivity和RemoteService類,位置和名稱就
隨便了。
    
    (1)MainActivity
        1) onCreate方法就可以直接註冊本app(app1)接受消息的服務
            Intent intent2 = new Intent().setComponent(new ComponentName(
                            "com.chaoya.aidlimone",
                            "com.chaoya.aidlimone.RemoteService"));
            bindService(intent2, mConnection2, Context.BIND_AUTO_CREATE);

 

 

            在發送消息的方法裏判斷app2的服務有沒有連接上,沒連接上的話就去連接綁定,之所以沒有也在
            onCreate方法中綁定是因爲同一個手機中沒法同時點擊打開兩個app,若是在onCreate中綁定的話,就會
            找不到服務,導致綁定失敗,因爲app2還沒啓動,同樣其服務也沒啓動,所以是連接不成功的;可能有人
            會問,爲什麼不先把app2啓動?如果先把app2啓動的話,app1啓動時確實可以連接上app2的服務,並且
            app1的接受消息的服務也綁定成功,app1算是沒問題了,但是app2呢,app2是沒有連接上app1的服務的,
            道理和先啓動app1是一樣的,不再贅述;這個時候想讓app2也連接上app1的服務,就需要app2重啓,但是
            問題又來了,若app2重啓了,那麼app2自己的接受消息的服務也會重新綁定初始化,對象會變哦,內存地
            址都不一樣了,這時候app1持有的還是那個一樣不存在的服務,如果這時app1調用發送消息服務,那麼就
            會報錯,什麼錯呢,就是Android的android.os.DeadObjectException異常。


        2)在發送點擊事件中綁定app2的服務
            Intent intent1 = new Intent().setComponent(new ComponentName(
                                "com.chaoya.aidlimtwo",
                                "com.chaoya.aidlimtwo.RemoteService"));
            bindService(intent1, mConnection1, Context.BIND_AUTO_CREATE);

            注意:1)和2)中綁定的服務是不一樣的,一個是自己的接受消息的服務,一個是調用對方的遠程服務。

        3)發送消息的服務具體操作
            private ServiceConnection mConnection1 = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    Log.e(TAG, "onServiceConnected");
                    remoteService = IRemoteService.Stub.asInterface(service);
                }

                @Override
                public void onServiceDisconnected(ComponentName name) {

                }
            };

            這個對象就是bindService時傳入的監聽,在發送消息時判斷一下remoteService,爲null時再bindServi
            ce一下。

            發消息的代碼
            if ("".equals(content.getText().toString().trim())) {
                Toast.makeText(this, "請輸入信息", Toast.LENGTH_SHORT).show();
                return;
            }
            if (remoteService == null) {
                Toast.makeText(this, "服務正在啓動...", Toast.LENGTH_SHORT).show();
                Intent intent1 = new Intent().setComponent(new ComponentName(
                        "com.chaoya.aidlimtwo",
                        "com.chaoya.aidlimtwo.RemoteService"));
                bindService(intent1, mConnection1, Context.BIND_AUTO_CREATE);
                return;
            }
            try {
                remoteService.sendMessage(new UserMessage(content.getText().toString().trim()));
                list.addFirst("女孩說:" + content.getText().toString().trim());
                content.setText("");
                adapter.notifyDataSetChanged();
            } catch (RemoteException e) {
                e.printStackTrace();
            }

            我這裏用了一個listview把發送和收到的消息都展示了

         4)接受消息的服務的具體操作
            RemoteService.InnerIBinder innerIBinder = (RemoteService.InnerIBinder) service;
            RemoteService remoteService = (RemoteService) innerIBinder.getService();
            remoteService.setCallBack(new RemoteService.CallBack() {
                @Override
                public void showMessage(UserMessage message) {
                    list.addFirst("男孩說:" + message.messageContent);
                    adapter.notifyDataSetChanged();
                }
            });

            這裏通過回調的方式去獲取了service收到的消息,我這裏是直接加入集合並展示了。
    (2)RemoteService,繼承自android.app.Service
        1)定義一個內部類供本app調用
            public class InnerIBinder extends IRemoteService.Stub {
                @Override
                public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
                         double aDouble, String aString) throws RemoteException {

                }
                @Override
                public void sendMessage(UserMessage message) throws RemoteException {
                    //將收到的消息回調給MainActivity,其實就是app2遠程調用的,對app1來說就是接受到的
                    callBack.showMessage(message);
                }
                public Service getService() {
                    return RemoteService.this;
                }
            }

        2)onBind方法中直接返回new InnerIBinder(); 
        3)定義一個回調接口

            public interface CallBack{
                void showMessage(UserMessage message);
            }
        4)設置回調方法
            public void setCallBack(CallBack callBack){
                this.callBack = callBack;
            }

、app2的代碼和app1幾乎一樣,除了調用服務的包名外。

、本着真正開源的精神,代碼上傳GitHub了,特討厭把代碼傳C**N,下載還要錢,不喜歡,地址如下:

 

 

 

        [https://github.com/xiaodouyaer/AIDLIM]

 

有寫的不對的地方,還請斧正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章