最简单的Activity、Service进程间 AIDL通信指南二(附github源码)

本文介绍如何实现在Android中使用AIDL进行跨进程的Activity和Service通信。详细步骤包括创建AIDL文件定义接口,Service的onBind方法返回Stub对象,以及在Activity中连接Service并调用接口获取数据。还探讨了跨进程时返回BinderProxy的原因和AIDL的工作原理。
摘要由CSDN通过智能技术生成

前言

上篇文章最简单的Activity、Service使用、通信指南一(进程内通信)(附github源码)最后提到,如果把Service设置为其他进程,那么我们使用自定义binder的方式返回的binder对象并不是我们自定义的binder对象,那样强制转换就报错误了。

那么为什么同一进程返回的是自定义binder对象,而跨进程返回的却不是自定义binder对象?BinderProxy是什么东西?

这篇文章主要是讲如何让Activity和Service跨进程通信,如果还没有看过Activity和Service同一进程通信,请看最简单的Activity、Service使用、通信指南一(进程内通信)(附github源码)

【转载请注明出处:最简单的Activity、Service使用、通信指南二(AIDL进程间通信)(附github源码) CSDN 王智博

源码下载

github:https://github.com/samwangzhibo/LoveStudy (不会使用github导入代码的同学,戳这)

效果展示:

最简单的Activity、Service使用、通信指南一(进程内通信)(附github源码)的例子一样,Service里面开启一个线程,每秒让自己的num变量加1,点击按钮,获取Service的num数值然后展示出来。

思路

这是需要和跨进程的Service连接,我们选择使用AIDL。

1.首先我们创建一个AIDL文件,用来说明我们定义的Service和Activity通信的接口

2.创建一个Service,onBind里面返回AIDL文件的Stub类的对象(这个对象实现了定义的接口)。

3.我们在Activity里面连接这个Service,获取数据展示

1.新建aidl文件

指定aidl文件的目录

新建IRemoteService.aidl文件,指定package和方法(只关注红框的内容)

他会在我们编译时生成IRemoteService.java的文件,我们看看里面有哪些东西.

可以看到多余生成了Stub的类,Stub还有一个Proxy的内部类.

2.创建Service,onbinder中返回IRemoteService.stub对象

3.Activity和Service连接,调用getNum接口获取数据

if(iRemoteService ==null)

    {
        Intent intent = new Intent(MainActivity.this, RemoteService.class);
        bindService(intent, this, BIND_AUTO_CREATE);
        commuteWithRemoteServiceBtn.setText("连接成功,点击获取跨进程service数据");
    } else

    {
        try {
            commuteWithRemoteServiceBtn.setText("获取service数据 : " + iRemoteService.getNum());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

这里获取onServiceConnected里面返回的service,然后通过IRemoteService.Stub.asInterface(service)把他转成IRemoteService的接口。

我们来看一下service是什么类型?IRemoteService.Stub.asInterface又有什么用?我们可以看出service是BinderProxy类型,和最简单的Activity、Service使用、通信指南一(进程内通信)(附github源码)返回的binder不一样(binder是onBinder里面返回的),为什么在跨进程的环境里面,就返回的是BinderProxy对象呢?

我们点开IRemoteService.Stub.asInterface方法,可以看到先调用queryLocalInterface,这个方法就是在同一进程的情况下获取自己,接下来的如果获取不到(跨进程),就把BinderProxy对象交给Stub的做一层Proxy代理。

public static com.example.wangzhibo.lovestudy.service.IRemoteService asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            //如果是同进程,直接返回本地对象
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.example.wangzhibo.lovestudy.service.IRemoteService))) {
                return ((com.example.wangzhibo.lovestudy.service.IRemoteService) iin);
            }
            return new com.example.wangzhibo.lovestudy.service.IRemoteService.Stub.Proxy(obj);
        }

然后就实现了第一次点击的时候,连接Service,第二次点击的时候getNum获取数据展示出来。

commuteWithRemoteServiceBtn.setText("获取service数据 : " + iRemoteService.getNum());

小结:

1.如果Service和Activity不在一个进程,我们发现onServiceConnection里面返回的就不是onBind()里面的对象,而是BinderProxy对象,这个时候我们需要用AIDL文件来帮助我们(当然也可以自己模仿AIDL写binder来实现)

2.AIDL文件实际上会生成java类,包含一个接口,一个Stub类,里面还有一个Proxy内部类。Activity使用Stub.asInterface获取接口对象,实际上是查询本地是否有binder,如果有就返回binder,或者就生成ProxyBinder的Stub.Proxy代理对象。

3.然后我们就能通过这个代理对象,调用接口,和远端Service通信了。

思路扩展:

1.这个Stub.Proxy何许人也?为啥能够和远端Binder通信?

2.为啥同进程情况下返回onBinde()的对象,跨进程情况返回BinderProxy而不是Binder对象?

3.每次我想要更新数据都要调用接口和服务端取数据,能不能实现服务端主动告知我数据变化,改变视图?

答案是肯定的。

下篇文章Activity传给Service回调,让Service主动修改Activity视图 三(AIDL进程间通信)(附github源码)主要实现一个Activity把回调传给Service,Service主动修改Activity视图的功能。

完整Android学习路径 请戳我的Android学习之旅(持续更新中...)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值