Android learning eight –Contentprovider

Introduction of ContentProvider

ContentProvider is mainly used to realize data sharing between different programs, allowing one program to access the data of another program, while also protecting the security of the accessed data. ContentProvider is the standard way for Android to realize cross-program data sharing. Before that, we need to learn about Android runtime permissions.

Runtime permissions

Android is introduced in the 6.0 system runtime permission function, in order to just protect the user’s security and privacy, this permission design idea, is that the user approves you apply for the program, will install, do not approve refused to install.

With the introduction of this feature, the user can install the program and not authorize all permissions at once, but authorize individual permissions as needed.

Common Permission Categories

Android divides common permissions into two types, one is common permissions, one is dangerous permissions

Ordinary permission: it is the permission that will not threaten the user’s privacy and security. For this part of the authorization system will automatically apply for us.

Threat permission: Refers to the threat to users’ privacy and security, such as access to users’ contact messages and location functions, which requires users to manually authorize.

Below is a list of some threat permissions up to Android 10

Androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml: androidmanifest.xml

Note that each dangerous permission in the table belongs to a permission group. We use the permission name for the runtime permission processing. In principle, if we approve a permission request, all other permissions in the same group will be automatically granted.

Apply for permission while the program is running

The following example uses CALL_PHONE to learn this permission. This permission is declared when writing the calling function. It is also classified as a dangerous permission because dialing a phone will involve telephone charges.

First we will create a new project called Runtimepermission project and modify the layout of antivity_man_XML by adding a button that triggers the call logic by clicking on it

<? xml version="1.0" encoding="utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
    android:layout_width="match_parent"
    android:layout_height="match_parent"
      android:orientation="vertical">

    <Button
        android:id="@+id/makCall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Make Call"/>
</LinearLayout>
Copy the code

Next, modify the ManActivity code

Of course, to be on the safe side we put the operation inside exception catching

package com.example.runtimepermission

import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val makecall: Button =findViewById(R.id.makCall)
        makecall.setOnClickListener { 
            try {
                Intent.action_call = intent.action_call = intent.action_call = intent.action_call
                // This is a built-in call action
                val  intent=Intent(Intent.ACTION_CALL)
                
                // The implementation protocol in data is TEL
                intent.data= Uri.parse("tel:10086")
                startActivity(intent)
            }catch (e:SecurityException){
                e.printStackTrace()
            }
           
        }
    }
}
Copy the code

Next, declare permissions in androidmanifest.xml

<? xml version="1.0" encoding="utf-8"? > <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.runtimepermission">
// Declare permissions
<uses-permission android:name="android.permission.CALL_PHONE"/>

Copy the code

If this worked well before Android 6.0, but not after, let’s look at the logs

This Permission Denial, as you can see, applies to problems caused by Permission Denial, since after Android6.0 all dangerous permissions must be handled at runtime

package com.example.runtimepermission 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 import java.util.jar.Manifest class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val makecall: Button = the findViewById (R.i d.m akCall) makecall. SetOnClickListener {/ / the first step to determine whether the user has authorization to us the if (ContextCompat. CheckSelfPermission (this, / / the second parameter is a specific permission to name here to use the return value and PackageManager PERMISSION_GRANTED compare equal / / has been authorized, Whereas no android. The Manifest. Permission. CALL_PHONE)! = PackageManager. PERMISSION_GRANTED) {/ / you call this method without authorization authorization, the first parameter to the Activity instance, / / the second String array, put the application permissions name in / / the third parameter, the request code, As long as it is the only value can ActivityCompat. RequestPermissions (this, arrayOf (android. The Manifest. Permission. CALL_COMPANION_APP), 1)} else {call()}}} Regardless of the outcome will be callback onRequestPermissionsResult () method of/packaging/authorization results to grantResults parameters / / we just judge authorized as a result, if agreed to call, Not agreed to the pop-up message 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){ return call() }else{ Toast.makeText(this,"You denied the Permission ", toast.length_short).show()}}}} private fun call(){try {// here constructs a hermit Intetn, ACTION_CALL val Intent =Intent(intent.action_call) // Tel intent.data= Uri.parse("tel:10086") startActivity(intent) }catch (e:SecurityException) { e.printStackTrace() } } }Copy the code

Finally, run the program and click “Make Call” button, which is used for users who are not authorized to Make phone calls. When running it for the first time, a dialog box for permission application will pop up, which we can agree or reject.

ContentResolver Basic usage

For an application that wants to access the ContentResolver shared data, it must use the ContentResolver class, which can be retrieved through the context’s get method

Reading system contacts

Start by building two contacts in the simulator

Create a new project and write a layout file that displays the contact messages read from the system in the ListView

<? The XML version = "1.0" encoding = "utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+id/contactsView" android:layout_width="match_parent" android:layout_height="match_parent"> </ListView> </LinearLayout>Copy the code

Finally modify ManActivty

package com.example.cantactstest import android.content.pm.PackageManager import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.provider.ContactsContract import android.widget.ArrayAdapter import android.widget.ListView import android.widget.Toast import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import java.util.jar.Manifest 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.l ayout. Simple_list_item_1, contactsList) / / to get layout id val ContacetView :ListView=findViewById(R.I.C.ontactsView) contacetView.adapter=adapter // Determine whether the user has agreed to the permission if(ContextCompat.checkSelfPermission(this,android.Manifest.permission.READ_CONTACTS)! = PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(this, ArrayOf (android Manifest. Permission. READ_CONTACTS), 1)} else {readContacts ()}} / / callback, Handle the returned result 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) readContacts() }else ->{ Toast.makeText(this, "You denide thr permission", Toast.length_short).show()}}} private fun readContacts(){// Query contact messages contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null, null)? .apply {while(moveToNext()){// Get the name of the contact val DisplayName = get string (getColumnIndex (ContactsContract.Com monDataKinds. Phone. DISPLAY_NAME)) / / to get contact people appointed number val number=getString(getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)) contactsList.add("$displayName\n$number") } adapter.notifyDataSetChanged() close() } } }Copy the code

The result is as follows

To be continued…