专栏首页搜狗测试Android中进程间通信(IPC)方式,知多少?

Android中进程间通信(IPC)方式,知多少?

【一、前言】

小编在车机项目测试中,有很多的定制需求,需要系统或者第三方应用和车机应用进行通信,故针对此部分学习下,希望不再做测试小白。

IPC(Inter-Process Communication)为进程间通信或跨进程通信,是指两个进程进行进程间通信的过程。

在Android中,为每一个应用程序都分配了一个独立的虚拟机,不同虚拟机在内存分配上都有不同的地址空间,互相访问数据需要借助其他手段。下面介绍在Android中实现IPC的方式。

【二、Android中进程间通信方式】

1、使用Bundle的方式

在Android中三大组件(Activity,Service,Receiver)都支持在Intent中传递Bundle数据,由于Bundle实现了Parcelable接口(一种特有的序列化方法),所以它可以很方便的在不同的进程之间进行传输。当在一个进程中启动另外一个进程的Activity,Service,Receiver时,可以在Bundle中附加需要传输给远程的进程的信息,并通过Intent发送出去。

putExtras(Bundle data):向Intent中放入所需要“携带”的数据包。

Bundle getExtras():取出Intent中所“携带”的数据包。

注意:我们传输的数据必须基本数据类型或者能够被序列化。

利用Bundle进行进程间通信,只能是单方向的简单数据传输,使用有一定的局限性。

2、使用文件共享的方式

文件共享:将对象序列化之后保存到文件中,在通过反序列,将对象从文件中读取出来。此方式对文件的格式没有具体的要求,可以是文件、XML、JSON等。

文件共享方式也存在着很大的局限性,如并发读/写问题,如读取的数据不完整或者读取的数据不是最新的。文件共享适合在对数据同步要求不高的进程间通信,并且要妥善处理并发读/写的问题。

3、使用Messenger的方式

我们也可以通过Messenger来进行进程间通信,在Messenger中放入我们需要传递的数据,实现进程间数据传递。Messenger只能传递Message对象,Messenger是一种轻量级的IPC方案,它的底层实现是AIDL。

服务端

(1):创建Service;

(2):构造Handler对象,实现handlerMessage方法;

(3):通过Handler对象,构造Messenger对象;

(4):通过Service的onBind()返回这个Messenger对象底层的Binder对象;

客户端

(1):创建Actvity;

(2):绑定远程进程Service;

(3):创建ServiceConnection,监听绑定服务的回调;

(4):通过onServiceConnected()方法的参数,构造客户端Messenger对象;

(5):通过Messenger向服务端发送消息。

Messenger的工作原理图:

Messenger内部消息处理使用Handler实现的,所以它是以串行的方式处理客服端发送过来的消息的,如果有大量的消息发送给服务器端,服务器端只能一个一个处理,如果并发量大的话用Messenger就不合适了,而且Messenger的主要作用就是为了传递消息,很多时候我们需要跨进程调用服务器端的方法,这种需求Messenger就无法做到了。

4、使用AIDL的方式

AIDL(Android Interface Definition Language)是一种IDL语言,用于生成可以在Android设备上两个进程之间进行进程间通信(IPC)的代码。

如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。AIDL是IPC的一个轻量级实现,Android也提供了一个工具,可以自动创建Stub(类架构,类骨架)。在应用间通信时,需要以下几步:

(1):定义一个AIDL接口;

(2):为远程服务(Service)实现对应Stub;

(3):将服务“暴露”给客户程序使用;

只有当你允许来自不同的客户端访问你的服务并且需要处理多线程问题时你才必须使用AIDL,其他情况下都可以选择其他方法。AIDL是处理多线程、多客户端并发访问的,而Messenger是单线程处理。

5、使用ContentProvider的方式

ContentProvider(内容提供者)是Android中的四大组件之一,为了在应用程序之间进行数据交换,Android提供了ContentProvider,ContentProvider是不同应用之间进行数据交换的API,一旦某个应用程序通过ContentProvider暴露了自己的数据操作的接口,那么不管该应用程序是否启动,其他的应用程序都可以通过接口来操作接口内的数据,包括数据的增、删、改、查等操作。

开发一个ContentProvider:

(1):定义自己的ContentProvider类,该类集成ContentProvider基类;

(2):在AndroidMainfest.xml中注册这个ContentProvider,注册时要给ContentProvider绑定一个域名;

(3):当注册好这个ContentProvider后,其他应用就可以访问ContentProvider暴露出来的数据了。

ContentProvider只是暴露出来可供其他应用操作的数据,其他应用则需要通过ContentProvider来操作。

使用ContentResolver操作数据:

(1):调用Activity的getContentResolver()获取ContentResolver对象;

(2):根据调用的ContentResolver的insert()、delete()、update()和query()方法操作数据库。

6、使用广播接收者(Broadcast)的方式

