原文同一时候发表在我的博客
点我进入还能看到很多其它

需求背景

近期接到这样一个需求,须要和别的 App 进行联动交互,比方下载器 App 和桌面 App 进行联动。桌面的 App 能直接显示下载器 App 内的下载任务进度和状态。

寻找解决方式

从需求上知道了,主要问题在怎样解决跨进程的通信上边。

  1. AIDL

    AIDL 即 Android Interface Definition Language的缩写,是专为 Android 中跨进程通信接口的描写叙述语言。优缺点非常明显,长处是稳定,快。Android 专门用于跨进程通信设计的。缺点是比較麻烦,AIDL 是通信的约定,參加通信的两方都须要把这个 AIDL 文件都加入自己的代码中,然后创建 Service 来实现訪问和被訪问。

  2. ContentProvider

    作为 Android 四大基础组件之中的一个的 ContentProvider 本来它的作用仅仅是提供内容性质的跨进程訪问。可是在 API 11 (Android 3.0) 中,ContentProvider 加入了一个新的方法,能够用来进行跨进程的方法调用,ContentProvider 中这种方法的定义例如以下:

    Bundle call(String method, String arg, Bundle extras)

    从易用性来讲,这个没有 AIDL 那么麻烦,并且扩展性更强,也没有 Broadcast 过于依赖系统,API 11 应该就是主要是缺点了,别的缺点临时没发现。欢迎补充。

  3. Broadcast

    广播是最简单的:长处是把分发消息的任务所有交给 Android 系统了;缺点也是由于全交给系统了,非常多地方不受控制。缺点:

    1. 尽管广播能够通过指定包名来进行发送指向性消息,可是却不能验证消息去向 App 的签名。
    2. 系统重新启动之后,在系统的广播队列里边的消息就丢失了。

实现

为了简要,主要讲讲 ContentProvider 吧。

ContentProvider

首先是下载器 App 的 ContentProvider 代码实现

