AIDL之双向通信

上一篇《Android进程通信一之AIDL》
说到进程A---->B拿去数据,那问题来了,B进程如果有了数据更新,如何回调给A啊?
这篇文章就来聊聊这个

原理

声明一个 AIDL 接口,然后在服务端所实现的 AIDL 接口中通过注册和注销来添加和删除声明的 AIDL 接口。然后在服务端需要发消息给客户端的时候遍历所有已注册的接口来发起通信,这就是为什么说AIDL可以一对多通信。

第一步

声明AIDL文件,并新增接口方法
在这里插入图片描述

// IMyAidlInterface.aidl
package com.ly.aidltest;
import com.ly.aidltest.Student;
import com.ly.aidltest.IReceive;

// Declare any non-default types here with import statements
/**除了默认的基本类型,就是下面直接生成出来的方法自带的这6种类型不需要import之外,其他的都需要手动import
* 其他类型包括下面几种:
*List 接口(会自动将List接口转为 ArrayList),且集合的每个元素都必须要么是基本类型,要么是Parcelable实现类
*Map 接口(会自动将 Map 接口转为 HashMap),且每个元素的 key 和 value 要么是基本类型,要么是Parcelable实现类
*Parcelable 的实现类
*AIDL 接口本身
*/


interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
    //定义两个方法,也就是提供给客户端的服务
    List<Student> getStudent();
    //这里的in 是有讲究的
    void addStudent(in Student stu);

    void registerListener(IReceive listener);
    void unregisterListener(IReceive listener);
}
第二步

服务端注册回调,并发送数据

public class MyService extends Service {
    private List<Student> list = new ArrayList<>();
     aidl 接口专用容器
    private RemoteCallbackList<IReceive>callbackList = new RemoteCallbackList<>();
    private static final String TAG = "MyService";
    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "onCreate: ");
        list.add(new Student("小明", 12));
        list.add(new Student("小红", 13));
        list.add(new Student("小军", 14));
    }
    private IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }
        @Override
        public List<Student> getStudent() throws RemoteException {

            return list;
        }
        @Override
        public void addStudent(Student stu) throws RemoteException {
            Log.e(TAG, "setStudent: " );
            list.add(stu);
            //beginBroadcast----finishBroadcast成对出现
            int size = callbackList.beginBroadcast();
            // 向客户端通信
            for(int i=0;i<size;i++){
                IReceive receiver = (IReceive) callbackList.getBroadcastItem(i);
                receiver.onNewStudentAdded(stu);
            }
            callbackList.finishBroadcast();

        }

        @Override
        public void registerListener(IReceive listener) throws RemoteException {
            callbackList.register(listener);
        }

        @Override
        public void unregisterListener(IReceive listener) throws RemoteException {
            callbackList.unregister(listener);
        }
    };
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind: " );
        return mBinder;
    }

第三步

客户端注册回调接收数据

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private  IMyAidlInterface sub;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            sub =  IMyAidlInterface.Stub.asInterface(service);
            try {
                List<Student> list = sub.getStudent();
                for(Student s : list){
                    Log.e(TAG, "onServiceConnected: "+s.getName()+" age:"+s.getAge());
                }
                sub.registerListener(listener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.tv).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(sub!=null){
                    try {
                        sub.addStudent(new Student("新来的",20));
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        Intent intent = new Intent();
        //5.0之后如果使用隐式启动service需要加上package
        intent.setPackage(getPackageName());
        intent.setAction("com.ly.aidltest.MyService");
        bindService(intent,connection,BIND_AUTO_CREATE);
    }

    private IReceive.Stub listener = new IReceive.Stub() {
        @Override
        public void onNewStudentAdded(Student stu) throws RemoteException {
            Log.e(TAG, "onNewStudentAdded--threadId"+Thread.currentThread().getId()+" name:"+stu.getName() );

        }
    };
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(sub!=null){
            try {
                sub.unregisterListener(listener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        unbindService(connection);
    }
}
RemoteCallbackList

这个对象只是Android帮我们封装的用于binder传输的对象而已,没有必要深究,实际上我们更要做的是不使用AIDL实现binder跨进程,这样才能真正理解Android的跨进程通信。
源码参见:
https://github.com/YuxiangZhu/AIDLTest

下一篇,我们来聊一聊binder原理,这样我们才知道AIDL到底省了我们多少事儿!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Android AIDLAndroid Interface Definition Language)是一种Android中用于实现跨进程通信的机制。它允许一个应用程序的进程与另一个应用程序的进程进行交互。 在AIDL中,双向通信可以通过以下步骤实现: 1. 创建AIDL接口:首先,在服务提供方的应用程序中创建一个AIDL接口类,该接口定义了需要在两个应用程序之间进行通信的方法。 2. 实现AIDL接口:在服务提供方的应用程序中实现AIDL接口。这些方法将用于处理由客户端发起的请求。 3. 绑定Service:在客户端应用程序中,通过绑定Service与提供方建立连接。这可以通过Intent和bindService()方法完成。 4. 获取Service接口:一旦客户端与服务提供方建立了连接,客户端将获得Service的接口。这个接口将通过onServiceConnected()方法返回给客户端。 5. 调用方法:客户端可以使用接口对象来调用服务提供方的方法,从而向服务提供方发送请求。 6. 返回结果:服务提供方在接收到请求后,根据请求的类型进行相应的处理,并将处理结果返回给客户端。 通过以上步骤,双向通信将会在两个应用程序之间建立起来。服务提供方可以处理客户端的请求,并将结果返回给客户端。而客户端可以调用服务提供方的方法,并获取所需的数据。 需要注意的是,为了保证AIDL双向通信的正常运行,需要在AndroidManifest.xml文件中声明相应的权限和服务。 总结来说,使用Android AIDL可以实现双向通信。服务提供方与客户端通过AIDL接口进行交互,客户端发送请求给服务提供方,并获取处理结果。这种机制可以方便地实现不同应用程序之间的数据交换和通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alex_ChuTT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值