广播是一种被动跨进程通信方式。当某个程序向系统发送广播时,其他的应用程序只能被动地接收广播数据。

Broadcast Receiver本质上是一个系统级的监听器,它专门监听各个程序发出的Broadcast,因此它拥有自己的进程,只要存在与之匹配的Intent被广播出来,Broadcast Receiver总会被激发。只要注册了某个广播之后,广播接收者才能收到该广播。广播注册的一个行为是将自己感兴趣的Intent Filter注册到Android系统的AMS(Activity Manager Service)中,里面保存了一个Intent Filter列表。广播发送者将Intent Filter的action行为发送到AMS中,然后遍历AMS中的Intent Filter列表,看谁订阅了该广播,然后将消息遍历发送到注册了相应的Intent Filter或者Service中---也就是说:会调用抽象方法onReceive()方法。其中AMS起到了中间桥梁的作用。

程序启动Broadcast Receiver:

(1):创建需要启动的Broadcast Receiver的intent;

(2):调用Context的sendBroadcast()或者sendOrderBroadcast()方法来启动指定的BroadcastReceivert。

每当Broadcast事件发生后,系统会创建对应的Broadcast Receiver实例,并自动触发onReceiver()方法,onReceiver()方法执行完后,BroadcastReceiver实例就会被销毁。

Tips:onReceiver()方法中尽量不要做耗时操作,如果onReceiver()方法不能再10秒之内完成事件的处理,Android会认为该进程无响应,也就弹出我们熟悉的ANR。

7、使用Socket的方式

Socket也是实现进程间通信的一种方式,Socket也称为“套接字”(网络通信中概念),通过Socket也可以实现跨进程通信,Socaket主要还是应用在网络通信中。

【三、Android 进程间通信不同方式的比较】

  • Bundle:四大组件间的进程间通信方式,简单易用,但传输的数据类型受限。
  • 文件共享: 不适合高并发场景,并且无法做到进程间的及时通信。
  • Messenger: 数据通过Message传输,只能传输Bundle支持的类型。
  • ContentProvider:android 系统提供的,简单易用,但使用受限,只能根据特定规则访问数据。
  • AIDL:功能强大,支持实时通信,但使用稍微复杂。
  • Socket:网络数据交换的常用方式。

本文分享自微信公众号 - 搜狗测试(SogouQA),作者:baiyang

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-05-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何迎接Android Q

    在这里,我们可以获取Android新版本的相关信息,如本次Android Q Beta版本,我们可以获知它的几大特点。 ①隐私保护持续升级 在新版本Andro...

    用户5521279
  • 大日志,看我如何对付你

    在服务器接口测试中,我们经常会和各种日志打交道。一旦测试时服务端出现了问题,而单凭服务端的日志又不能发现问题原因的时候,往往开发要向我们测试人员询问...

    用户5521279
  • iOS代码调试之LLDB命令

    在LLDB模式下,根据需要输入相关的LLDB调试命令既可进行代码调试,下面小编将给大家介绍几款常用的LLDB命令。 1.打印 打印是代码调试中最常用...

    用户5521279
  • 编程一样可以很带感

        这个想法在我脑子里已经存在很久了,大约从大二的时候就开始有这个想法,原因是当时看到我心中无限向往和喜爱的计算机被教材和老师教授成那个样子,很多身边的同学...

    一心一怿
  • 如何使用Mytop监控MySQL性能

    Mytop是一个用于监控MySQL性能的开源命令行工具。它受到名为top的Linux系统监视工具的启发,在外观和感觉上类似于它。Mytop连接到MySQL服务器...

    一步
  • 资讯 | DARPA 最新计划 L2M:研发超越图灵模型和诺依曼架构的新型计算机

    选自CIO 作者:Agam Shah 机器之心编译 参与:黄小天 DARPA 认为,计算机应该做的不仅是计算,还有像人一样学习。 ? 美国国防部高级研究计划局(...

    机器之心
  • 快手(AAU)更新记录v2.9.1.12

    用户2135432
  • 60万人才储备, 谷歌收购 Kaggle 背后利益分析

    【新智元导读】Kaggle 是一个预测建模和机器学习竞赛的众包平台,Google 收购 Kaggle 令它得以在这个人才紧缺的市场获得60万数据科学家的人才储备...

    新智元
  • 一次模块重构的总结

    不同子类通过重写 BaseItem 的公共属性的 set、get 方法来达到初始化组件或者获取所需提交数据等 这一步中把转化的逻辑都写在了自定义控件内部,对...

    進无尽
  • 建立缓存,防高并发代码demo

    我在之前的博客中提到过——缓存并发,当一个key过期时,访问这个key的请求量过大,穿透到数据库.解决办法:1,分布式锁,保证每个key同时只有一个线程去查询数...

    算法之名

扫码关注云+社区

领取腾讯云代金券