Read Contacts without Permission?
Asked Answered
M

3

11

I want to read Contacts via Contacts Picker like this:

Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
startActivityForResult(contact, CONTACT_PICK_CODE);

If I get the Result, the intent.getData() contains an uri to lookup the Contact, but I need the permission READ_CONTACTS to to read it.

I thought it may be possible to recieve a Contact without this permission, similar to the CALL permission: If I want to make a call directly, I need it, but without it I can send a number to the phone app, and the user must click on the call button.
Is there a similar functionallity for READ_CONTACTS I'm not aware of?

Marylou answered 12/7, 2013 at 9:35 Comment(0)
C
16

You can retrieve Contact info without permissions and is something like you tell in the question.

In resume, you create an intent to pick a contact, this give you a URI (and temporally, also give you permissions to read it), then you use the URI to query to retrieve the data using Contact Provider API.

You can read more about it in Intents guide.

For example (from the guide):

static final int REQUEST_SELECT_PHONE_NUMBER = 1;

public void selectContact() {
    // Start an activity for the user to pick a phone number from contacts
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType(CommonDataKinds.Phone.CONTENT_TYPE);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, REQUEST_SELECT_PHONE_NUMBER);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_SELECT_PHONE_NUMBER && resultCode == RESULT_OK) {
        // Get the URI and query the content provider for the phone number
        Uri contactUri = data.getData();
        String[] projection = new String[]{CommonDataKinds.Phone.NUMBER};
        Cursor cursor = getContentResolver().query(contactUri, projection,
                null, null, null);
        // If the cursor returned is valid, get the phone number
        if (cursor != null && cursor.moveToFirst()) {
            int numberIndex = cursor.getColumnIndex(CommonDataKinds.Phone.NUMBER);
            String number = cursor.getString(numberIndex);
            // Do something with the phone number
            ...
        }
    }
}
Crisper answered 25/8, 2014 at 17:8 Comment(0)
C
1

I hope there isn't such a functionality. The way you compare the "call without permissions" with the "read contacts without permissions" will be i think like the user has to enter the contactdata per hand.

The permissions have to be requested by app to protect the privacy of the user and helps to prevent data-collecting-apps.

If your app needs the contact list I think you can add the permission and the user will understand why you need it. If you don't need the contacts, you should not try the read the contacts.

An app always should only provide functionality that is really needed and nothing more. If a desktop-programm will collect data of what you are doing on computer, what games you are playing, whit whom you are mailing, etc. you will call it a trojan.

So just read the contacts if its really needed and then the user will give you the permissions therefore.

The permission.system of android mostly make sense ;)

Confectioner answered 12/7, 2013 at 9:55 Comment(6)
I agree to some degree. But "to Enter Contakt Data By Hand" is a bad example for "send number to dialer". I can send the actual number, and the user DOESN'T have to enter it itself. If I want to "query contacts in Background" like in an autocomplete EditText, the Permission makes complete sense. The User may not be aware that contacts are accessed. BUT If I show the user HIS CONTACT APP, and he has to pick one, how can he not be aware of that his "contacts" beeing accessed? It's just a convinience for him, instead of Enter the data, to take one from ContactsMarylou
PLUS that most Permission fail at startActivityForResult. in ContactPicker the User can Pick his Contact, and I get a data Intent Back, WITHOUT needing the Permission. Unfortunatly data only contains a lookup uri, which then needs this permission If you want to read it.Marylou
If I understand that right you want the user to pick one contact but therefore you must either read all of his contacts and create a list to chhose from or the user-contact-app has to send the contact data from the selected one to your intent. The second way may be impossible depending on users contact app and the first one needs the permission :)Confectioner
I thought permission system was designed in a way that another activity can grant the permission for a caller which like to take some action which he hasn't a permission for hisself. I don't wanna make a contact app, just let the User actively "send my app a contact". Ie. I can "share" something without the need of Internet Permission. The user may delegate a file to share to his Email-App which takes it as attachment and has an Internet PermissionMarylou
The "original" contact App will send a Contact, well at least a data uri where to find it...Marylou
Thats right but without the permissions you cannot read that content, can you? I think this is an security reason why the data is not sent to read without permissionsConfectioner
S
0

I have found, by experimentation, a few Contacts fields that can be queried successfully without READ_CONTACTS permission.

They are:

  • ContactsContract.Data.LOOKUP_KEY,
  • ContactsContract.Data.DISPLAY_NAME,
  • ContactsContract.Data.DISPLAY_NAME_PRIMARY

However,

  • ContactsContract.CommonDataKinds.Phone.NUMBER

throws an IllegalArgumentException "invalid column: data1". Similar exceptions were thrown by any of the other data columns that I tried.

I have tested this on many APIs, from 8 through 32. It fails in API 8, which requires READ_CONTACTS. It works in API 10 and up. I don't know about API 9.

In API 30+, any queries made must be announced in the AndroidManifest.xml <queries> elements.

This particular data makes sense in Android's strict security sense. This permits a client app to obtain a Uri by the user picking it from the Contacts app, together with an identifying name. The client app can later use this Uri to pull up the contact in the Contact app. No sensitive information is communicated -- the name is after all just a label that the user has applied to the contact.

I would love to know if and where this is documented.

Strobila answered 18/7, 2022 at 23:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.