什么是ContentProvider
是Android的四大组件之一,主要用于不同的应用程序之间实现数据共享功能
什么是ContentResolver
是数据调用者,ContentProvider将数据发布出来,通过ContentResolver对象结合Uri进行调用,可以对ContentProvider进行增删改查
什么是Uri
Uri(Uniform Resource Identifier通用资源标识)代表数据操作的地址,每一个ContentProvider发布数据时都会有唯一的地址。ContentProvider中的Uri有固定格式,如下图:
Authority:授权信息,用以区别不同的ContentProvider;
Path:表名,用以区分ContentProvider中不同的数据表;
Id:Id号,用以区别表中的不同数据;
; 创建自定义ContentProvider的步骤:
1.使用SQLite技术,创建好数据库和数据表
2.新建类继承ContentProvider
3.重写6个抽象方法
4.创建UriMatcher,定义Uri规则
5.在Manifest中注册provider
6.ContentResolver对ContentProvider中共享的数据进行增删改查操作
A进程插入数据到数据库,步骤如下
1.创建数据库表:
package com.example.demoa
import android.content.ContentUris
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.net.Uri
const val TABLE_NAME ="weather"
const val CONTENT_AUTHORITY = "com.example.demoa.WeatherProvider"
val BASE_CONTENT_URI: Uri = Uri.parse("content://$CONTENT_AUTHORITY")
val CONTENT_URI: Uri = BASE_CONTENT_URI.buildUpon().appendPath(TABLE_NAME).build()
fun buildUri(id: Long): Uri? {
return ContentUris.withAppendedId(CONTENT_URI, id)
}
private const val DB_NAME ="weather_provider.db"
private const val DB_VERSION = 1
private const val CREATE_TABLE =
"create table if not exists $TABLE_NAME(_id integer primary key,city TEXT, weather TEXT, weather_id TEXT, temperature TEXT)"
class DbHelper(mContext: Context?) : SQLiteOpenHelper(mContext, DB_NAME, null, DB_VERSION) {
override fun onCreate(db: SQLiteDatabase?) {
db?.execSQL(CREATE_TABLE)
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
TODO("Not yet implemented")
}
}
2.创建 ContentProvider
:
package com.example.demoa
import android.content.ContentProvider
import android.content.ContentValues
import android.content.UriMatcher
import android.database.Cursor
import android.database.SQLException
import android.database.sqlite.SQLiteDatabase
import android.net.Uri
const val TEST = 100
class WeatherProvider : ContentProvider() {
private lateinit var mdb : SQLiteDatabase
companion object{
fun buildUriMatcher() : UriMatcher{
val matcher = UriMatcher(UriMatcher.NO_MATCH)
matcher.addURI(CONTENT_AUTHORITY, TABLE_NAME, TEST)
return matcher
}
}
override fun onCreate(): Boolean {
mdb = DbHelper(context).writableDatabase
return false
}
override fun query(
uri: Uri,
projection: Array<out String>?,
selection: String?,
selectionArgs: Array<out String>?,
sortOrder: String?
): Cursor? {
var cursor : Cursor? = null
when(buildUriMatcher().match(uri)){
TEST ->{
cursor = mdb.query(TABLE_NAME, projection, selection, selectionArgs, null, sortOrder, null)
}
}
return cursor
}
override fun getType(uri: Uri): String? {
return null
}
override fun insert(uri: Uri, values: ContentValues?): Uri? {
var returnUri : Uri? = null
var id : Long?
when(buildUriMatcher().match(uri)){
TEST ->{
id = mdb.insert(TABLE_NAME, null, values)
context?.contentResolver?.notifyChange(uri, null)
if(id > 0){
returnUri = buildUri(id)
}else{
throw SQLException("Failed to insert row into $uri")
}
}
else->{
SQLException("Unknown uri: $uri")
}
}
return returnUri
}
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
val num : Int = mdb.delete(TABLE_NAME, selection, selectionArgs)
context?.contentResolver?.notifyChange(uri, null)
return num
}
override fun update(
uri: Uri,
values: ContentValues?,
selection: String?,
selectionArgs: Array<out String>?
): Int {
return 0
}
}
3.插入数据:
package com.example.demoa
import android.content.ContentValues
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.example.test.R
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun insertData(view: View) {
var contentValues = ContentValues()
contentValues.put("city", "Shenzhen")
contentValues.put("weather_id", "2033432")
contentValues.put("temperature", "26")
contentResolver.delete(CONTENT_URI, null, null)
contentResolver.insert(CONTENT_URI, contentValues)
}
}
4.别忘了在AndroidManifest.xml中注册ContentProvider:
<provider
android:name="com.example.demoa.WeatherProvider"
android:authorities="com.example.demoa.WeatherProvider"
android:exported="true">
provider>
5.执行完insertData()后,数据就已经插入到数据库了
下面我们通过adb查看插入的数据
(1)cd到/data/data/com.example.demoa/databases目录下,ls可以看到weather_provider.db,但此时执行sqlite3 weather_provider.db报错 unable to open database
(2)执行 chmod 777 weather_provider.db
(3)执行 sqlite3 weather_provider.db
(4) .tables
,可以看到所有的数据库表
(5) select * from weather;
注意最后的 ;
不能省略,否则没有执行。执行完这条语句之后就可以看到数据了:1|Shenzhen||2033432|26
B进程取数据
package com.example.demob;
import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
private val TAG = MainActivity::class.simpleName
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
getInfo()
}
private fun getInfo(){
val mUri = Uri.parse("content://com.example.demoa.WeatherProvider/weather")
val cursor = this.contentResolver.query(mUri, null, null, null, null)
if (cursor != null) {
while (cursor.moveToNext()) {
val city: String = cursor.getString(1)
val weather_id: String = cursor.getString(3)
val temperature: String = cursor.getString(4)
Log.d(TAG, "$city<>$weather_id<>$temperature")
}
cursor.close()
}
}
}
Original: https://blog.csdn.net/leihu007/article/details/123530182
Author: LionelRay
Title: ContentProvider跨进程通信
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/816800/
转载文章受原作者版权保护。转载请注明原作者出处!