Android ContentProvider基础知识学习笔记

这篇具有很好参考价值的文章主要介绍了Android ContentProvider基础知识学习笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、动态申请权限
<uses-feature
        android:name="android.hardware.telephony"
        android:required="false" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
package com.jpc.contentprovidertest

import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat

/**
 * 运行时权限的核
 * 心就是在程序运行过程中由用户授权我们去执行某些危险操作,程序是不可以擅自做主去执行
 * 这些危险操作的。因此,第一步就是要先判断用户是不是已经给过我们授权了,借助的是
 * ContextCompat.checkSelfPermission()方法。checkSelfPermission()方法接收两
 * 个参数:第一个参数是Context,这个没什么好说的;第二个参数是具体的权限名,比如打电
 * 话的权限名就是Manifest.permission.CALL_PHONE。然后我们使用方法的返回值和
 * PackageManager.PERMISSION_GRANTED做比较,相等就说明用户已经授权,不等就表示用
 * 户没有授权。
 * 如果已经授权的话就简单了,直接执行拨打电话的逻辑操作就可以了,这里我们把拨打电话的
 * 逻辑封装到了call()方法当中。如果没有授权的话,则需要调用
 * ActivityCompat.requestPermissions()方法向用户申请授权。
 * requestPermissions()方法接收3个参数:第一个参数要求是Activity的实例;第二个参数
 * 是一个String数组,我们把要申请的权限名放在数组中即可;第三个参数是请求码,只要是唯
 * 一值就可以了,这里传入了1。
 *
 */
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val makeCall = findViewById<Button>(R.id.btn_make_call)
        makeCall.setOnClickListener {
            if (ContextCompat.checkSelfPermission(this,
                    android.Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this,
                    arrayOf(android.Manifest.permission.CALL_PHONE), 1)
            } else {
                call()
            }
        }

    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when(requestCode) {
            1 -> {
                if(grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    call()
                }else{
                    Toast.makeText(this, "你拒绝了该权限申请", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }
    private fun call(){
        try {
            val intent = Intent(Intent.ACTION_CALL)
            intent.data = Uri.parse("tel:10086")
            startActivity(intent)
        }catch (e: SecurityException){
            e.printStackTrace()
        }
    }
}
2、读取手机联系人
<uses-permission android:name="android.permission.READ_CONTACTS"/>
package com.jpc.contentprovidertest

import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.ContactsContract
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.ListView
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat

class MainActivity : AppCompatActivity() {
    private val contactsList = ArrayList<String>()
    private lateinit var adapter: ArrayAdapter<String>
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, contactsList)
        val listView = findViewById<ListView>(R.id.contacts_view)
        listView.adapter = adapter
        if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_CONTACTS)
            != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.READ_CONTACTS), 1)
        }else{
            readContacts()
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when(requestCode) {
            1 -> {
                if(grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    call()
                }else{
                    Toast.makeText(this, "你拒绝了该权限申请", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }

    private fun readContacts() {
        // 查询联系人数据
        // ContactsContract.CommonDataKinds.Phone类已经帮我们做好了封装,提供了一个
        //CONTENT_URI常量,而这个常量就是使用Uri.parse()方法解析出来的结果
        contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null,null)
            ?.apply {
                while (moveToNext()){
                    // 获取联系人姓名
                    val name = getString(getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))
                    val phone = getString(getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER))
                    contactsList.add("$name\n$phone")
                }
                // 通知并刷新ListView
                adapter.notifyDataSetChanged()
                close() // 关闭Cursor对象
            }
    }
}
3、创建自己的ContentProvider
class MyProvider : ContentProvider() {
 override fun onCreate(): Boolean {
 return false
 }
 override fun query(uri: Uri, projection: Array<String>?, selection: String?,
 selectionArgs: Array<String>?, sortOrder: String?): Cursor? {
 return null
 }
 override fun insert(uri: Uri, values: ContentValues?): Uri? {
 return null
 }
 override fun update(uri: Uri, values: ContentValues?, selection: String?,
 selectionArgs: Array<String>?): Int {
 return 0
 }
 override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
 return 0
 }
 override fun getType(uri: Uri): String? {
 return null
 }
}

