Java – Some phones require READ_CONTACTS permission to read from the contact picker

Some phones require READ_CONTACTS permission to read from the contact picker… here is a solution to the problem.

Some phones require READ_CONTACTS permission to read from the contact picker

I have an HTC ONE M7 (GPE 4.2.2) and HTC EVO 3D (4.0.3) HTC Sense 3.6

HTC ONE does not need:

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

However, on HTC EVO 3D, the following code throws an exception:

 public static String getPhoneNumberFromIntent(Context context, Intent data) throws SecurityException {
    String contactNumber = null;
    final Uri contactUri = data.getData();
    if (contactUri != null) {
        Cursor c = null;
        try {
             Read contact number from contacts provider
            String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER};
            c = context.getContentResolver().query(contactUri, projection, null, null, null);
            if (c != null && c.moveToFirst()) {
                int maxNumberLength = context.getResources().getInteger(R.integer.max_phone_number_cze);
                contactNumber = cutOnlyLastPhoneNumberDigits(c.getString(0), maxNumberLength);
            }
        } finally {
            if (c != null) {
                c.close();
            }
        }
    }
    return contactNumber;
}

java.lang.SecurityException: Permission Denial: reading com.android.providers.contacts.HtcContactsProvider2
uri content://com.android.contacts/data/2158 from pid=14938, uid=10125 requires android.permission.READ_CONTACTS

I read that when the user manually selects a contact, the application is granted the required permissions. However, this does not work on some phones (HTC EVO 3D).

Why is this? Is there a workaround, such as being able to request this permission at runtime?

Solution

HTC ONE does not need: <uses-permission android:name="android.permission.READ_CONTACTS" /> on HTC EVO 3D however, following code throws an exception

If the Uri you get is from a ACTION_PICK or ACTION_GET_CONTENT, whether you have temporary read access to that contact will vary depending on the contact selection app.

I have read that appliaction is granted required permissions when user selects contact by hand. However on some phones this does not work (HTC EVO 3D).

Not all contact selection apps are required to grant you temporary read access to contacts. In fact, it’s not clear to me whether a third-party contact manager will be able to grant you temporary read access to your contacts.

Is there a workaround such is ability to ask for this permission at runtime ?

You cannot change the combination of candidate permissions at run time.

Your choice is:

  1. Always ask READ_CONTACTS in the list. This ensures that you can do what you want, but at the cost of requesting another kind of permission, which potential users may not like.

  2. Handle SecurityException and simply not use the data you are trying query() if that data is not required.

  3. Writing a separate application with READ_CONTACTS can serve as a “plug-in” permission for your application, securely retrieving contact data on behalf of your main application. You can then route users who get SecurityException to install your contacts plug-in. This is difficult to write without introducing security holes, so I encourage you to use one of the other options.

Related Problems and Solutions