IPC之ContentProvider

2019-12-17  本文已影响0人  钦_79f7

参考Android开发艺术探索

Provider 服务端

class BookProvider : ContentProvider() {
    companion object {
        const val TAG = "BookProvider"
        const val AUTHORITY = "${BuildConfig.APPLICATION_ID}.book_provider"

        val USER_CONTENT_URI: Uri = Uri.parse("content://$AUTHORITY/user")
        val BOOK_CONTENT_URI: Uri = Uri.parse("content://$AUTHORITY/book")

        const val BOOK_URI_CODE = 0
        const val USER_URI_CODE = 1
    }

    private val sUriMatcher = UriMatcher(UriMatcher.NO_MATCH)
    private lateinit var mDb: SQLiteDatabase

    init {
        //创建URI关联,可以进入SDK中查看注释使用示例
        //这里将 book 和 user 两个表分别与URICode进行了关联,分别为 0 和 1
        sUriMatcher.addURI(AUTHORITY, "book", BOOK_URI_CODE)
        sUriMatcher.addURI(AUTHORITY, "user", USER_URI_CODE)
    }

    private fun getTableName(uri: Uri): String {
        return when (sUriMatcher.match(uri)) {
            BOOK_URI_CODE -> DbOpenHelper.BOOK_TABLE_NAME
            USER_URI_CODE -> DbOpenHelper.USER_TABLE_NAME
            else -> ""
        }
    }


    override fun onCreate(): Boolean {
        Logs.d(TAG, "onCreate, current thread is : ${Thread.currentThread().name}")
        initProviderData()
        return true
    }

    /**
     * 初始化数据库,执行数据库操作属于耗时操作
     */
    private fun initProviderData() {
        println("provider init data")
        mDb = DbOpenHelper(context).writableDatabase
        mDb.execSQL("delete from ${DbOpenHelper.BOOK_TABLE_NAME}")
        mDb.execSQL("delete from ${DbOpenHelper.USER_TABLE_NAME}")
        mDb.execSQL("insert into book values(3,'Android');")
        mDb.execSQL("insert into book values(4,'iOS');")
        mDb.execSQL("insert into book values(5,'Html5');")
        mDb.execSQL("insert into user values(1,'jake',1);")
        mDb.execSQL("insert into user values(2,'jasmine',0);")
    }

    override fun insert(uri: Uri, values: ContentValues?): Uri {
        Logs.d(TAG, "insert, current thread is : ${Thread.currentThread().name}")
        val tableName = getTableName(uri)
        if (tableName.isEmpty()) {
            throw IllegalArgumentException("Unsupported URI: $uri")
        }
        mDb.insert(tableName, null, values)
        context.contentResolver.notifyChange(uri, null)
        return uri
    }

    override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor? {
        Logs.d(TAG, "query, current thread is : ${Thread.currentThread().name}")
        val tableName = getTableName(uri)
        if (tableName.isEmpty()) {
            throw IllegalArgumentException("Unsupported URI : $uri")
        }
        return mDb.query(tableName, projection, selection, selectionArgs, null, null, sortOrder, null)
    }


    override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?): Int {
        val row = mDb.update(getTableName(uri), values, selection, selectionArgs)
        if (row > 0) {
            context.contentResolver.notifyChange(uri, null)
        }
        return row
    }

    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
        val count = mDb.delete(getTableName(uri), selection, selectionArgs)
        if (count > 0) {
            context.contentResolver.notifyChange(uri, null)
        }
        return count
    }

    override fun getType(uri: Uri?): String? {
        Logs.d(TAG, "getType, current thread is : ${Thread.currentThread().name}")
        return null
    }
}

客户端

class ProviderActivity : AppCompatActivity() {
    companion object {
        const val TAG = "ProviderActivity"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_provider)
        setTitle(R.string.title_content_provider)

        executeSQL()
    }

    private fun executeSQL() {
        val values = ContentValues()
        values.put("_id", 6)
        values.put("name", "程序设计艺术")
        contentResolver.insert(BookProvider.BOOK_CONTENT_URI, values)
        val bookCursor = contentResolver.query(BookProvider.BOOK_CONTENT_URI, arrayOf("_id", "name"), null, null, null)
        while (bookCursor.moveToNext()) {
            Logs.d(TAG, "query book: ${Book(bookCursor.getInt(0), bookCursor.getString(1))}")
        }
        bookCursor.close()

        val userCursor = contentResolver.query(BookProvider.USER_CONTENT_URI, arrayOf("_id", "name", "sex"), null, null, null)
        while (userCursor.moveToNext()) {
            Logs.d(TAG, "query user : ${User(userCursor.getInt(0), userCursor.getString(1), userCursor.getInt(2))}")
        }
        userCursor.close()
    }
}

数据库辅助类

class DbOpenHelper(context: Context) : SQLiteOpenHelper(context, DB_NAME, null, DB_VERSION) {
    companion object {
        const val DB_VERSION = 1
        const val DB_NAME = "book_provider.db"
        const val BOOK_TABLE_NAME = "book"
        const val USER_TABLE_NAME = "user"

        //图书和用户信息表
        const val CREATE_BOOK_TABLE = "CREATE TABLE IF NOT EXISTS $BOOK_TABLE_NAME(_id INTEGER PRIMARY KEY,name TEXT)"
        const val CREATE_USER_TABLE = "CREATE TABLE IF NOT EXISTS $USER_TABLE_NAME(_id INTEGER PRIMARY KEY,name TEXT,sex INT)"
    }

    override fun onCreate(db: SQLiteDatabase) {
        db.execSQL(CREATE_BOOK_TABLE)
        db.execSQL(CREATE_USER_TABLE)
    }

    override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
}

AndroidManifets

        <!-- 关于权限的声明,还可以分为读权限与写权限,外界应用在访问此provider的时候必须依次声明相应的读写权限,否则外界应用会异常终止 -->
        <provider
            android:name=".demo.provider.BookProvider"
            android:authorities="${applicationId}.book_provider"
            android:permission="com.qxb.PROVIDER"
            android:process=":provider" />
        <activity android:name=".demo.provider.ProviderActivity" />

运行结果

com.stone.testdemo:provider D/BookProvider: [ main: (BookProvider.kt:48) onCreate ] - onCreate, current thread is : main
com.stone.testdemo:provider I/System.out: provider init data
com.stone.testdemo:provider D/BookProvider: [ Binder_2: (BookProvider.kt:69) insert ] - insert, current thread is : Binder_2
com.stone.testdemo:provider D/BookProvider: [ Binder_1: (BookProvider.kt:80) query ] - query, current thread is : Binder_1
com.stone.testdemo D/ProviderActivity: [ main: (ProviderActivity.kt:31) executeSQL ] - query book: Book(id=3, name=Android)
t:31) executeSQL ] - query book: Book(id=4, name=iOS)
com.stone.testdemo D/ProviderActivity: [ main: (ProviderActivity.kt:31) executeSQL ] - query book: Book(id=5, name=Html5)
t:31) executeSQL ] - query book: Book(id=6, name=程序设计艺术)
com.stone.testdemo:provider D/BookProvider: [ Binder_2: (BookProvider.kt:80) query ] - query, current thread is : Binder_2
com.stone.testdemo D/ProviderActivity: [ main: (ProviderActivity.kt:37) executeSQL ] - query user : User(id=1, name=jake, sex=1)
t:37) executeSQL ] - query user : User(id=2, name=jasmine, sex=0)
上一篇下一篇

猜你喜欢

热点阅读