(1) onCreate()。初始化ContentProvider的时候调用。通常会在这里完成对数据库的创建和升级等操作,返回true表示ContentProvider初始化成功,返回false则表示失败。
(2) query()。从ContentProvider中查询数据。uri参数用于确定查询哪张表,projection参数用于确定查询哪些列,selection和selectionArgs参数用于约束查询哪些行,sortOrder参数用于对结果进行排序,查询的结果存放在Cursor对象中返回。
(3) insert()。向ContentProvider中添加一条数据。uri参数用于确定要添加到的表,待添加的数据保存在values参数中。添加完成后,返回一个用于表示这条新记录的URI。
(4) update()。更新ContentProvider中已有的数据。uri参数用于确定更新哪一张表中的数据,新数据保存在values参数中,selection和selectionArgs参数用于约束更新哪些行,受影响的行数将作为返回值返回。
(5) delete()。从ContentProvider中删除数据。uri参数用于确定删除哪一张表中的数据,selection和selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回。
(6) getType()。根据传入的内容URI返回相应的MIME类型。

一个标准的内容URI写法是:

content://com.example.app.provider/table1

这就表示调用方期望访问的是com.example.app这个应用的table1表中的数据。
除此之外,我们还可以在这个内容URI的后面加上一个id,例如:

content://com.example.app.provider/table1/1

这就表示调用方期望访问的是com.example.app这个应用的table1表中id为1的数据。
内容URI的格式主要就只有以上两种,以路径结尾表示期望访问该表中所有的数据,以id结尾表示期望访问该表中拥有相应id的数据。我们可以使用通配符分别匹配这两种格式的内容URI,规则如下。

  • *表示匹配任意长度的任意字符。
  • #表示匹配任意长度的数字。

所以,一个能够匹配任意表的内容URI格式就可以写成:

content://com.example.app.provider/*

一个能够匹配table1表中任意一行数据的内容URI格式就可以写成:

content://com.example.app.provider/table1/#

再借助UriMatcher这个类就可以轻松地实现匹配内容URI的功能。UriMatcher中提供了一个addURI()方法,这个方法接收3个参数,可以分别把authority、path和一个自定义代码传进去。这样,当调用UriMatcher的match()方法时,就可以将一个Uri对象传入。文章来源地址https://www.toymoban.com/news/detail-845989.html

