五ContentProvider权限动态申请 通讯录增删改查

Posted 学习中的owl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了五ContentProvider权限动态申请 通讯录增删改查相关的知识,希望对你有一定的参考价值。

五、ContentProvider相关

ContentProvider内容提供者: 负责数据存取,常用于APP进数据共享,跨进程数据存取等…比如读取相册,读取联系人,都是ContentProvider来实现的

  • **1.**我们想在自己的应用中访问别的应用,或者说一些ContentProvider暴露给我们的一些数据, 比如手机联系人,短信、相册等!我们想对这些数据进行读取或者修改,这就需要用到ContentProvider了!
  • **2.**我们自己的应用,想把自己的一些数据暴露出来,给其他的应用进行读取或操作,我们也可以用到ContentProvider,另外我们可以选择要暴露的数据,就避免了我们隐私数据的的泄露!

1.权限申请

android6.0开始,凡是涉及用户隐私的权限(读写短信,读写联系人,拍摄,录音等等),都需要运行时申请,弹窗提醒用户是否授权。用户不授权则无法继续操作

首先在AndroidManifest.xml中声明读取通信录的权限

<uses-permission android:name="android.permission.READ_CONTACTS"/>

运行时动态申请权限,请求用户授权

class TestContentProviderActivity : AppCompatActivity()

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)

        //判断读取通讯录的允许
        if(ActivityCompat.checkSelfPermission(this , android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED)
            //如果未授权
            ActivityCompat.requestPermissions(
                this ,
                arrayOf(android.Manifest.permission.READ_CONTACTS) ,
                100)
        else
            getContacts() //读取联系人
        
    

    //读取联系人
    private fun getContacts() 
        Toast.makeText(this, "getContacts", Toast.LENGTH_SHORT).show()
    

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) 
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)

        if(requestCode==100 && permissions[0]==android.Manifest.permission.READ_CONTACTS)
            if(grantResults[0] == PackageManager.PERMISSION_GRANTED) //表示授予权限
                getContacts()
            else
                Toast.makeText(this,"读取通讯录的权限被拒绝,程序将无法继续工作",Toast.LENGTH_LONG).show()
            
        
    

2.读取通讯录联系人

表名说明
content://com.android.contacts/data/phones读取联系人的表的名字
字段说明
display_name用户名
Data1手机号
//读取联系人
@SuppressLint("Range")
private fun getContacts() 
    //查询对象
    val resolver = contentResolver
    //格式化一个uri
    val uri = Uri.parse("content://com.android.contacts/data/phones")
    //得到一个游标
    val cursor = resolver.query(uri, null, null, null, null)?:return

    while (cursor.moveToNext()) 
        //获取联系人名字和号码
        val displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))
        val phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
        Log.e("ContentProvider", "姓名:$displayName")
        Log.e("ContentProvider", "号码:$phoneNumber")
        Log.e("ContentProvider", "======================")
    
    cursor.close() //游标关闭!!

3.通信录插入联系人

表名说明
content://com.android.contacts/data/data插入联系人的表的名字
content://com.android.contacts/data/raw_contacts插入联系人的原始表的名字
//插入联系人
private fun insertContact() 
    /*
     * 首先向RawContacts.CONTENT_URI执行一个空值插入,目的是获得系统返回的rawContactId
     * 这时后面插入data表的数据,才能使插入的联系人在通讯录里面可见
     */
    val resolver = contentResolver
    val values = ContentValues()
    val rawContactUri = contentResolver!!.insert(ContactsContract.RawContacts.CONTENT_URI, values)!!
    val rawContactId = ContentUris.parseId(rawContactUri)

    //往data表里写入姓名数据
    values.clear() //先把可能存在的数据清空
    values.put(ContactsContract.Data.RAW_CONTACT_ID , rawContactId)
    values.put(ContactsContract.Data.MIMETYPE , CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) //内容类型
    values.put(CommonDataKinds.StructuredName.GIVEN_NAME , "some_name")
    resolver.insert(ContactsContract.Data.CONTENT_URI , values)

    //往data表里写入电话数据
    values.clear() //先把可能存在的数据清空
    values.put(ContactsContract.Data.RAW_CONTACT_ID , rawContactId)
    values.put(ContactsContract.Data.MIMETYPE , CommonDataKinds.Phone.CONTENT_ITEM_TYPE) //内容类型
    values.put(CommonDataKinds.Phone.NUMBER , "1231231234")
    values.put(CommonDataKinds.Phone.TYPE , CommonDataKinds.Phone.TYPE_MOBILE) //手机号
    resolver.insert(ContactsContract.Data.CONTENT_URI , values)

    //往data表里写入Email的数据
    values.clear() //先把可能存在的数据清空
    values.put(ContactsContract.Data.RAW_CONTACT_ID , rawContactId)
    values.put(ContactsContract.Data.MIMETYPE , CommonDataKinds.Email.CONTENT_ITEM_TYPE) //内容类型
    values.put(CommonDataKinds.Email.DATA , "some_name@xx.com")
    values.put(CommonDataKinds.Email.TYPE , CommonDataKinds.Email.TYPE_HOME) //家庭邮箱
    resolver.insert(ContactsContract.Data.CONTENT_URI , values)

