Android 使用AIDL进行两个APP之间通讯以及相互消息回调(一)

前言:

AIDL:Android Interface Definition Language,翻译过来就是Android接口定义语言。是用于定义服务器和客户端通信接口的一种描述语言,可以拿来生成用于IPC的代码。所以使用AIDL需要一个服务端和客户端
作用:可以在一个进程中获取另一个进程的数据和调用其暴露出来的方法,从而满足进程间通信的需求。

1.AIDL支持的基本数据类型

  1. 八种基本数据类型:byte、char、short、int、long、float、double、boolean
  2. String,CharSequence
  3. 实现了Parcelable接口的数据类型
  4. List 类型。List承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象
  5. Map类型。Map承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象

2.服务端的实现

   创建工程,以及所需aidl文件

  • 使用Android Studio新建一个工程,命名为TestAidlDemo1Android 使用AIDL进行两个APP之间通讯以及相互消息回调(一)_第1张图片
  • 右键New一个AIDL文件,取名为IAidlInterface,AS会自动在工程目录生成一个路径完全一样的aidl文件夹Android 使用AIDL进行两个APP之间通讯以及相互消息回调(一)_第2张图片Android 使用AIDL进行两个APP之间通讯以及相互消息回调(一)_第3张图片
  • 既然是要回调消息,那就还需要一个回调接口,同样的方法,创建IAidlCallBack.aidl文件,那么接下来就进行代码编写

