当谈到在 Android 上实现跨进程通信(IPC)时,ContentProvider
往往是一个备受关注的话题。ContentProvider
作为 Android 中的一种数据共享机制,最初设计用于应用内数据的共享和访问,但它也被广泛应用于不同应用程序之间的进程间通信。
上一篇文章讲述了如何利用BroadcastReceiver
在进程之间通信,用广播的方式虽然能够达到通信效果,但是在进程被杀死的情况下还是无法通信。所以本文来介绍另一种进程之间的通信方式在进程被意外杀死的情况下依然可以接收到另一个进程的消息。
ContentProvider
是 Android
系统提供的一种用于管理应用程序数据的组件。尽管其名称可能会让你误以为它仅仅提供数据存储的功能,但实际上它更像是一个数据访问的中间层,允许应用程序之间共享数据,并提供统一的接口供其他应用程序访问和操作这些数据。
主要用途包括:
ContentProvider
可以允许应用程序之间共享数据。这些数据可以是结构化的、非结构化的,甚至可以是文件、数据库中的数据等。ContentProvider
提供的标准化接口,其他应用程序可以访问和操作相应应用程序的数据,包括增删改查等操作。ContentProvider
使用 URI
来标识数据,其他应用程序可以使用 URI
来定位和访问特定数据。ContentProvider
可以定义权限来控制哪些应用程序有权访问数据,从而保护数据安全性。在A项目中创建一个名为
AppProvider
的类,继承ContentProvider
,主要是在call
方法中写接收消息的逻辑判断,代码示例如下。
@Override
public Bundle call(String method, String arg, Bundle extras) {
if ("receive_B_msg".equals(method)) {
String packageName = extras.getString("packageName");
Log.d("call", "--- AppProvider receive_B_msg packageName:" + packageName);
if (mContext != null){
//你的逻辑操作
}else {
Log.d("call", "--- AppProvider call() mContext is null");
}
return extras;
}
return null;
}
在A项目的清单文件内对自定义的
AppProvider
进行声明注册。其中authorities
是B发消息的路径名称
<application>
<provider
android:name=".AppProvider"
android:authorities="aaaaaaaa"
android:exported="true" />
</application>
<queries>
<package android:name="com.xzhy.bdemo" />
<provider android:authorities="com.xzhy.bdemo.AppProvider" />
</queries>
在B项目中调用下面代码对A发送消息
ContentResolver resolver = getContentResolver();
Bundle extras = new Bundle();
extras.putString("clsName", "SomeClassName");
extras.putString("status", "SomeStatus");
extras.putString("packageName", "com.xzhy.bdemo");
extras.putString("processName", "SomeProcessName");
resolver.call(Uri.parse("content://aaaaaaaa"), "receive_B_msg", null, extras);
查看A项目的日志可以发现已经成功收到了B发来的消息。
在真机上面使用A、B两个进程关闭掉A的情况下发消息,B进程项目是会报错的无法找到路径,但是在模拟器7.0的手机上测试却不会报错显示。
本文简单的介绍了如何利用ContentProvider
在跨进程之间进行通信,需要注意的是虽然在杀死掉进程A后B进程发消息会受影响,但实际上在同一个App下开启另一个进程在原本进程和新开进程之间用这种方式即使进程被杀死也依然是可以做到通信的。本文仅仅是开两个App进程进行的测试,遇到的业务场景比如说在一个APP下你用来做壳包,通过虚拟加载的形式在打开App后安装了另一个App,此时新的App需要与原本的壳包进程进行通信可以采用ContentProvider
的形式进行通信不用关心壳包是否被杀死也可以收到消息。