ContentProvider跨进程通信

什么是ContentProvider

是Android的四大组件之一,主要用于不同的应用程序之间实现数据共享功能

什么是ContentResolver

是数据调用者,ContentProvider将数据发布出来,通过ContentResolver对象结合Uri进行调用,可以对ContentProvider进行增删改查

什么是Uri

Uri(Uniform Resource Identifier通用资源标识)代表数据操作的地址,每一个ContentProvider发布数据时都会有唯一的地址。ContentProvider中的Uri有固定格式,如下图:

ContentProvider跨进程通信
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/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球