package cn.hiroz.downloader.realname;import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.util.Log;public class DownloaderContentProvider extends ContentProvider {@Overridepublic boolean onCreate() {return false;}@Overridepublic Cursor query(Uri uri, String[] strings, String s, String[] strings2, String s2) {return null;}@Overridepublic String getType(Uri uri) {return null;}@Overridepublic Uri insert(Uri uri, ContentValues contentValues) {return null;}@Overridepublic int delete(Uri uri, String s, String[] strings) {return 0;}@Overridepublic int update(Uri uri, ContentValues contentValues, String s, String[] strings) {return 0;}@Overridepublic Bundle call(String method, String arg, Bundle extras) {if ("DOWNLOAD".equals(method)) {     // 当调用我下载的时候Log.e("Downloader", "download: " + arg);// 调用桌面 App 的方法来更新状态updateStatus("download");} else ("PAUSE".equals(method)) {    // 当调用我暂停的时候Log.e("Downloader", "pause: " + arg);// 调用桌面 App 的方法来更新状态updateStatus("pause");}return null;}// 我们要调用的对方的 ContentProvider 的 URIprivate final Uri LAUNCHERCONTENTPROVIDER_URI = Uri.parse("content://cn.hiroz.launcher.LauncherContentProvider");
}private void updateStatus(String status) {getContext().getContentResolver().call(LAUNCHERCONTENTPROVIDER_URI, "UPDATE_STATUS", status, new Bundle());}

在下载器 App 的 AndroidManifest.xml 中还须要加入 ContentProvider 的定义:

<provider
    android:name="cn.hiroz.downloader.realname.DownloaderContentProvider"android:authorities="cn.hiroz.downloader.DownloaderContentProvider"android:exported="true"/>

我特地加了authorities设置。这样在交互时候訪问的 ContentProvider 的 URI 会看起来不一样。也不会暴露我真实的 ContentProvider 类

然后是桌面 App 的 ContentProvider 代码实现

package cn.hiroz.launcher.realname;import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.util.Log;public class LauncherContentProvider extends ContentProvider {@Overridepublic boolean onCreate() {return false;}@Overridepublic Cursor query(Uri uri, String[] strings, String s, String[] strings2, String s2) {return null;}@Overridepublic String getType(Uri uri) {return null;}@Overridepublic Uri insert(Uri uri, ContentValues contentValues) {return null;}@Overridepublic int delete(Uri uri, String s, String[] strings) {return 0;}@Overridepublic int update(Uri uri, ContentValues contentValues, String s, String[] strings) {return 0;}@Overridepublic Bundle call(String method, String arg, Bundle extras) {// 当被调用“更新状态”的时候if ("UPDATE_STATUS".equals(method)) {Log.e("Launcher", "update status: " + arg);}return null;}// 我们要调用的对方的 ContentProvider 的 URIprivate final Uri DOWNLOADERCONTENTPROVIDER_URI = Uri.parse("content://cn.hiroz.downloader.DownloaderContentProvider");
}public void download(String arg) {getContext().getContentResolver().call(DOWNLOADERCONTENTPROVIDER_URI, "DOWNLOAD", status, new Bundle());}public void pause(String arg) {getContext().getContentResolver().call(DOWNLOADERCONTENTPROVIDER_URI, "PAUSE", status, new Bundle());}}

在桌面 App 的 AndroidManifest.xml 中还须要加入 ContentProvider 的定义:

<provider
    android:name="cn.hiroz.launcher.realname.LauncherContentProvider"android:authorities="cn.hiroz.launcher.LauncherContentProvider"android:exported="true"/>

然后在桌面 App 中。就能够通过 LauncherContentProvider 的 download 方法和 pause 方法来调用下载器 App 的功能了(这两个方法写在这里不太合适,只是我仅仅是为了节省篇幅放一起了)。下载器 App 中被调用了方法,就会调用桌面 App 的更新状态。

这里仅仅是演示了一个交互的过程,有很多其它问题欢迎大家一起讨论学习~~

引申

  • 找不到 ContentProvider 的时候须要做一下空指针保护

  • 签名校验

Android中使用ContentProvider进行跨进程方法调用相关推荐

  1. android studio 跨进程,Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用...

    本文首发于微信公众号「后厂技术官」 在上一篇文章Android IPC机制(二)用Messenger进行进程间通信中我们介绍了使用Messenger来进行进程间通信的方法,但是我们能发现Messeng ...

  2. Android中Sharedpreferences牵涉到跨进程时不能实时读取的问题

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/11271053 在做课程表应用时,由于要设置课前提醒的时间,我通过Sharedprefere ...

  3. Android ContentProvider支持跨进程数据共享与互斥、同步 杂谈

    在开发中,假如,A.B进程有部分信息需要同步,这个时候怎么处理呢?设想这么一个场景,有个业务复杂的Activity非常占用内存,并引发OOM,所以,想要把这个Activity放到单独进程,以保证OOM ...

  4. android datepicker使用方法,android中DatePicker和TimePicker的使用方法详解

    本文以实例讲述了android中DatePicker和TimePicker的使用方法,具体步骤如下: 下面是实现具体功能的代码,其中main.xml代码为: android:layout_width= ...

  5. Android 模拟游戏手柄按键(跨进程 KeyEvent 事件)实践方案

    Android 模拟游戏手柄按键(跨进程 KeyEvent 事件)实践方案

  6. Android解析xml的方法,Android中解析XML格式数据的方法

    XML介绍:Extensible Markup Language,即可扩展标记语言 一.概述 Android中解析XML格式数据大致有三种方法: SAX DOM PULL 二.详解 2.1 SAX S ...

  7. android 使用 系统字体,Android_解析Android中使用自定义字体的实现方法,1、Android系统默认支持三种字 - phpStudy...

    解析Android中使用自定义字体的实现方法 1.Android系统默认支持三种字体,分别为:"sans", "serif", "monospace ...

  8. android中NFC读写功能的实现方法

    这篇文章主要为大家详细介绍了android中NFC读写功能的实现方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本文实例为大家分享了android中NFC读写功能的 ...

  9. android获取颜色资源,Android中获取颜色的几种方法

    Android中获取颜色的几种方法: 通过android封装好的Color类中的常量 public static final int BLACK = 0xFF000000; public static ...

最新文章

  1. Laravel5.2之Filesystem-从Dropbox中下载文件到AWS S3
  2. 5年程序员生涯,使用的最频繁的Git 命令总结
  3. 【搜索引擎基础知识2】网络爬虫
  4. 【Mybatis-Plus】(一)初识Mybatis-Plus 入门案例
  5. find 的-regex 与 -name的区别
  6. 自步对比学习: 充分挖掘无监督学习样本
  7. java常用的空对象 null
  8. URAL K-based Numbers(1-3)
  9. 区块如何防篡改_CFCA联盟链荣获“2020区块链技术与应用创新成果”奖
  10. (6)Python集合
  11. 播布客里小布老师的所有视频收集
  12. 十五、分布式相关理论
  13. 数说IN语丨万豪酒店再敲警钟!防数据泄露,数博士有妙招!
  14. uniapp自定义导航栏,手机顶部通知栏字体颜色修改
  15. K12在线教育App如何实现用户增长?
  16. BIM电子沙盘编辑软件BIMSHOW开启下载了
  17. 论浏览器冲突引起的桌面和任务栏图标一直闪的解决办法
  18. 小游戏推广项目,适合新手操作的网路项目
  19. 微信开放平台open认证_在Open Knowledge上传播开放数据的日常任务
  20. UE5如何将屏幕坐标转为世界坐标和世界方向

热门文章

  1. linux IP类常用命令
  2. zend studio搭建php开发环境搭建,PHP-Zend Studio PHP环境的搭建
  3. 大前端开发者需要了解的基础编译原理和语言知识
  4. Django 之Form
  5. C/S与B/S架构的区别和优缺点
  6. android SDK Manager 代理服务器设置
  7. 最为一个领导,我该怎么领导
  8. jQuery css()选择器使用说明
  9. ASP.NET Web - 服务器控件
  10. Android 的 SDK Manager 无法启动 闪退解决方法