This is the first day of my participation in the Gwen Challenge in November. Check out the details: the last Gwen Challenge in 2021
This study note is mainly to learn the basic knowledge of ContentProvider, through the operation of adding, deleting, changing and checking contact information, to understand how to provide program data through ContentProvider operation. This study note is based on the basics of content providers and can be accessed directly by clicking on the link to the official documentation.
An overview of the
Content providers help manage access to data stored by themselves and other applications, and provide ways to share data with other applications. They encapsulate data and provide a mechanism for defining data security.
A content provider is a standard interface that connects data in one process to code in another. By configuring content providers, other applications can securely access and modify the data of the current application.
basis
Access the content provider
If you need to access data in the content provider, you can use the Context’s ContentResolver object on the client side to communicate with the provider. The provider object receives the data request from the client, performs the requested action, and returns the result. Some methods of the ContentResolver object call methods of the same name in the provider object. The ContentResolver method provides basic CRUD (create, retrieve, update, and delete) functionality for a persistent storage space.
Android’s address book is one of the built-in providers where users can store address book information. If we need to query the current phone’s contact list, we can call the contentresolver.query () method, which calls the query() method in the ContentProvider. The following code shows how to retrieve the current phone’s contact list:
// Read contact data
private fun queryContactList(a) {
// Request contact information
val cursor = this.contentResolver.query(
ContactsContract.Contacts.CONTENT_URI,
null.null.null.null) cursor? .let {while (it.moveToNext()){
val rawId = it.getString(it.getColumnIndex(ContactsContract.Contacts.NAME_RAW_CONTACT_ID))
// Request contact information according to rawId
val dataCursor = this.contentResolver.query(
ContactsContract.Data.CONTENT_URI,
null."${ContactsContract.Data.RAW_CONTACT_ID}=? ",
arrayOf(rawId.toString()),
null,
)?.apply {
while (this.moveToNext()) {
// Get the type information
val mimeType = this.getString(this.getColumnIndex(ContactsContract.Data.MIMETYPE))
var name = ""
var phone = ""
when(mimeType){
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE -> {
name = this.getString(this.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME))
}
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE -> {
phone = this.getString(this.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
}
}
Log.i(TAG, "queryContactList: contact name is:$name,phone is:$phone") } } dataCursor? .close() } } cursor? .close() }Copy the code
The function of the above code is to retrieve the name and phone number of each contact from the contact database. We first query the rawId of all original contacts through the ContentResolver query() method, and then use these RAwiDs to find specific information.
Query (); query();
The query () parameters | Parameter of the SELECT keyword | note |
---|---|---|
Uri | FROM table_name | The Uri maps to the table named table_name in the provider |
projection | col,col,col… | We need to query an array of column names |
selection | where col = ? | Specifies the condition for the selected row |
selectionAtgs | In place of selection? The value of the | We need to specify the conditional value |
sortOrder | ORDER BY col,col | Specified returnCursor The display order of each line in |
contentUri
The content Uri is used to identify data in the provider. The content Uri contains the symbolic name of the entire provider (that is, the authority part of the Uri) and the name pointing to the table (that is, the PATH part of the Uri).
In the code above, we use ContactsContract. Contacts. The constant CONTENT_URI to say we need to query the path of the table. The ContentResolver object resolves the Uri’s authorization and compares it to a system table of known providers to resolve the provider. The ContentResolver can then assign the query parameters to the correct provider.
The ContentProvider uses the path portion of the content Uri to represent the name of the table to be accessed. Typically, a provider displays a path for each table it exposes.
In the code above, ContactsContract. Contacts. CONTENT_URI full path is:
content://com.android.contacts/contacts
Also, many applications support adding an ID to the end of a Uri without specifying a specific line to query. For example, in the above code, we only want to query for the contact whose rawId is 2, so we could set the Uri to:
val cursor = this.contentResolver.query(
ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI,2),
null.null.null.null
)
Copy the code
We use the ID value when we retrieve many rows and want to update or delete a row.
Insert, update, and delete data
Similar to retrieving data from the provider, we can modify the data through the interaction between the provider client and the provider’s ContentProvider. We can invoke the methods of ContentResolver using arguments passed to the corresponding methods of ContentProvider, and the provider and provider client handle security and interprocess communication automatically.
Insert data
If we need to insert data into the provider, we can do so by calling the contentresolver.insert () method. This method inserts a new line in the provider and returns a content Uri for that line. The following code demonstrates how to insert a new contact into the address book:
*/ Private fun addRawContact(accountName: accountName, accountName, accountName, accountName, accountName, accountName, accountName, accountName, accountName) String, accountType: Var id = -1l var id = -1l val value = ContentValues() var id = -1l val value = ContentValues() value.put(ContactsContract.RawContacts.ACCOUNT_NAME, accountName) value.put(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType) val uri = this.contentResolver.insert( ContactsContract.RawContacts.CONTENT_URI, value ) if (uri ! If (id == -1l) {showInfo(r.string.can_not_create_account)} else {addContact(id)}} private fun addContact(rawId: Long) { val name = mBinding.etContactName.text.toString() val phone = mBinding.etContactPhoneNumber.text.toString() // After we have the account ID, we need to store the contact information in the account. We will not judge whether the contact information is duplicate. Directly inserted into the Data / / insert first name information val nameContentValues = ContentValues () nameContentValues. Put (ContactsContract. Data. RAW_CONTACT_ID, rawId) nameContentValues.put( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE ) nameContentValues.put(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, Name) / / and then inserted into the mobile phone number information val phoneContentValues = ContentValues () phoneContentValues. Put (ContactsContract. Data. RAW_CONTACT_ID, rawId) phoneContentValues.put( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE ) phoneContentValues.put(ContactsContract.CommonDataKinds.Phone.NUMBER, Phone) / / insert this. ContentResolver. Insert (ContactsContract. Data. CONTENT_URI, nameContentValues) this.contentResolver.insert(ContactsContract.Data.CONTENT_URI, phoneContentValues) }Copy the code
The above code demonstrates inserting a new contact into the address book. At first we ContactsContract. RawContacts. CONTENT_URI, pointing to the original contact has added a new original contact records in the table, insert the data, we get the record Uri, after we separated the id information, access to this id, We can set the name and phone number of the contact for this ID.
After doing the above, we can find the information of the contact we just inserted in the address book application.
ContentProviderOperation
The code above, we in the add contact, is to ContactsContract. Data. The CONTENT_URI points to add the two rows of Data in the table, a line is the name of the contact Data, Data line is contact number of hands. We did two inserts.
Operations of this type of bulk access provider, such as inserting a large number of rows or rows in multiple tables through the same method call, or typically performing a set of operations across process boundaries as transactions (atomic operations), can be performed using ContentProviderOperation, modifying the methods in Add Contacts as follows:
// Use ContentProviderOperation for batch operations
val operationList = arrayListOf<ContentProviderOperation>()
// Insert the contact name
operationList.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValue(ContactsContract.Data.RAW_CONTACT_ID,rawId)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
.build()
)
// Insert the contact phone number
operationList.add(
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawId)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
.build()
)
// Perform the insert operation
val resultArray = this.contentResolver.applyBatch(ContactsContract.AUTHORITY,operationList)
Copy the code
You can also insert a contact in the address book by performing the preceding operations.
Update the data
As with inserting data, we can update the corresponding data using the contentresolver.update () method. The only thing to note is that we need to specify conditions when updating the data. The following code demonstrates updating information about a contact using ContentProviderOpration.
// Update contact information
private fun updateContact(a){
val operation = arrayListOf<ContentProviderOperation>()
val name = mBinding.etContactName.text.toString()
val phone = mBinding.etContactPhoneNumber.text.toString()
// Set the name informationoperation.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI) .withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) .withValue(ContactsContract.Data.RAW_CONTACT_ID,mContactEntity!! .rawId) .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,name) .withSelection("${ContactsContract.Data._ID}=? ", arrayOf(mContactEntity!! .nameId.toString())) .build() )// Set the phone numberoperation.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI) .withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) .withValue(ContactsContract.Data.RAW_CONTACT_ID,mContactEntity!! .rawId) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER,phone) .withSelection("${ContactsContract.Data._ID}=? ", arrayOf(mContactEntity!! .phoneId.toString())) .build() )// Perform the insert operation
val resultArray = this.contentResolver.applyBatch(ContactsContract.AUTHORITY,operation)
for(result in resultArray){
Log.i(TAG, "addContact: result is:${result.uri}")}// Exit the page after performing the operation
onBackPressed()
}
Copy the code
The code above sets up to update the contact information based on the current ID. Eventually, a contact’s information is successfully updated to the new data.
Delete the data
Deleting rows is similar to retrieving row data. Specify the selection criteria for the rows to be deleted. The client method returns the number of deleted rows.
// Delete a contact
private fun deleteContact(a){ mContactEntity? .let {val count = this.contentResolver.delete(
ContactsContract.RawContacts.CONTENT_URI,
"${ContactsContract.RawContacts._ID}=?",
arrayOf("${it.rawId}")
)
Log.i(TAG, "deleteContact: count is:$count")
// Exit the page after deletion
onBackPressed()
}
}
Copy the code
In the code above, we specify the rawId want to delete the contact, through this id deleted ContactsContract. RawContacts the data in the table, after return to see the designated contact person no longer exists.
At this point, we have learned how to access and modify the provider’s data in the ContentProvider.
The code in this study note is located at ContentProvider