Android 6.0 上的读取联系人权限被拒绝

Read Contacts permission is denied on Android 6.0

我想从 android 获得读取联系人权限。我在清单文件中指定了权限。

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

它在设备 4.4.2 上运行,但在 6.0 上崩溃,出现异常:

 FATAL EXCEPTION: main
                                                                        Process: com.example.siddhi.meavita, PID: 17612
                                                                        java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.siddhi.meavita/com.example.siddhi.meavita.ContactList}: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord{44abcb5 17612:com.example.siddhi.meavita/u0a158} (pid=17612, uid=10158) requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS

所以我环顾四周寻找解决方案,我开始知道 android 6.0 以后它有一个权限模型来请求权限。

所以我读了这个link:
https://developer.android.com/training/permissions/requesting.html

并遵循此处建议的代码:

Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord in Android Studio

而我是这样写代码的:

public class ContactList extends ListActivity {


    private ArrayList<contact> contact_list = null;
    private contactAdapter mContactAdapter = null;

    private ArrayList<contact> items;
    boolean[] isChecked;
    Cursor mCursor;
    ListView lv;
    public int RQS_PICK_CONTACT = 1;
    private static final int PERMISSIONS_REQUEST_READ_CONTACTS = 100;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_contacts_list);

        int permissionCheck = ContextCompat.checkSelfPermission(ContactList.this,
                Manifest.permission.READ_CONTACTS);

        contact_list = new ArrayList<contact>();

        lv = getListView();

        getContacts();

    }

    @SuppressWarnings("unused")
    private void getContacts() {


            String[] projection = new String[] {
                    ContactsContract.Contacts.DISPLAY_NAME,
                    ContactsContract.Contacts.HAS_PHONE_NUMBER,
                    ContactsContract.Contacts._ID };


            mCursor = managedQuery(ContactsContract.Contacts.CONTENT_URI, null, null, null,null);

            while (mCursor.moveToNext()) {
                contact contact = new contact();

                String contactId = mCursor.getString(mCursor.getColumnIndex(ContactsContract.Contacts._ID));
                contact.setContactName(mCursor.getString(mCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
                contact_list.add(contact);
            }
            isChecked = new boolean[mCursor.getCount()];

            for (int i = 0; i < isChecked.length; i++) {
                isChecked[i] = false;
            }

           showContacts();

    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == RQS_PICK_CONTACT) {
            if (resultCode == RESULT_OK) {

                getContacts();

            }
        }
    }

    public class contactAdapter extends ArrayAdapter<contact> {

        public contactAdapter(Context context, int textViewResourceId, ArrayList<contact> items1) {
            super(context, textViewResourceId, items1);
            items = items1;
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            ViewHolder mViewHolder;

            mViewHolder = new ViewHolder();
            LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = vi.inflate(R.layout.contact_list_item, parent, false);
            mViewHolder.cb = (CheckBox) convertView.findViewById(R.id.checkBox);
            mViewHolder.name = (TextView) convertView.findViewById(R.id.name);

            convertView.setTag(mViewHolder);

            if (isChecked[position] == true)
                mViewHolder.cb.setChecked(true);
            else
                mViewHolder.cb.setChecked(false);
            mViewHolder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean ischecked) {
                    if (buttonView.isChecked())
                        isChecked[position] = true;
                    else
                        isChecked[position] = false;
                }
            });

            contact contacts = items.get(position);
            if (contacts != null) {
                if (mViewHolder.cb != null) {
                    mViewHolder.name.setText(contacts.getContactName());
                }
            }

            return convertView;
        }
    }

    public class ViewHolder {
        CheckBox cb;
        TextView name;
    }

    @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();
                }
            }
        }


    private void showContacts()
    {
        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 {

                this.mContactAdapter = new contactAdapter(this, R.layout.contact_list_item, contact_list);
                lv.setAdapter(this.mContactAdapter);
                mCursor.close();
            }

        }

}

还是报异常。这里出了什么问题?谢谢..

我不是 100% 熟悉获取联系人,但据我所知,您的 getContacts() 方法总是在创建片段时被调用。因此,让我们假设用户从未授予权限。您仍在尝试设置联系人列表。如果权限还没有被授予,甚至一开始就不必费心设置列表。所以像:

//onCreate
lv = getListView();

if(ContextCompat.checkSelfPermission(this,
    Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
         getContacts();
 }

此外,您可能想要更改您的逻辑以适应这一点。因此,如果已请求,请删除 showContacts() 中的权限检查,并将其移至 onCreate 中。 getContacts 只有在您获得许可的情况下才应调用。

Android 6.0 (API 23) 需要在清单中使用此权限,就像您的一样。

将此放入您的清单中。

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