总所周知,ContentProvider用于跨进程通信,可以通过继承ContentProvider实现query、insert、delete、update、getType方法,来让其他进程对本进程的数据库进行CRUD增删改查操作,一般这是涉及到数据大的时候,如果涉及的数据量很小,可以通过重写ContentProvider的call 方法来简单实现跨进程通信;
注意:自定义的ContentProvider也是可以在AndroidManifest.xml中指定运行在子进程的,和自定义的Service一样
1、继承ContentProvider,重写必须实现的方法和call方法:
package com.example.myapplication
import android.content.ContentProvider
import android.content.ContentValues
import android.database.Cursor
import android.net.Uri
import android.os.Bundle
import android.util.Log
class MyContentProvider: ContentProvider() {
override fun onCreate(): Boolean {
return true
}
override fun query(
p0: Uri,
p1: Array<out String>?,
p2: String?,
p3: Array<out String>?,
p4: String?
): Cursor? {
return null
}
override fun getType(p0: Uri): String? {
return null
}
override fun insert(p0: Uri, p1: ContentValues?): Uri? {
return null
}
override fun delete(p0: Uri, p1: String?, p2: Array<out String>?): Int {
return 0
}
override fun update(p0: Uri, p1: ContentValues?, p2: String?, p3: Array<out String>?): Int {
return 0
}
override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
Log.d("Alex", "call(method: $method, arg: String?, extras: Bundle?)")
return super.call(method, arg, extras)
}
override fun call(authority: String, method: String, arg: String?, extras: Bundle?): Bundle? {
Log.d("Alex", "call(authority: String, method: $method, arg: String?, extras: Bundle?)")
return super.call(authority, method, arg, extras)
}
}
<provider
android:name=".MyContentProvider"
android:authorities="com.example.myapplication.MyContentProvider"
android:exported="true"/>
2、模拟一个其他进程,比如服务进程:
package com.example.myapplication
import android.app.Service
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.IBinder
import androidx.annotation.RequiresApi
class Myservice: Service() {
companion object {
const val URI: String = "content://com.example.myapplication.MyContentProvider/"
}
@RequiresApi(Build.VERSION_CODES.Q)
override fun onCreate() {
super.onCreate()
// contentResolver通过Context实例可以拿到
contentResolver.call(Uri.parse(URI), "onEvent", "", null)
}
override fun onBind(p0: Intent?): IBinder? {
TODO("Not yet implemented")
}
}
<service
android:name=".Myservice"
android:process=":myservice"></service>
3、找个地方开启这个服务进程:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
// TODO: Use the ViewModel
activity?.startService(Intent(activity, Myservice::class.java))
}
4、打印结果,表明已经实现了跨进程通信,服务进程已经调用了ContentProvider的call方法:
2022-12-25 12:15:47.685 10970-18681/com.example.myapplication D/Alex: call(authority: String, method: onEvent, arg: String?, extras: Bundle?)
2022-12-25 12:15:47.685 10970-18681/com.example.myapplication D/Alex: call(method: onEvent, arg: String?, extras: Bundle?)
这里已经能看到传过来的method方法名“onEvent” , 其他参数都可以自定义哈。
好了,又可以愉快玩耍了。