class MyProvider : ContentProvider() {
 private val table1Dir = 0
 private val table1Item = 1
 private val table2Dir = 2
 private val table2Item = 3
 private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH)
 init {
 uriMatcher.addURI("com.example.app.provider", "table1", table1Dir)
 uriMatcher.addURI("com.example.app.provider ", "table1/#", table1Item)
 uriMatcher.addURI("com.example.app.provider ", "table2", table2Dir)
 uriMatcher.addURI("com.example.app.provider ", "table2/#", table2Item)
 }
 ...
 override fun query(uri: Uri, projection: Array<String>?, selection: String?,
 selectionArgs: Array<String>?, sortOrder: String?): Cursor? {
 when (uriMatcher.match(uri)) {
 table1Dir -> {
 // 查询table1表中的所有数据
 }
 table1Item -> {
 // 查询table1表中的单条数据
 }
 table2Dir -> {
 // 查询table2表中的所有数据
 }
 table2Item -> {
 // 查询table2表中的单条数据
 }
 }
 ...
 }
 ...
}
class MyProvider : ContentProvider() {
 ...
 override fun getType(uri: Uri) = when (uriMatcher.match(uri)) {
 table1Dir -> "vnd.android.cursor.dir/vnd.com.example.app.provider.table1"
 table1Item -> "vnd.android.cursor.item/vnd.com.example.app.provider.table1"
 table2Dir -> "vnd.android.cursor.dir/vnd.com.example.app.provider.table2"
 table2Item -> "vnd.android.cursor.item/vnd.com.example.app.provider.table2"
 else -> null
 }
}
4、实战
class DatabaseProvider : ContentProvider() {
 private val bookDir = 0
 private val bookItem = 1
 private val categoryDir = 2
 private val categoryItem = 3
 private val authority = "com.example.databasetest.provider"
 private var dbHelper: MyDatabaseHelper? = null
 private val uriMatcher by lazy {
 val matcher = UriMatcher(UriMatcher.NO_MATCH)
 matcher.addURI(authority, "book", bookDir)
 matcher.addURI(authority, "book/#", bookItem)
 matcher.addURI(authority, "category", categoryDir)
 matcher.addURI(authority, "category/#", categoryItem)
 matcher
 }
 override fun onCreate() = context?.let {
 dbHelper = MyDatabaseHelper(it, "BookStore.db", 2)
 true
 } ?: false
www.blogss.cn
 override fun query(uri: Uri, projection: Array<String>?, selection: String?,
 selectionArgs: Array<String>?, sortOrder: String?) = dbHelper?.let {
 // 查询数据
 val db = it.readableDatabase
 val cursor = when (uriMatcher.match(uri)) {
 bookDir -> db.query("Book", projection, selection, selectionArgs,
 null, null, sortOrder)
 bookItem -> {
 val bookId = uri.pathSegments[1]
 db.query("Book", projection, "id = ?", arrayOf(bookId), null, null,
 sortOrder)
 }
 categoryDir -> db.query("Category", projection, selection, selectionArgs,
 null, null, sortOrder)
 categoryItem -> {
 val categoryId = uri.pathSegments[1]
 db.query("Category", projection, "id = ?", arrayOf(categoryId),
 null, null, sortOrder)
 }
 else -> null
 }
 cursor
 }
 override fun insert(uri: Uri, values: ContentValues?) = dbHelper?.let {
 // 添加数据
 val db = it.writableDatabase
 val uriReturn = when (uriMatcher.match(uri)) {
 bookDir, bookItem -> {
 val newBookId = db.insert("Book", null, values)
 Uri.parse("content://$authority/book/$newBookId")
 }
 categoryDir, categoryItem -> {
 val newCategoryId = db.insert("Category", null, values)
 Uri.parse("content://$authority/category/$newCategoryId")
 }
 else -> null
 }
 uriReturn
 }
 override fun update(uri: Uri, values: ContentValues?, selection: String?,
 selectionArgs: Array<String>?) = dbHelper?.let {
 // 更新数据
 val db = it.writableDatabase
 val updatedRows = when (uriMatcher.match(uri)) {
 bookDir -> db.update("Book", values, selection, selectionArgs)
 bookItem -> {
 val bookId = uri.pathSegments[1]
 db.update("Book", values, "id = ?", arrayOf(bookId))
 }
 categoryDir -> db.update("Category", values, selection, selectionArgs)
 categoryItem -> {
 val categoryId = uri.pathSegments[1]
 db.update("Category", values, "id = ?", arrayOf(categoryId))
 }
 else -> 0
 }
 updatedRows
 } ?: 0
 override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?)
 = dbHelper?.let {
 // 删除数据
www.blogss.cn
 val db = it.writableDatabase
 val deletedRows = when (uriMatcher.match(uri)) {
 bookDir -> db.delete("Book", selection, selectionArgs)
 bookItem -> {
 val bookId = uri.pathSegments[1]
 db.delete("Book", "id = ?", arrayOf(bookId))
 }
 categoryDir -> db.delete("Category", selection, selectionArgs)
 categoryItem -> {
 val categoryId = uri.pathSegments[1]
 db.delete("Category", "id = ?", arrayOf(categoryId))
 }
 else -> 0
 }
 deletedRows
 } ?: 0
 override fun getType(uri: Uri) = when (uriMatcher.match(uri)) {
 bookDir -> "vnd.android.cursor.dir/vnd.com.example.databasetest.provider.book"
 bookItem -> "vnd.android.cursor.item/vnd.com.example.databasetest.provider.book"
 categoryDir -> "vnd.android.cursor.dir/vnd.com.example.databasetest.
 provider.category"
 categoryItem -> "vnd.android.cursor.item/vnd.com.example.databasetest.
 provider.category"
 else -> null
 }
}

