10

I want to check how new permission model works so in app's settings I disable Contacts. Then I go to app and try to read Contacts and ... it kinda works:

try {
    Uri result = data.getData();
    int contentIdx;
    cursor = getContentResolver().query(result, null, null, null, null);
    contentIdx = cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
    if(cursor.moveToFirst()) {
        content = cursor.getInt(contentIdx);
    }

    if(content > 0) {
        contentIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
        if(cursor.moveToFirst()) {
            name = cursor.getString(contentIdx);
        }
        contentIdx = cursor.getColumnIndex(BaseColumns._ID);
        if(cursor.moveToFirst()) {
            content = cursor.getLong(contentIdx);
        }
        cursor = managedQuery(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] { Phone.NUMBER }, Data.CONTACT_ID + "=?", new String[] { String.valueOf(content) }, null);
        if(cursor.moveToFirst()) {
            number = cursor.getString(cursor.getColumnIndex(Phone.NUMBER));
        }
    }
} catch (Exception e) {
    //SecurityException
}
  • I'm able to read Contact's Name
  • when I try to read Contact's Number SecurityException is thrown

java.lang.SecurityException: Permission Denial: reading com.android.providers.contacts.HtcContactsProvider2 uri content://com.android.contacts/data/phones from pid=20123, uid=10593 requires android.permission.READ_CONTACTS, or grantUriPermission()

Why is that?

Related stuff: Contact data leakage via pick activities

Machavity
  • 30,841
  • 27
  • 92
  • 100
Marian Paździoch
  • 8,813
  • 10
  • 58
  • 103
  • 1
    Note that you are not using the ContactsContract from google, as you can see, we see that you're accessing com.android.providers.contacts.HtcContractsProvider, maybe HTC has an issue with validating permission. My suggestion would be to check an AOSP device and see if the same thing is true. If its not true, then it means its a permission leak issue inside of HTC. If they are the same, it sounds like an AOSP issue with. – JoxTraex Feb 23 '16 at 10:09
  • It also reproduces on Nexus. – Marian Paździoch Feb 23 '16 at 10:11

1 Answers1

27

Android marshmallow have new permissions system. You need to request permissions at run time, using code such as the following — part of which I have copied in here from http://developer.android.com/training/permissions/requesting.html

@Override public void onClick(View v) {
    switch (v.getId()){
        case R.id.tv_contact:{
            askForContactPermission();
            break;
        }
    }  }

private void getContact(){
    Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
    startActivityForResult(intent, PICK_CONTACT); }

 public void askForContactPermission(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (ContextCompat.checkSelfPermission(getActivity(),Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
                    Manifest.permission.READ_CONTACTS)) {
                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                builder.setTitle("Contacts access needed");
                builder.setPositiveButton(android.R.string.ok, null);
                builder.setMessage("please confirm Contacts access");//TODO put real question
                builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
                    @TargetApi(Build.VERSION_CODES.M)
                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        requestPermissions(
                                new String[]
                                        {Manifest.permission.READ_CONTACTS}
                                , PERMISSION_REQUEST_CONTACT);
                    }
                });
                builder.show();
                // Show an expanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.

            } else {

                // No explanation needed, we can request the permission.

                ActivityCompat.requestPermissions(getActivity(),
                        new String[]{Manifest.permission.READ_CONTACTS},
                        PERMISSION_REQUEST_CONTACT);

                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        }else{
            getContact();
        }
    }
    else{
        getContact();
    } }

@Override public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST_CONTACT: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getContact();
                // permission was granted, yay! Do the
                // contacts-related task you need to do.

            } else {
                ToastMaster.showMessage(getActivity(),"No permission for contacts");
                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    } }
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Maor Hadad
  • 1,850
  • 21
  • 36