5, ContentProvider permission dynamic application address book addition, deletion, modification and query

5, ContentProvider related

ContentProvider: content provider is responsible for data access. It is often used for APP data sharing, cross process data access, etc... for example, reading photo albums and contacts are implemented by ContentProvider

  • **1. * * we want to access other applications in our own applications, or some data exposed to us by the ContentProvider, such as mobile phone contacts, SMS, photo albums, etc! If we want to read or modify these data, we need to use the ContentProvider!
  • **2. * * for our own applications, we can also use ContentProvider if we want to expose some of our data and read or operate it for other applications. In addition, we can choose the data to be exposed to avoid the disclosure of our private data!

1. Permission application

Starting from Android 6.0, all permissions involving user privacy (reading and writing SMS, reading and writing contacts, shooting, recording, etc.) need to be applied at runtime, and a pop-up window will remind the user whether to authorize. If the user is not authorized, the operation cannot continue

First, declare the permission to read the address book in AndroidManifest.xml

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

The runtime dynamically applies for permission and requests user authorization

class TestContentProviderActivity : AppCompatActivity(){

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

        //Determine the permission to read the address book
        if(ActivityCompat.checkSelfPermission(this , android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED){
            //If not authorized
            ActivityCompat.requestPermissions(
                this ,
                arrayOf(android.Manifest.permission.READ_CONTACTS) ,
                100)
        }else{
            getContacts() //Read contacts
        }
    }

    //Read contacts
    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){ //Indicates that permission is granted
                getContacts()
            }else{
                Toast.makeText(this,"Permission to read the address book is denied. The program will not continue to work",Toast.LENGTH_LONG).show()
            }
        }
    }
}

2. Read the contact list

Table nameexplain
content://com.android.contacts/data/phonesRead the name of the contact's table
fieldexplain
display_nameuser name
Data1cell-phone number
//Read contacts
@SuppressLint("Range")
private fun getContacts() {
    //Query object
    val resolver = contentResolver
    //Format a uri
    val uri = Uri.parse("content://com.android.contacts/data/phones")
    //Get a cursor
    val cursor = resolver.query(uri, null, null, null, null)?:return

    while (cursor.moveToNext()) {
        //Get contact name and number
        val displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))
        val phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
        Log.e("ContentProvider", "full name:$displayName")
        Log.e("ContentProvider", "number:$phoneNumber")
        Log.e("ContentProvider", "======================")
    }
    cursor.close() //Cursor closed!!
}

3. Insert contact in the address book

Table nameexplain
content://com.android.contacts/data/dataInsert the name of the contact's table
content://com.android.contacts/data/raw_contactsInsert the name of the contact's original table
//Insert contact
private fun insertContact() {
    /*
     * First, send a message to RawContacts.CONTENT_URI performs a null value insertion in order to obtain the rawContactId returned by the system
     * At this time, insert the data in the data table later to make the inserted contact visible in the address book
     */
    val resolver = contentResolver
    val values = ContentValues()
    val rawContactUri = contentResolver!!.insert(ContactsContract.RawContacts.CONTENT_URI, values)!!
    val rawContactId = ContentUris.parseId(rawContactUri)

    //Write name data into the data table
    values.clear() //Clear the possible data first
    values.put(ContactsContract.Data.RAW_CONTACT_ID , rawContactId)
    values.put(ContactsContract.Data.MIMETYPE , CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) //Content type
    values.put(CommonDataKinds.StructuredName.GIVEN_NAME , "some_name")
    resolver.insert(ContactsContract.Data.CONTENT_URI , values)

    //Write phone data to the data table
    values.clear() //Clear the possible data first
    values.put(ContactsContract.Data.RAW_CONTACT_ID , rawContactId)
    values.put(ContactsContract.Data.MIMETYPE , CommonDataKinds.Phone.CONTENT_ITEM_TYPE) //Content type
    values.put(CommonDataKinds.Phone.NUMBER , "1231231234")
    values.put(CommonDataKinds.Phone.TYPE , CommonDataKinds.Phone.TYPE_MOBILE) //cell-phone number
    resolver.insert(ContactsContract.Data.CONTENT_URI , values)

    //Write Email data to the data table
    values.clear() //Clear the possible data first
    values.put(ContactsContract.Data.RAW_CONTACT_ID , rawContactId)
    values.put(ContactsContract.Data.MIMETYPE , CommonDataKinds.Email.CONTENT_ITEM_TYPE) //Content type
    values.put(CommonDataKinds.Email.DATA , "some_name@xx.com")
    values.put(CommonDataKinds.Email.TYPE , CommonDataKinds.Email.TYPE_HOME) //Home mailbox
    resolver.insert(ContactsContract.Data.CONTENT_URI , values)
}

4. Update contact information

  • Get the contact of the contact in the address book according to the mobile phone number_ 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
}
  • Update contact's name
//Update contacts
private fun updateContact() {
    val contractId = getContactIdByPhone(234524)
    if(contractId == null){
        Toast.makeText(this , "The contact does not exist and cannot be updated" , 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. Delete contact

  • Delete contact by name
val ret = contentResolver.delete(
    ContactsContract.RawContacts.CONTENT_URI,
    CommonDataKinds.Phone.DISPLAY_NAME + "=?",
    arrayOf("some_name")
)
if(ret>0){
    Toast.makeText(this,"Delete succeeded", Toast.LENGTH_SHORT).show()
}else{
    Toast.makeText(this, "Deletion failed", Toast.LENGTH_SHORT).show()
}
  • Delete contact according to mobile phone number
val contact_id = getContactIdByPhone(1111)

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

6. Read all messages in inbox

fieldexplain
addressRecipient address, i.e. mobile phone number, e.g. + 861381180000
personcharacter
dateDate, long type, such as 1256539465022. You can set the date display format
protocolProtocol 0: SMS_RPOTO SMS, 1:MMS_PROTO MMS
readRead 0: unread, 1: read
typeSMS type 1: received SMS, 2: sent SMS
bodySpecific content of SMS

Dynamic access required

<uses-permission android:name="android.permission.READ_SMS"/>
private fun getMessage() {
    val uri = Uri.parse("content://sms/")
    val resolver = contentResolver
    //Query the sender address, date, type and content of SMS
    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","addressee $address")
        Log.e("ContentProvider","Type time [$type]:$data")
        Log.e("ContentProvider","SMS content $body")
        Log.e("ContentProvider","-----------------------------")
    }

    cursor.close() //Close cursor!!
}

Other operation URIs related to SMS

content://sms/ All SMS

content://sms/inbox Inbox

content://sms/sent has been sent

content://sms/draft draft

content://sms/outbox Outbox

content://sms/failed fail in send

content://sms/queued List to be sent

Keywords: Java Android RESTful http

Added by Imad on Fri, 19 Nov 2021 14:58:18 +0200