到了这里,关于Android ContentProvider基础知识学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Zookeeper学习笔记(1)—— 基础知识

    Zookeeper 是一个开源的分布式的, 为分布式框架提供协调服务 的 Apache 项目 Zookeeper从设计模式角度来理解:是一个基于 观察者模式 设计的 分布式服务管理框架 ,它 负责存储和管理大家都关心的数据 ,然后 接受观察者的注 册 ,一旦这些数据的状态发生变化,Zookeeper就 将负

    2024年02月05日
    浏览(27)
  • (学习笔记-IP)IP基础知识

    IP在TCP/IP参考模型中处于第三层,也就是 网络层。 网络层的主要作用是: 实现主机与主机之间的通信,也叫点对点的通信。  网络层与数据链路层的关系: MAC的作用是实现 直连 的两个设备之间通信,而IP负责 没有直连 的两个网络之间进行通信传输  因此 计算机网络中需要

    2024年02月16日
    浏览(43)
  • golang学习笔记(defer基础知识)

    defer语句用于golang程序中延迟函数的调用, 每次defer都会把一个函数压入栈中, 函数返回前再把延迟的函数取出并执行。 为了方便描述, 我们把创建defer的函数称为主函数, defer语句后面的函数称为延迟函数。延迟函数可能有输入参数, 这些参数可能来源于定义defer的函数,

    2024年04月25日
    浏览(35)
  • 数电模电基础知识学习笔记汇总

    文章目录: 数电和模电的关系 一:模电学习笔记 二:数电学习笔记 三:福利 1.NI Multisim14.0电路仿真软件的下载安装 2.进制转换 3.电路常用公式 4.好的参考笔记  4.1 笔记  3.1.1 模电 3.1.1 数电 4.2 网站 5.八股文 来源:一周搞(不)定数电模电全集,电子基础知识 11小时 模电基

    2024年02月15日
    浏览(44)
  • Windows Api 学习笔记 1——基础知识(上)

    推荐阅读《深入浅出:Windows Api 程序设计》。《深入浅出:Windows Api 程序设计》是 王端明 先生的著作,是2022年人民邮电出版社出版的图书。 Microsoft Windows是美国微软公司开发的一套操作系统。自1985年问世以来,随着软硬件的升级,Microsoft Windows不断迭代更新,变得更加人性

    2024年02月08日
    浏览(51)
  • CAN总线学习笔记 | CAN基础知识介绍

    1.1 CAN协议简介 CAN 是控制器局域网络 (Controller Area Network) 的简称,它是由研发和生产汽车电子产品著称的德国 BOSCH 公司开发的,并最终成为国际标准(ISO11519以及ISO11898),是国际上应用最广泛的现场总线之一。差异点如下: 1.2 CAN物理层 CAN 通讯不是以时钟信号来进行同步的,它

    2023年04月09日
    浏览(34)
  • UE4 地形编辑基础知识 学习笔记

    之前自己写过这样的功能,今天看到一个UE现成的 点击地形,选择样条 按住CTRL键+点击屏幕中某一个点会在场景内生成一个这样的图标 再点两次,会生成B样条的绿线条 点击+号再选择一个模型,会生成对应的链条状的mesh 拉高最远处的一个图标抬高 如果想地形贴合该mesh,则

    2024年02月11日
    浏览(43)
  • web渗透安全学习笔记:2、HTML基础知识

    目录 前言 HTML的标题 段落链接与插入图片 HTML元素 HTML属性 HTML头部 HTML与CSS HTML与JavaScript 表格与列表 HTML区块 布局 HTML表单 HTML与数据库 音频与视频 HTML事件 运行效果:   ———————————————————————————————————————————  ——

    2024年01月21日
    浏览(42)
  • 嵌入式学习笔记——STM32硬件基础知识

    上一篇中我们重点是讲了一下怎么搭建开发环境以及怎么下载烧录的过程,这都是解决的电脑端的开发环境问题,还没有到实际的开发板上,我们的单片机是都是焊接在开发板上的,PCB上有着它所需的工作电路。并不是直接给供电电压就可以让其工作的,本文主要是简介一下

    2024年01月22日
    浏览(50)
  • PyTorch学习笔记(二):PyTorch简介与基础知识

      👨‍💻 作者简介: 大数据专业硕士在读,CSDN人工智能领域博客专家,阿里云专家博主,专注大数据与人工智能知识分享, 公众号: GoAI的学习小屋,免费分享书籍、简历、导图等资料,更有交流群分享AI和大数据,加群方式公众号回复“加群”或➡️点击链接。 🎉 专栏

    2023年04月09日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包