零基础学安卓编程

安卓开发入门教程-ContentProvider

2020-11-04  本文已影响0人  蓝不蓝编程

什么是ContentProvider

ContentProvider时安卓提供的跨应用共享数据的一种方式,它允许一个应用安全的访问另外一个应用提供的数据.

调用系统提供的ContentProvider-访问通讯录

效果图:

实现方案

  1. 在AndroidManifest.xml中添加权限
<uses-permission android:name="android.permission.READ_CONTACTS" />
  1. 在app模块build.gradle文件中添加依赖
//用于简化动态权限申请
implementation 'com.qw:soulpermission:1.3.0'
  1. 访问通讯录代码
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //对按钮添加点击事件
        button.setOnClickListener {
            readContactsWithPermission()
        }
    }

    /**
     * 先申请读取系统通讯录权限,再进行读取。
     */
    private fun readContactsWithPermission() {
        SoulPermission.getInstance()
            .checkAndRequestPermission(
                Manifest.permission.READ_CONTACTS,
                object : CheckRequestPermissionListener {
                    override fun onPermissionOk(permission: Permission) {
                        readContacts()
                    }

                    override fun onPermissionDenied(permission: Permission) {
                        toast("请授予权限")
                    }
                })
    }

    /**
     * 读取系统通讯录并展示总数和其中一个联系人的姓名与电话。
     */
    private fun readContacts() {
        val contacts: ArrayList<String> = getContactsInfo()
        contacts.forEach {
            Log.d("MainActivity", "联系人信息:$it")
        }
    }

    /**
     * 读取系统通讯录信息
     */
    private fun getContactsInfo(): ArrayList<String> {
        val dataList = ArrayList<String>()
        val cursor = contentResolver.query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null
        )
        if (cursor != null) {
            while (cursor.moveToNext()) {
                val displayName =
                    cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))
                val phone =
                    cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
                dataList.add("$displayName:$phone")
            }
            cursor.close()
        }

        return dataList
    }

    private fun toast(text: String) =
        Toast.makeText(this, text, Toast.LENGTH_LONG).show()
}

自定义ContentProvider

效果图

1. 创建ContentProvider

1). 在工程目录中单击右键,选择“New>Other>Content Provider”



2). 在窗口中设置Class Name(类名)和URI Authorities(一个全局唯一的路径,一般以自己的包名开头)



3). 创建后的ContentProvider过于冗长,此处略去.
4). 查看AndroidManifest.xml文件,里面应该已经增加了如下provider配置.
<manifest ...>
    <application ...>
        <provider
            android:name=".MyContentProvider"
            android:authorities="com.add007.providerdemo"
            android:enabled="true"
            android:exported="true"></provider>
        ...
    </application>
</manifest>

2. 添加数据库操作类

/**
 * 数据库辅助操作类
 */
class DbHelper
    (context: Context?, databaseName: String, version: Int) : SQLiteOpenHelper(
    context, databaseName, null, version
) {
    //创建用户表的sql语句,表名:user_table,包含主键_id,用户名字段:user_name。
    private var createUserTableSql =
        ("CREATE TABLE user_table(_id INTEGER PRIMARY KEY, user_name text)")

    /**
     * 创建数据库表
     */
    override fun onCreate(db: SQLiteDatabase) {
        db.execSQL(createUserTableSql)
    }

    /**
     * 数据库升级
     */
    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        val sql = "DROP TABLE IF EXISTS user_table"
        db.execSQL(sql)
        onCreate(db)
    }

    /**
     * 插入数据
     */
    fun insert(tableName: String, cv: ContentValues) = writableDatabase.insert(tableName, null, cv)

    /**
     * 删除指定数据
     */
    fun delete(tableName: String, id: Int): Int {
        val where = "_id = ?"
        val whereValue = arrayOf(id.toString())
        return writableDatabase.delete(tableName, where, whereValue)
    }

    /**
     * 删除所有数据
     */
    fun deleteAll(tableName: String) = writableDatabase.delete(tableName, null, null)

    /**
     * 更新数据
     */
    fun update(
        tableName: String, values: ContentValues, whereClause: String?, whereArgs: Array<String>?
    ) = writableDatabase.update(tableName, values, whereClause, whereArgs)

    /**
     * 查询数据,返回一个指定数据集合的游标
     */
    fun query(tableName: String): Cursor {
        return readableDatabase.query(tableName, null, null, null, null, null, null)
    }
}