4.更新联系人信息

  • 根据手机号获取联系人在通讯录的contact_id
@SuppressLint("Range")
fun getContactIdByPhone(phone : Long) : String?
    val uri = Uri.parse("content://com.android.contacts/data/phones/filter/$phone")
    val resolver = contentResolver
    val cursor = resolver.query(uri, arrayOf(ContactsContract.Data.CONTACT_ID), null, null, null)?:return null

    if (cursor.moveToNext())
        val contractId = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID))
        return contractId
    

    return null

  • 更新联系人的姓名
//更新联系人
private fun updateContact() 
    val contractId = getContactIdByPhone(234524)
    if(contractId == null)
        Toast.makeText(this , "联系人不存在,无法更新" , Toast.LENGTH_LONG).show()
        return
    

    val values = ContentValues()
    values.put(ContactsContract.Data.MIMETYPE , CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
    values.put(CommonDataKinds.StructuredName.GIVEN_NAME, "new_name")
    contentResolver.update(
        ContactsContract.Data.CONTENT_URI,
        values,
        "$ContactsContract.Data.CONTACT_ID=?",
        arrayOf(contractId)
    )


5.删除联系人

  • 根据姓名删除联系人
val ret = contentResolver.delete(
    ContactsContract.RawContacts.CONTENT_URI,
    CommonDataKinds.Phone.DISPLAY_NAME + "=?",
    arrayOf("some_name")
)
if(ret>0)
    Toast.makeText(this,"删除成功", Toast.LENGTH_SHORT).show()
else
    Toast.makeText(this, "删除失败", Toast.LENGTH_SHORT).show()

  • 根据手机号删除联系人
val contact_id = getContactIdByPhone(1111)

contentResolver.delete(RawContacts.CONTENT_URI,CommonDataKinds.Phone.CONTACT_ID+"=?", arrayOf(contact_id));

6.读取收件箱所有短信

字段说明
address收件人地址,即手机号,如+8613811810000
person人物
date日期,long型,如1256539465022,可以对日期显示格式进行设置
protocol协议0 :SMS_RPOTO短信,1:MMS_PROTO彩信
read是否阅读0:未读,1:已读
type短信类型1: 接收到的短信,2:发出的短信
body短信具体内容

需要动态获取权限

<uses-permission android:name="android.permission.READ_SMS"/>
private fun getMessage() 
    val uri = Uri.parse("content://sms/")
    val resolver = contentResolver
    //查询短信的  发件人地址  日期     短信类型  短信具体内容
    val cursor = resolver.query(uri, arrayOf("address", "address", "type", "body"), null, null, null)?:return
    while (cursor.moveToNext())
        val address = cursor.getString(0)
        val data = cursor.getString(1)
        val type = cursor.getString(2)
        val body = cursor.getString(3)

        Log.e("ContentProvider","收件人 $address")
        Log.e("ContentProvider","类型时间 [$type]:$data")
        Log.e("ContentProvider","短信内容 $body")
        Log.e("ContentProvider","-----------------------------")
    

    cursor.close() //关闭游标!!

短信相关的其它操作uri

content://sms/ 所有短信

content://sms/inbox 收件箱

content://sms/sent 已发送

content://sms/draft 草稿

content://sms/outbox 发件箱

content://sms/failed 发送失败

content://sms/queued 待发送列表

以上是关于五ContentProvider权限动态申请 通讯录增删改查的主要内容,如果未能解决你的问题,请参考以下文章

用ContentProvider获取通讯录联系人

Android 应用开发动态权限管理示例 ( 使用原生代码实现 | 申请权限 | 判定权限申请结果 | 判定 “ 不再询问 “ 情况 )

ContentProvider的介绍和使用

Android 四大组件之ContentProvider 访问通讯录进行增删改查操作

如何使用ContentResolver

ContentProvider 增删改查通讯录