I am getting this error when I am trying to read contacts from phone and I included READ_CONTACTS
permission in Manifest file. And the strange thing is that it was working fine in Eclipse but when I converted my project to Gradle and run it in Android Studio I'm getting this error.
logcat says:
Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord{302f069 29282:com.GP/u0a322} (pid=29282, uid=10322) requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS
here is the Manifest code:
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<!-- Read Contacts from phone -->
<uses-permission android:name="android.permission.read_contacts" />
<uses-permission android:name="android.permission.read_phone_state" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
Due to the Marshmallow update Requesting Permissions at Run Time the read contact permission not work. The sample code is
import android.Manifest;
import android.content.ContentResolver;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Build;
import android.provider.ContactsContract;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
// The ListView
private ListView lstNames;
// Request code for READ_CONTACTS. It can be any number > 0.
private static final int PERMISSIONS_REQUEST_READ_CONTACTS = 100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Find the list view
this.lstNames = (ListView) findViewById(R.id.lstNames);
// Read and show the contacts
showContacts();
}
/**
* Show the contacts in the ListView.
*/
private void showContacts() {
// Check the SDK version and whether the permission is already granted or not.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS);
//After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method
} else {
// Android version is lesser than 6.0 or the permission is already granted.
List<String> contacts = getContactNames();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, contacts);
lstNames.setAdapter(adapter);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission is granted
showContacts();
} else {
Toast.makeText(this, "Until you grant the permission, we canot display the names", Toast.LENGTH_SHORT).show();
}
}
}
/**
* Read the name of all the contacts.
*
* @return a list of names.
*/
private List<String> getContactNames() {
List<String> contacts = new ArrayList<>();
// Get the ContentResolver
ContentResolver cr = getContentResolver();
// Get the Cursor of all the contacts
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
// Move the cursor to first. Also check whether the cursor is empty or not.
if (cursor.moveToFirst()) {
// Iterate through the cursor
do {
// Get the contacts name
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
contacts.add(name);
} while (cursor.moveToNext());
}
// Close the curosor
cursor.close();
return contacts;
}
}
The sample screenshots :
I got the following source code from here
My issue was that I was using a Marshmallow emulator and that has made some changes as to how we request permissions from user. Hence it kept asking for the permissions even after adding them. http://developer.android.com/training/permissions/requesting.html
The new run-time permission scheme is used only if the app's targetSdkVersion (specified in the manifest) is 23 or higher. So, one way to avoid the issue is to make the targetSdkVersion lower than 23. See the description here:
https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous
Simply add this to your AndroidManifest.xml inside <manifest>
:
<uses-permission android:name="android.permission.READ_CONTACTS"/>