3. 修改ContentProvider类

class MyContentProvider : ContentProvider() {
    private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH)
    private val authority = "cn.cxy.contentproviderdemo.provider"
    private val allUsers = 1 //返回多个记录的匹配码
    private val singleUser = 2 //返回单个记录的匹配码
    private lateinit var dbHelper: DbHelper
    private val userTable = "user_table"

    /**
     * 配置本应用支持的路径后缀
     */
    init {
        uriMatcher.addURI(authority, "user", allUsers);
        uriMatcher.addURI(authority, "user/#", singleUser);
    }

    /**
     * 创建存储数据的数据库
     */
    override fun onCreate(): Boolean {
        dbHelper = DbHelper(context, "userTable", 1)
        return true
    }

    override fun getType(uri: Uri) = when (uriMatcher.match(uri)) {
        singleUser -> "vnd.android.cursor.item/vnd.cn.cxy.contentproviderdemo.provider.user"
        allUsers -> "vnd.android.cursor.dir/vnd.cn.cxy.contentproviderdemo.provider.user"
        else -> null
    }

    /**
     * 插入数据
     */
    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        var resultUri: Uri? = null
        when (uriMatcher.match(uri)) {
            singleUser, allUsers -> {
                var userId = dbHelper.insert(userTable, values!!)
                resultUri = Uri.parse("content://$authority/user/${userId}")
            }
        }

        return resultUri
    }

    /**
     * 更新数据
     */
    override fun update(
        uri: Uri, values: ContentValues?, selection: String?,
        selectionArgs: Array<String>?
    ) = dbHelper.update("user_table", values!!, null, null)

    /**
     * 删除数据
     */
    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
        when (uriMatcher.match(uri)) {
            singleUser, allUsers -> {
                dbHelper.deleteAll(userTable)
            }
        }
        return 0
    }

    /**
     * 查询数据
     */
    override fun query(
        uri: Uri, projection: Array<String>?, selection: String?,
        selectionArgs: Array<String>?, sortOrder: String?
    ) = dbHelper.query("user_table")
}

4. activity中调用

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        addDataBtn.setOnClickListener { addUser() }
        updateDataBtn.setOnClickListener { updateUser() }
        delDataBtn.setOnClickListener { delUser() }
        queryDataBtn.setOnClickListener { queryUser() }
    }

    /**
     * 新增数据
     */
    private fun addUser() {
        GlobalScope.launch(Dispatchers.IO) {
            val uri: Uri = Uri.parse("content://cn.cxy.contentproviderdemo.provider/user")
            val values = ContentValues().apply { put("user_name", "张三") }
            contentResolver.insert(uri, values)
        }
    }

    /**
     * 更新数据
     */
    private fun updateUser() {
        GlobalScope.launch(Dispatchers.IO) {
            val uri: Uri = Uri.parse("content://cn.cxy.contentproviderdemo.provider/user")
            val values = ContentValues().apply { put("user_name", "李四") }
            contentResolver.update(uri, values, null, null)
        }
    }

    /**
     * 删除数据
     */
    private fun delUser() {
        GlobalScope.launch(Dispatchers.IO) {
            val uri: Uri = Uri.parse("content://cn.cxy.contentproviderdemo.provider/user")
            contentResolver.delete(uri, null, null)
        }
    }

    /**
     * 查询数据
     */
    private fun queryUser() {
        GlobalScope.launch(Dispatchers.IO) {
            val uri = Uri.parse("content://cn.cxy.contentproviderdemo.provider/user")
            val cursor = contentResolver.query(uri, null, null, null, null)
            if (cursor != null) {
                var count = 0
                while (cursor.moveToNext()) {
                    val id = cursor.getInt(cursor.getColumnIndexOrThrow("_id"))
                    val name = cursor.getString(cursor.getColumnIndexOrThrow("user_name"))
                    Log.d("MainActivity", "用户:${id}_$name")
                    count++
                }
                cursor.close()
                if (count == 0) {
                    Log.d("MainActivity", "数据库是空的!")
                }
            }
        }
    }
}

完整源代码

https://gitee.com/cxyzy1/ContentProviderDemo

上一篇 下一篇

猜你喜欢

热点阅读