实现代码逻辑

  • 编写IAidlInterface.aldi代码,因为我们需要回调消息,那么我们需要注册回调以及注销回调接口,一个发送消息的接口,一个获取历史消息的接口,代码如下(AIDL文件不会自动导包,一些不是基本支持数据类型需要我们自己手动import,)
    import com.pgc.testaidldemo1.IAidlCallBack;
    interface IAidlInterface {
        /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
        void registerCallBack(IAidlCallBack iAidlCallBack);
        void unregisterCallBack(IAidlCallBack iAidlCallBack);
        void sendMessage(String message);
        List getMessages();
    }
    

     

  • 编写IAidlCallBack.aidl代码:既然是回调接口,那么我们只需要一个消息发送成功的回调接口就行,代码如下

    interface IAidlCallBack {
        /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
        void onMessageSuccess(String message);
    }

     

  • 既然是服务端,我们需要实现接收消息已经处理消息的逻辑代码,所以我们创建一个AidlService,继承Service,因为Service不能直接接收Callback,但是提供了RemoteCallbackList来注册回调

    private RemoteCallbackList callbackList= new RemoteCallbackList<>();

    同时RemoteCallbackList提供了beginBroadcast来获取当前注册的回调数,因此我们可以通过这个方法进行回调处理(再使用了beginBroadcast之后必须调用finishBroadcast不然会报beginBroadcast() called while already in a broadcast错误)

    final int num=callbackList.beginBroadcast();
    for (int i=0;i

     接下来实例化binder对象并返回给客户端,

    @Override
        public IBinder onBind(Intent intent) {
            return binder;
        }
    
        private final IAidlInterface.Stub binder=new IAidlInterface.Stub() {
            @Override
            public void registerCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
                callbackList.register(iAidlCallBack);
            }
    
            @Override
            public void unregisterCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
                callbackList.unregister(iAidlCallBack);
            }
    
            @Override
            public void sendMessage(String message) throws RemoteException {
                messages.add(message);
                final int num=callbackList.beginBroadcast();
                for (int i=0;i getMessages() throws RemoteException {
                return messages;
            }
        };

      

  • 在AndroidManifest.xml注册Service

    
        
                
       
    

     

  • AidlService全部代码

    package com.pgc.testaidldemo1;
    
    import android.annotation.SuppressLint;
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteCallbackList;
    import android.os.RemoteException;
    
    import androidx.annotation.Nullable;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    /**
     * Created by PengGuiChu on 2020/4/11.
     */
    @SuppressLint("Registered")
    public class AidlService extends Service {
        private RemoteCallbackList callbackList= new RemoteCallbackList<>();
        private List messages=new ArrayList<>();
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return binder;
        }
    
        private final IAidlInterface.Stub binder=new IAidlInterface.Stub() {
            @Override
            public void registerCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
                callbackList.register(iAidlCallBack);
            }
    
            @Override
            public void unregisterCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
                callbackList.unregister(iAidlCallBack);
            }
    
            @Override
            public void sendMessage(String message) throws RemoteException {
                messages.add(message);
                final int num=callbackList.beginBroadcast();
                for (int i=0;i getMessages() throws RemoteException {
                return messages;
            }
        };
    
        @Override
        public void onCreate() {
            super.onCreate();
        }
    }
    

     

  • 因为是服务端和客户端实现相互消息回调,因此在服务端也需要通过binderService来获取binder,相对客户端,因为服务端和AidlService是在同一线程,我们可以直接binderService

    Intent intent=new Intent(getApplicationContext(),AidlService.class);
    bindService(intent,serviceConnection,BIND_AUTO_CREATE);

    然后实例化ServiceConnection

    private ServiceConnection serviceConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                
            }
    
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
    
            }
    };

    然后在onServiceConnected中获取binder

    iAidlInterface=IAidlInterface.Stub.asInterface(iBinder);
    try {
          iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0);//监听进程是否消失
          iAidlInterface.registerCallBack(iAidlCallBack);//注册消息回调
          messages.addAll(iAidlInterface.getMessages());//获取历史消息
          listView.setAdapter(arrayAdapter=new ArrayAdapter<> 
          (getApplicationContext(),android.R.layout.simple_list_item_1,messages));
    } catch (RemoteException e) {
           e.printStackTrace();
    }

    DeathRecipient实例

        private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
            //当承载IBinder的进程消失时接收回调的接口
            @Override
            public void binderDied() {
                if (null == iAidlInterface) {
                    return;
                }
                try {
                    iAidlInterface.unregisterCallBack(iAidlCallBack);//注销
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
                iAidlInterface = null;
            }
        };

    iAidlCallBack实例

        private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() {
            @Override
            public void onMessageSuccess(String message) {
                if (messages!=null&&arrayAdapter!=null){
                    messages.add(message);
                    handler.sendEmptyMessage(1);
                }
            }
        };

     MainActivity全部代码

    package com.pgc.testaidldemo1;
    
    
    
    import android.annotation.SuppressLint;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.RemoteException;
    import android.view.View;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    
    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    import java.util.ArrayList;
    import java.util.List;
    
    import butterknife.BindView;
    import butterknife.ButterKnife;
    import butterknife.OnClick;
    
    public class MainActivity extends AppCompatActivity {
        @BindView(R.id.list_view)
        ListView listView;
        private IAidlInterface iAidlInterface;
        private int num;
        private List messages=new ArrayList<>();
        private ArrayAdapter arrayAdapter;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ButterKnife.bind(this);
            Intent intent=new Intent(getApplicationContext(),AidlService.class);
            bindService(intent,serviceConnection,BIND_AUTO_CREATE);
        }
    
    
        @OnClick(R.id.send_message)
        public void onViewClicked(View view) {
            if (iAidlInterface!=null){
                try {
                    iAidlInterface.sendMessage("消息"+num);
                    num++;
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    
        private ServiceConnection serviceConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                iAidlInterface=IAidlInterface.Stub.asInterface(iBinder);
                try {
                    iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0);//监听进程是否消失
                    iAidlInterface.registerCallBack(iAidlCallBack);//注册消息回调
                    messages.addAll(iAidlInterface.getMessages());//获取历史消息
                    listView.setAdapter(arrayAdapter=new ArrayAdapter<>(getApplicationContext(),android.R.layout.simple_list_item_1,messages));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
    
            }
        };
    
        private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
            //当承载IBinder的进程消失时接收回调的接口
            @Override
            public void binderDied() {
                if (null == iAidlInterface) {
                    return;
                }
                try {
                    iAidlInterface.unregisterCallBack(iAidlCallBack);//注销
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
                iAidlInterface = null;
            }
        };
    
        private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() {
            @Override
            public void onMessageSuccess(String message) {
                if (messages!=null&&arrayAdapter!=null){
                    messages.add(message);
                    handler.sendEmptyMessage(1);
                }
            }
        };
    
        @SuppressLint("HandlerLeak")
        private Handler handler=new Handler(){
            @Override
            public void handleMessage(@NonNull Message msg) {
                arrayAdapter.notifyDataSetChanged();
            }
        };
    
        @Override
        protected void onDestroy() {
            //解除注册
            if (null != iAidlInterface && iAidlInterface.asBinder().isBinderAlive()) {
                try {
                    iAidlInterface.unregisterCallBack(iAidlCallBack);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
            //解除绑定服务
            unbindService(serviceConnection);
            super.onDestroy();
        }
    }
    

    到此我们的服务端就编码完成,实现效果

Android 使用AIDL进行两个APP之间通讯以及相互消息回调(一)_第4张图片

3.客户端实现

   创建client工程

  •      选中TestAidlDemo1工程右键NEW一个model,命名为clientAndroid 使用AIDL进行两个APP之间通讯以及相互消息回调(一)_第5张图片
  • 要想client项目能够连接上Service,我们直接复制上面工程的aidl文件到client工程的main文件里,这样是为了保证两个项目的aidl文件路径一致

       Android 使用AIDL进行两个APP之间通讯以及相互消息回调(一)_第6张图片

  • 而调用逻辑基本和上面MainActivity一样,需要注意一点的是,因为是两个不同进程,在这里我们不能直接bindService来调起服务端,而是通过以下代码实现
    Intent intent=new Intent();
    String ACTION = "AIDL.service";//对应服务端AndroidManifest.xml配置service action:name
    intent.setAction(ACTION);
    intent.setPackage("com.pgc.testaidldemo1");//对应服务端AndroidManifest.xml package
    bindService(intent,serviceConnection,BIND_AUTO_CREATE);

     

  • client的MainActivity全部代码

    package com.pgc.client;
    
    import android.annotation.SuppressLint;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.RemoteException;
    import android.view.View;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    
    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    
    import com.pgc.testaidldemo1.IAidlCallBack;
    import com.pgc.testaidldemo1.IAidlInterface;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import butterknife.BindView;
    import butterknife.ButterKnife;
    import butterknife.OnClick;
    
    public class MainActivity extends AppCompatActivity {
        @BindView(R.id.list_view)
        ListView listView;
        private IAidlInterface iAidlInterface;
        private int num;
        private List messages=new ArrayList<>();
        private ArrayAdapter arrayAdapter;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ButterKnife.bind(this);
            Intent intent=new Intent();
            String ACTION = "AIDL.service";
            intent.setAction(ACTION);
            intent.setPackage("com.pgc.testaidldemo1");
            bindService(intent,serviceConnection,BIND_AUTO_CREATE);
        }
    
    
        @OnClick(R.id.send_message)
        public void onViewClicked(View view) {
            if (iAidlInterface!=null){
                try {
                    iAidlInterface.sendMessage("消息"+num);
                    num++;
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    
        private ServiceConnection serviceConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                iAidlInterface=IAidlInterface.Stub.asInterface(iBinder);
                try {
                    iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0);
                    iAidlInterface.registerCallBack(iAidlCallBack);
                    messages.addAll(iAidlInterface.getMessages());
                    listView.setAdapter(arrayAdapter=new ArrayAdapter<>(getApplicationContext(),android.R.layout.simple_list_item_1,messages));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
    
            }
        };
    
        private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
            //当承载IBinder的进程消失时接收回调的接口
            @Override
            public void binderDied() {
                if (null == iAidlInterface) {
                    return;
                }
                iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
                iAidlInterface = null;
                //断线重来逻辑
            }
        };
    
        private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() {
            @Override
            public void onMessageSuccess(String message) {
                if (messages!=null&&arrayAdapter!=null){
                    messages.add(message);
                    handler.sendEmptyMessage(1);
                }
            }
        };
    
        @SuppressLint("HandlerLeak")
        private Handler handler=new Handler(){
            @Override
            public void handleMessage(@NonNull Message msg) {
                arrayAdapter.notifyDataSetChanged();
            }
        };
    
        @Override
        protected void onDestroy() {
            //解除注册
            if (null != iAidlInterface && iAidlInterface.asBinder().isBinderAlive()) {
                try {
                    iAidlInterface.unregisterCallBack(iAidlCallBack);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
            //解除绑定服务
            unbindService(serviceConnection);
            super.onDestroy();
        }
    }
    

     

  • 运行效果

  • Android 使用AIDL进行两个APP之间通讯以及相互消息回调(一)_第7张图片

源码下载地址

https://github.com/pengkongkong/TestAidlDemo1

你可能感兴趣的:(我的Android之路)