Android中使用ContentProvider进行跨进程方法调用
原文同一时候发表在我的博客
点我进入还能看到很多其它
需求背景
近期接到这样一个需求,须要和别的 App 进行联动交互,比方下载器 App 和桌面 App 进行联动。桌面的 App 能直接显示下载器 App 内的下载任务进度和状态。
寻找解决方式
从需求上知道了,主要问题在怎样解决跨进程的通信上边。
AIDL
AIDL 即 Android Interface Definition Language的缩写,是专为 Android 中跨进程通信接口的描写叙述语言。优缺点非常明显,长处是稳定,快。Android 专门用于跨进程通信设计的。缺点是比較麻烦,AIDL 是通信的约定,參加通信的两方都须要把这个 AIDL 文件都加入自己的代码中,然后创建 Service 来实现訪问和被訪问。
ContentProvider
作为 Android 四大基础组件之中的一个的 ContentProvider 本来它的作用仅仅是提供内容性质的跨进程訪问。可是在 API 11 (Android 3.0) 中,ContentProvider 加入了一个新的方法,能够用来进行跨进程的方法调用,ContentProvider 中这种方法的定义例如以下:
Bundle call(String method, String arg, Bundle extras)从易用性来讲,这个没有 AIDL 那么麻烦,并且扩展性更强,也没有 Broadcast 过于依赖系统,API 11 应该就是主要是缺点了,别的缺点临时没发现。欢迎补充。
Broadcast
广播是最简单的:长处是把分发消息的任务所有交给 Android 系统了;缺点也是由于全交给系统了,非常多地方不受控制。缺点:
- 尽管广播能够通过指定包名来进行发送指向性消息,可是却不能验证消息去向 App 的签名。
- 系统重新启动之后,在系统的广播队列里边的消息就丢失了。
实现
为了简要,主要讲讲 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 {
@Override
public boolean onCreate() {
return false;
}
@Override
public Cursor query(Uri uri, String[] strings, String s, String[] strings2, String s2) {
return null;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
return null;
}
@Override
public int delete(Uri uri, String s, String[] strings) {
return 0;
}
@Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
return 0;
}
@Override
public 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 的 URI
private 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 {
@Override
public boolean onCreate() {
return false;
}
@Override
public Cursor query(Uri uri, String[] strings, String s, String[] strings2, String s2) {
return null;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
return null;
}
@Override
public int delete(Uri uri, String s, String[] strings) {
return 0;
}
@Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
return 0;
}
@Override
public Bundle call(String method, String arg, Bundle extras) {
// 当被调用“更新状态”的时候
if ("UPDATE_STATUS".equals(method)) {
Log.e("Launcher", "update status: " + arg);
}
return null;
}
// 我们要调用的对方的 ContentProvider 的 URI
private 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进行跨进程方法调用的更多相关文章
- Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用
在上一篇文章Android IPC机制(二)用Messenger进行进程间通信中我们介绍了使用Messenger来进行进程间通信的方法.可是我们能发现Messenger是以串行的方式来处理client ...
- Android IPC机制(三)使用AIDL实现跨进程方法调用
上一篇文章中我们介绍了使用Messenger来进行进程间通信的方法,但是我们能发现Messenger是以串行的方式来处理客户端发来的信息,如果有大量的消息发到服务端,服务端仍然一个一个的处理再响应客户 ...
- Android四大组件应用系列——使用ContentProvider实现跨进程通讯
一.问题描述 如何在Android中实现不同应用之间的通讯(既跨进程进行调用)?Android提供了多种实现方式,使我们可以实现跨进程访问Activity.通过ContentProvider跨进程访问 ...
- Wayland中的跨进程过程调用浅析
原文地址:http://blog.csdn.net/jinzhuojun/article/details/40264449 Wayland协议主要提供了Client端应用与Server端Composi ...
- Android中View的绘制过程 onMeasure方法简述 附有自定义View例子
Android中View的绘制过程 onMeasure方法简述 附有自定义View例子 Android中View的绘制过程 当Activity获得焦点时,它将被要求绘制自己的布局,Android fr ...
- 【转】Android中引入第三方Jar包的方法(java.lang.NoClassDefFoundError解决办法)
原文网址:http://www.blogjava.net/anchor110/articles/355699.html 1.在工程下新建lib文件夹,将需要的第三方包拷贝进来.2.将引用的第三方包,添 ...
- Android中解析XML格式数据的方法
XML介绍:Extensible Markup Language,即可扩展标记语言 一.概述 Android中解析XML格式数据大致有三种方法: SAX DOM PULL 二.详解 2.1 SAX S ...
- Android 中对于图片的内存优化方法
Android 中对于图片的内存优化方法,需要的朋友可以参考一下 1. 对图片本身进行操作 尽量不要使用 setImageBitmap.setImageResource. BitmapFact ...
- android不需要Socket的跨进程推送消息AIDL!
上篇介绍了跨进程实时通讯http://www.cnblogs.com/xiaoxiaing/p/5818161.html 但是他有个缺点就是服务端无法推送消息给客户端,今天这篇文章主要说的就是服务器推 ...
随机推荐
- Linux上MySQL的安装
a.检测是否安装了mysql rpm -qa | grep mysql b.卸载系统自带的mysql rpm -e --nodeps 卸载的包 rpm -e --nodeps mysql-libs- ...
- 虚拟软件vmware安装
什么是虚拟软件: 虚拟原件是一个可以使你在一台机器上同时运行二个或更多Windows.LINUX等系统.它可以模拟一个标准PC环境.这个环境和真实的计算机一样,都有芯片组.CPU.内存.显卡.声卡.网 ...
- jquery多种方式实现输入框input输入时的onput,onpropertychange,onchange触发事件及区别
有关inputs输入内容的事件监听,一般我们会想到下面几个关键词:onput,onpropertychange,onchange onput与onchange的一个区分 onput:该事件在 < ...
- C#用panel实现子窗体的切换
今天编程的时候,遇到一个问题:在同一个窗体区域加载两个不同的窗体,每次只显示一个子窗体并能够对这两个子窗体做切换. 对于这个问题用panel控件是非常简单的,只要每次清空panel控件上的子窗体,然后 ...
- CLR类型设计之方法与构造器
无论学习那门语言都要学习函数体,C#,JAVA,PHP,都会涉及到函数体,而C#的函数体成员并不少,方法和构造器就是函数体成员之一,函数体成员还包括但不限于:方法,属性,构造器,终结器,运算符及索引器 ...
- mysql全日志添加时间戳以及SQL多行问题处理(更新)
需求引入 在日常运维中,DBA可能经常会查看某个Query_Id对应哪些SQL,例如追查大事务问题:也可能业务端需要查看某时间端内所有SQL. 然而mysql在输入全日志的时候没有在每行SQL前打印时 ...
- [C#]使用dnSpy对目标程序(EXE或DLL)进行反编译修改并编译运行
本文为原创文章.源代码为原创代码,如转载/复制,请在网页/代码处明显位置标明原文名称.作者及网址,谢谢! 本文使用的工具下载地址为: https://github.com/cnxy/dnSpy/arc ...
- final、static、代码块、静态代码块、内部类、代码执行顺序
final final域使得确保初始化安全性(initialization safety)成为可能,初始化安全性让不可变形对象不需要同步就能自由地被访问和共享 作用在类上 ...
- border-sizing属性
box-sizing属性可以为三个值之一:content-box(default),border-box,padding-box. content-box,border和padding不计算入widt ...
- 使用Gulp构建前端自动化方案
前言 在刚入门前端的时候,我们并不清楚前端有工具可以帮我们自动化打包压缩文件,当时只关注能实现功能就可以了,也不太在意前端性能优化的问题,随着项目功能的复杂,项目也变得越来越大,页面的执行速度也开始变 ...