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
}
SecurityException
is thrownjava.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
The method shouldShowRequestPermissionRationale() can be used to check whether the user selected the 'never asked again' option and denied the permission.
When an app requests a permission that belongs to a particular permission group (i.e. READ_CONTACTS), Android asks the user about the higher level group instead (CONTACTS). This way when the app later needs the WRITE_CONTACTS permission, Android can automatically grant this itself without prompting the user.
The three permission protection levels in Android are as follows: Normal Permissions. Signature Permissions. Dangerous Permissions.
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button:{
askForContactPermission();
break;
}
}
}
private void getContact(){
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null, null);
while (phones.moveToNext())
{
String name=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
Toast.makeText(getApplicationContext(),name+" "+phoneNumber, Toast.LENGTH_LONG).show();
}
phones.close();
}
public void askForContactPermission(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_CONTACTS)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
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(this,
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 {
Toast.makeText(this, "No Permissions ", Toast.LENGTH_SHORT).show();
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
Android marshmallow have new permissions system. You need to request permissions at run time. http://developer.android.com/training/permissions/requesting.html.
Example:
@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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With