SecurityException Permission Denial when accessing contacts

3

I want to show contacts in the calendar but the application closes instantly. I do not know where the error is:

public class Main extends ListActivity {

    TextView txt;
    ListView list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
         txt = (TextView)findViewById(R.id.contactName);
        list = (ListView) findViewById(android.R.id.list);
        showContacts();
}

protected void showContacts(){

        String[] projection = new String[]{
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                ContactsContract.CommonDataKinds.Phone.NUMBER,
                ContactsContract.CommonDataKinds.Phone._ID;}

        int[] to = new int[]{R.id.contactID,R.id.contactName};
        txt.setText(ContactsContract.PhoneLookup.CONTENT_FILTER_URI.toString());
        //Uri contacts = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        Uri contacts = ContactsContract.Contacts.CONTENT_URI;
        //Uri contacts = Uri.parse("content://contacts/people");
        Cursor c = getContentResolver().query(contacts,projection,null,null,null);
        ListAdapter sca = new SimpleCursorAdapter(Main.this,android.R.layout.activity_list_item,c,projection,to); 
list.setAdapter(sca); 

Error:

  

FATAL EXCEPTION: main Process: es.exitae.listadocontactos7, PID: 4184   java.lang.RuntimeException: Unable to start activity   ComponentInfo {es.exitae.listadocontactos7 / en.exitae.listadocontactos7.Main}:   java.lang.SecurityException: Permission Denial: opening provider   com.android.providers.contacts.ContactsProvider2 from   ProcessRecord {98c9152 4184: en.exitae.listadocontactos7 / u0a73}   (pid = 4184, uid = 10073) requires android.permission.READ_CONTACTS or   android.permission.WRITE_CONTACTS at   android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2665)

The error continues, I do not understand much but from what little I see is that you are telling me to add permissions in the android manifest and I have already done that

This is my android manifes:

<uses-permission android:name="android.permission.READ_CONTACTS" ></uses-permission>
<uses-permission android:name="android.permission.WRITE_CONTACTS" ></uses-permission>
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".Main">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

    </activity>

</application>
    
asked by JoseBanyeres 07.01.2017 в 09:05
source

2 answers

2
  

Starting with Android 6.0 (API level 23), users grant permissions to apps while they are running, not when they install the app. This approach simplifies the process of installing the app, since the user does not need to grant permissions when installing or updating the app. It also gives the user more control over the functionality of the app; for example, a user could choose to provide a camera app with access to it, but not the location of the device. The user can revoke the permissions at any time from the app's configuration screen.

If you use any dangerous permission you must ask for authorization in time of execution to access its functionality, in fact the Android Studio will mark you as an error if you access these permissions without doing a check before.

List of dangerous permits:

READ_CALENDAR
WRITE_CALENDAR
CAMERA
READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
RECORD_AUDIO
READ_PHONE_STATE
CALL_PHONE
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
BODY_SENSORS
SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE

link

My recommendation is to use a library that facilitates things by having to check if the user accepted, rejected, gave not to see again ...

Here are some:

link

link

    
answered by 07.01.2017 в 20:53
1

As you have indicated to access the contacts, it is necessary to obtain special permits. This is from Android M onwards, as indicated here How to request permissions at runtime

If you do not want to use external libraries, you can do it by code as follows.

First add the permission in AndroidManifest.xml

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

Then in a function within your code you add

protected void showContacts(){
    //Si es mayor que android 6 (Marshmallow)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if ((ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED)) {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_CONTACTS}, 1);
            } 
            else {

                String[] projection = new String[]{
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                ContactsContract.CommonDataKinds.Phone.NUMBER,
                ContactsContract.CommonDataKinds.Phone._ID;}

        int[] to = new int[]{R.id.contactID,R.id.contactName};
        txt.setText(ContactsContract.PhoneLookup.CONTENT_FILTER_URI.toString());
        //Uri contacts = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        Uri contacts = ContactsContract.Contacts.CONTENT_URI;
        //Uri contacts = Uri.parse("content://contacts/people");
        Cursor c = getContentResolver().query(contacts,projection,null,null,null);
        ListAdapter sca = new SimpleCursorAdapter(Main.this,android.R.layout.activity_list_item,c,projection,to); 
            list.setAdapter(sca);

            }
        }else{
            //Si es menor que android 6

                String[] projection = new String[]{
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                ContactsContract.CommonDataKinds.Phone.NUMBER,
                ContactsContract.CommonDataKinds.Phone._ID;}

        int[] to = new int[]{R.id.contactID,R.id.contactName};
        txt.setText(ContactsContract.PhoneLookup.CONTENT_FILTER_URI.toString());
        //Uri contacts = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        Uri contacts = ContactsContract.Contacts.CONTENT_URI;
        //Uri contacts = Uri.parse("content://contacts/people");
        Cursor c = getContentResolver().query(contacts,projection,null,null,null);
        ListAdapter sca = new SimpleCursorAdapter(Main.this,android.R.layout.activity_list_item,c,projection,to); 
list.setAdapter(sca);
        }

}

Finally the method onRequestPermissionsResult() is added which is responsible for reading the response of the user at the time that your app requests the required permission

@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
        if (requestCode == 1) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                Toast.makeText(context, "Permiso concedido", Toast.LENGTH_SHORT).show();
            } else {

                Toast.makeText(context, "Es necesario admitir este permiso para leer los contactos", Toast.LENGTH_LONG).show();
            }

        }
    }
    
answered by 11.04.2018 в 20:04