获取手机通讯录
获取手机通讯录需要使用到 ContentProvider 的观察者 ContentResolver 来获取。
` //获取手机通讯录联系人
    ContentResolver resolver = this.getContentResolver();

    // 获取手机联系人
    Cursor phoneCursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PHONES_PROJECTION,
            null, null, null);
    if (phoneCursor != null) {
        while (phoneCursor.moveToNext()) {
            //得到手机号码
            String phoneNumber = phoneCursor.getString(PHONES_NUMBER_INDEX);
            //当手机号码为空的或者为空字段 跳过当前循环
            if (TextUtils.isEmpty(phoneNumber))
                continue;

            //得到联系人名称
            String contactName = phoneCursor.getString(PHONES_DISPLAY_NAME_INDEX);

            //得到联系人ID
            Long contactid = phoneCursor.getLong(PHONES_CONTACT_ID_INDEX);

            //得到联系人头像ID
            Long photoid = phoneCursor.getLong(PHONES_PHOTO_ID_INDEX);

            //得到联系人头像Bitamp
            Bitmap contactPhoto = null;

            //photoid 大于0 表示联系人有头像 如果没有给此人设置头像则给他一个默认的
            if (photoid > 0) {
                Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactid);
                InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(resolver, uri);
                contactPhoto = BitmapFactory.decodeStream(input);
            } else {
                contactPhoto = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
            }
            mContactsName.add(contactName);
            mContactsNumber.add(phoneNumber);
            mContactsPhonto.add(contactPhoto);
        }
        phoneCursor.close();
    }
    for (int i = 0; i < mContactsNumber.size(); i++) {
        Log.i(TAG, "电话号码: " + mContactsNumber.get(i));
    }
    for (int i = 0; i < mContactsName.size(); i++) {
        Log.i(TAG, "姓名: " + mContactsName.get(i));
    }
    Log.i(TAG, "头像的数量: " + mContactsPhonto.size());
    Log.i(TAG, "--------------------------------------------");
}`
// 获取手机 SIM 卡的联系人
`ContentResolver resolver = this.getContentResolver();
    // 获取Sims卡联系人
    Uri uri = Uri.parse("content://icc/adn");
    Cursor phoneCursor = resolver.query(uri, PHONES_PROJECTION, null, null,
            null);

    if (phoneCursor != null) {
        while (phoneCursor.moveToNext()) {

            // 得到手机号码
            String phoneNumber = phoneCursor.getString(PHONES_NUMBER_INDEX);
            // 当手机号码为空的或者为空字段 跳过当前循环
            if (TextUtils.isEmpty(phoneNumber))
                continue;
            // 得到联系人名称
            String contactName = phoneCursor
                    .getString(PHONES_DISPLAY_NAME_INDEX);

            //Sim卡中没有联系人头像

            mContactsName.add(contactName);
            mContactsNumber.add(phoneNumber);
        }

        phoneCursor.close();
    }`
关于 anroid6.0 权限完全解析
在 6.0版本 增强了用户的安全机制。涉及到用户的隐私以及安全的时候需要用户自己手动去授权。
## 检查用户是否授权
#### 这里涉及到的 API,ContextCoompat.checkSelfPermission ,主要用于检测某个权限是否已经被授予,方法返回值
` if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_CONTACTS)
                != PackageManager.PERMISSION_GRANTED) {
            //申请权限  第二个参数是一个 数组 说明可以同时申请多个权限
            ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.READ_CONTACTS}, 1);
        } else {//已授权
            obtionContacts();
        }`
## 申请授权 返回授权结果
`
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == 1) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //权限申请成功
            obtionContacts();
        } else {
            Toast.makeText(MainActivity.this, "获取联系人的权限申请失败", Toast.LENGTH_SHORT).show();
        }
    }
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

`

在Fragment中申请权限,不要使用ActivityCompat.requestPermissions, 直接使用Fragment的requestPermissions方法,否则会回调到Activity的 onRequestPermissionsResult
如果在Fragment中嵌套Fragment,在子Fragment中使用requestPermissions方 法,onRequestPermissionsResult不会回调回来,建议使用 getParentFragment().requestPermissions方法,这个方法会回调到父Fragment中的onRequestPermissionsResult,加入以下代码可以把回调透传到子Fragment
` @Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 
 super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
 List fragments = getChildFragmentManager().getFragments(); 
 if (fragments != null) { 
 for (Fragment fragment : fragments) { 
 if (fragment != null) { 
 fragment.onRequestPermissionsResult(requestCode,permissions,grantResults); 
 } 
 } 
 } 
 }`