ContentPrivider跨应用获取数据
2022-11-14 本文已影响0人
小城哇哇
1.背景
最近公司有一个新的业务功能,需要在我们的系统的主APP里面获取到其它所有APP的播放历史记录,在接到这个需求的时候,跨进程获取第三方应用数据的方法有很多种,IPC、广播、ContentPrivider(基于AIDL),但是获取数据是所有的播放记录,所有第一选择就是ContentPrivider.
我们一般使用ContentPrivider都是用来读取第三方的数据库信息,返回的是一个Cursor,因为各个业务线的数据格式都是不一样的,必须让各个业务线返回相同的数据字段便于统一处理,开始是考虑封装一个SDK给其他各个业务,把播放记录都存放到我们统一封装的数据库表,这样做的弊端有以下两点:
- 这样的弊端就是第三方的业务要保存一份自己的数据库信息,同时还要单独在我们的SDK里面进行数据存储
- 应用之前已有的历史数据都要在第一次使用的时候导入到新的数据库
- 只能读取数据库的数据,应用获取数据不一定在本地可能在后台需要去后台读取数据
2.实现方案
为了解决上述两个弊端,在无意中看到了MatrixCursor 这个类,通过这个类可以构造一个虚拟的Cursor,即使没有数据库也能通过ContentPrivider共享数据给第三方的应用。
还是需要定义一个ContentPrivider,如下:
<pre data-language="plain" id="2YABp" class="ne-codeblock language-plain" style="border: 1px solid #e8e8e8; border-radius: 2px; background: #f9f9f9; padding: 16px; font-size: 13px; color: #595959">public class MyProvider extends ContentProvider {
// 以下是ContentProvider的6个方法
/**
* 初始化ContentProvider
*/
@Override
public boolean onCreate() {
return true;
}
/**
* 添加数据
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
// 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
// 该方法在最下面
return uri;
}
/**
* 查询数据
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
String[] tableCursor = new String[]{"name", "job", "salary"};
MatrixCursor matrixCursor = new MatrixCursor(tableCursor);
matrixCursor.addRow(new Object[]{"张三", "老司机", "11111"});
matrixCursor.addRow(new Object[]{"李四", "维修员", "2222"});
matrixCursor.addRow(new Object[]{"王五", "开发工程师", "3333"});
return matrixCursor;
}
/**
* 更新数据
*/
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// 由于不展示,此处不作展开
return 0;
}
/**
* 删除数据
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// 由于不展示,此处不作展开
return 0;
}
@Override
public String getType(Uri uri) {
// 由于不展示,此处不作展开
return null;
}
}</pre>
重点看一下这个query方法:
<pre data-language="plain" id="5N6qr" class="ne-codeblock language-plain" style="border: 1px solid #e8e8e8; border-radius: 2px; background: #f9f9f9; padding: 16px; font-size: 13px; color: #595959"> /**
* 查询数据
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
String[] tableCursor = new String[]{"name", "job", "salary"};
MatrixCursor matrixCursor = new MatrixCursor(tableCursor);
matrixCursor.addRow(new Object[]{"张三", "老司机", "11111"});
matrixCursor.addRow(new Object[]{"李四", "维修员", "2222"});
matrixCursor.addRow(new Object[]{"王五", "开发工程师", "3333"});
return matrixCursor;
}
</pre>
首先我们实例化一个MatrixCursor,传入表字段,然后通过addRow方法一次根据添加数据后返回即可;
然后把MyPrivider定义到AndroidManifest.xml文件
<pre data-language="plain" id="Rgc29" class="ne-codeblock language-plain" style="border: 1px solid #e8e8e8; border-radius: 2px; background: #f9f9f9; padding: 16px; font-size: 13px; color: #595959"> <provider
android:name="com.data.dataprovider.MyProvider"
android:authorities="${applicationId}.myprovider"
android:exported="true" /></pre>
当每个业务apk集成这个MyProvider后,我们主APP就可以直接去获取数据了
然后在系统主APP里面正常调用ContentPrivider数据一样即可:
<pre data-language="plain" id="XdLl4" class="ne-codeblock language-plain" style="border: 1px solid #e8e8e8; border-radius: 2px; background: #f9f9f9; padding: 16px; font-size: 13px; color: #595959"> // 设置URI
Uri uri_user = Uri.parse("content://scut.carson_ho.contentprovider.myprovider");
ContentResolver resolver = getContentResolver();
//可以传入参数,进行分页查询等
Cursor cursor = resolver.query(uri_user, new String[]{"page", "size","data"}, "data", new String[]{"1","10 0","123"}, null);
while (cursor.moveToNext()) {
Log.d("MatrixCursor", "query:" +" name:"+ cursor.getString(0) + " job:" + cursor.getString(1) + " salary:" + cursor.getString(2));
// 将表中数据全部输出
}
cursor.close();
//打印结果
D/MatrixCursor: query: name:张三 job:老司机 salary:11111
D/MatrixCursor: query: name:李四 job:维修员 salary:2222
D/MatrixCursor: query: name:王五 job:开发工程师 salary:3333</pre>
后续不管各个业务的数据从本地数据库还是从后台获取,都能够通过统一的字段返回,主APP不用考虑数据问题。