Android笔记-ContentProvider call方法
ContentProvider call方法 使用.
资料来源:
https://developer.android.com/guide/topics/providers/content-providers
https://juejin.im/entry/5a4c39605188257c4d1b8a4a更新
1
2
320.04.17 初始化
21.02.11 添加一个错误修正
21.02.13 补充完整
导语
- 开始实现的 NoWakeLock 使用了 ContentProvider 标准的查询和插入,结果实在不尽如人意.太死板了.
- 进入瓶颈,去翻 Xprivacylua 的源码,发现 Xprivacylua 也使用了 ContentProvider ,不过大段是自定义的 call 方法.
- 从网上资料来看,call 方法确实灵活多了,也是同步的调用,底层与查询/插入都是一样的实现.传输数据一次不能超过 1M.传输的数据需要可序列化.
声明 ContentProvider
1 | class DSContentProvider : ContentProvider() { |
在 AndroidManifest.xml -> application 下声明
1 | <provider |
call 方法
fun call(method: String, arg: String?, extras: Bundle?): Bundle? {}
- method: String 一般是我们自定义 call 方法的方法名.
- arg: String? 大概是可有可无的字段.
- extras: Bundle? 传输数据的载体,需要从 Bundle 中取出对应数据.
实际的例子也非常简单
1
2
3
4
5
6
7override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
//no need handler
if (extras == null) {
return null
}
return context?.let { ProviderHandler.getInstance(it).getMethod(method, extras) }
}传入 method 到具体的 Handler,再根据具体的方法名,执行获取结果.(kt 真香😂)
以一个 test 方法为例,因为 call 方法要求返回一个 Bundle? 这里直接返回了 “Test”.
1
2
3
4
5
6
7
8
9
10
fun test(bundle: Bundle): Bundle? {
val test = bundle.get("Test") as String?
LogUtil.d(TAG, "$test")
val tmp = Bundle()
tmp.putString("Test", "Test")
return tmp
}调用 Test 方法
1
2
3
4
5
6fun getMethod(methodName: String, bundle: Bundle): Bundle? {
return when (methodName) {
"test" -> test(bundle)
else -> null
}
}AndroidTest 类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25class NWLContentProviderTest {
private var mContentResolver: ContentResolver? = null
private val authority = "com.js.nowakelock"
fun setUp() {
val context = ApplicationProvider.getApplicationContext<Context>()
mContentResolver = context.contentResolver
}
fun call() {
val method = "test"
val url = Uri.parse("content://$authority")
val extras = Bundle()
extras.putString("Test", "Test")
val bundle = mContentResolver?.call(url, method, null, extras)
//if (bundle != null) {
// LogUtil.d("test1", bundle.toString())
//}
assertEquals(bundle!!.getString("Test"), "Test")
}
}执行测试,取回的结果也是 “Test”.
AndroidX.test dependency error
参考 Set up project for AndroidX Test 添加 Android X Test 依赖
运行 NWLContentProviderTest
会提示错误:
1 | Execution failed for task ':app:processDebugAndroidTestManifest'. |
参考 AndroidX.test dependency error 发现是 androidx.fragment:fragment-testing
要求核心版本是 1.2…这不是大水冲了龙王庙吗…
原帖的解决方案没太看懂,反正先注释掉 androidx.fragment:fragment-testing
目前没有再使用.
结语
- 为了个 IPC 还折腾了 aidl + service. 还有 call 配合 service,加上之前的 XSharedPreferences ,几乎把android ipc 折腾全了…
- 之后就是填坑了,希望能尽快填完.