判断app读取联系人权限是否已经授权

本文介绍了在Android应用中判断读取联系人权限是否已授权的问题,特别是针对OPPO手机的特殊情况。由于厂商定制系统的影响,常规方法可能无法准确判断,文章提供了一种通过异步读取联系人的方式来间接确定权限状态,并给出了检测是否为OPPO手机以及跳转到设置页面开启权限的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近公司的app有一个需求,需要对应用程序是否授权进行判断,如果没有授权就引导用户去设置页面打开授权本以为很简单,结果app上线后出现很多问题。为了让各位程序猿哥们少走弯路把解决方案奉献给大家。废话不多说:

由于各个手机厂商对自己的room做了严格的封装,导致我们使用Android系统自带读取是否权限的api无法获取到,因此无法判断某个权限是否已经授权,比如现在市场上最火的OPPO手机,每次读取联系人权限是否被打开的时候总是返回true,因此我们无法去判断。这一章我们主要以检测app是否对读取联系人授权为例,其他权限判断也一样。

首先我们来分析下,读取权限的方案有四种:分别是通过packageManager,Activity,ActivityCompat,PermissionCheck这四个类去读取,比如判断联系人权限是否打开:

boolean permission = (PackageManager.PERMISSION_GRANTED ==
        pm.checkPermission("android.permission.READ_CONTACTS", "包名"));

其他的方法网上有很多,在此不多说。

  前面说了,由于各种原因,这个permission是一个不准确的值,我们拿到它很多情况下无法用来判断权限是否打开,尝试了很久之后于是总结一套很有效的方案:就是直接去读取联系人,我们可以开启一个异步任务去读取联系人,这里我用的是AsyncTask:

  protected ArrayList<Contact> doInBackground(Context... voids) {
            ContentResolver resolver = context.getContentResolver();
            // 获取Sims卡联系人
            Uri uri = Uri.parse("content://com.android.contacts/contacts"); //访问raw_contacts            //获得_id属性
            Cursor cursor = null;
            try {
                cursor = resolver.query(uri, new String[]{ContactsContract.Data._ID}, null, null, "sort_key asc");
            } catch (Exception e) {
                e.printStackTrace();
            }

            if (cursor == null) {
                return null; // error
            }

            ArrayList<Contact> result = new ArrayList<>();
            while (cursor.moveToNext()) {
                Contact contact = new Contact();
                StringBuilder buf = new StringBuilder();
                //获得id并且在data中寻找数据
                int id = cursor.getInt(0);
//            buf.append("id="+id);
                uri = Uri.parse("content://com.android.contacts/contacts/" + id + "/data");
                //data1存储各个记录的总数据,mimetype存放记录的类型,如电话、email                Cursor phoneCursor = resolver.query(uri, null, null, null, null);

                if (phoneCursor == null) {
                    return result;
                }

                while (phoneCursor.moveToNext()) {


//                String name = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));//获取联系人name
//                String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); //获取联系人number

                    String data = phoneCursor.getString(phoneCursor.getColumnIndex("data1"));

                    if (phoneCursor.getString(phoneCursor.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/name")) {
                        contact.setName(data);   //如果是名字
//                    buf.append(",name="+data);
                    } else if (phoneCursor.getString(phoneCursor.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/phone_v2")) {  //如果是电话
                        if (TextUtils.isEmpty(contact.getNumber())) {
                            contact.setNumber(data);
                        } else if (TextUtils.isEmpty(contact.getNumber2())) {
                            contact.setNumber2(data);
                        } else {
                            contact.setNumber3(data);
                        }
//                    buf.append(",phone="+data);
                    } else if (phoneCursor.getString(phoneCursor.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/email_v2")) {  //如果是email
                        if (TextUtils.isEmpty(contact.getEmail())) {
                            contact.setEmail(data);
                        } else if (TextUtils.isEmpty(contact.getEmail2())) {
                            contact.setEmail2(data);
                        } else {
                            contact.setEmail3(data);
                        }

//                    buf.append(",email="+data);
                    } else if (phoneCursor.getString(phoneCursor.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/postal-address_v2")) { //如果是地址

                        if (TextUtils.isEmpty(contact.getAddress())) {
                            contact.setAddress(data);
                        } else if (TextUtils.isEmpty(contact.getAddress2())) {
                            contact.setAddress2(data);
                        } else {
                            contact.setAddress3(data);
                        }
//                    buf.append(",address="+data);
                    } else if (phoneCursor.getString(phoneCursor.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/organization")) {  //如果是组织
//                    buf.append(",organization=" + data);
                    }
                }

                phoneCursor.close();
                result.add(contact);
            }
            cursor.close();

            return result;
        }
在doInbackground里面读取完成之后,然后我们再去onPostExcute判断读取的结果,根据结果我们就可以来判断应用的读取联系人权限是否被用户打开,如果打开了就直接去进行对应的操作,如果没有打开就弹出对话框引导用户去设置页面打开权限。OnPostExcute方法如下:

   protected void onPostExecute(ArrayList<Contact> result) {
        loadManager.dismiss();

        if (null == result) {
            // 没有权限
            // 我们前面的逻辑保证了只有OPPO R9会走到这儿
            final Dialog dialog = new Dialog(getActivity(), R.style.dialog);
            dialog.setContentView(R.layout.dialog_oppo_permission_help);
            dialog.setCancelable(false);
            TextView tv_step1 = (TextView) dialog.findViewById(R.id.tv_step1);
            TextView tv_step2 = (TextView) dialog.findViewById(R.id.tv_step2);
            Button btn_go = (Button) dialog.findViewById(R.id.btn_go);
            tv_step1.setText(Html.fromHtml(
                    "<font color=#ffffff>进入应用信息点击</font> <font color=#ee9516>权限管理</font>"));
            tv_step2.setText(Html.fromHtml(
                    "<font color=#ffffff>设置权限状态为&quot</font> <font color=#ee9516>允许</font> <font color=#ffffff>&quot</font>"));
            btn_go.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    dialog.dismiss();
                    Intent intent = SystemUtils.getAppDetailSettingIntent();
                    startActivityForResult(intent, 0);
                }
            });
            dialog.show();
        } else if (result.isEmpty()) {
            // 没有联系人
            Toast.makeText(context, "通讯录里没有联系人,请添加一个联系人后重试", Toast.LENGTH_SHORT).show();
        } else {
            // 读取联系人成功
            Intent selectContact = new Intent();
            selectContact.putExtra(ContactActivity.PARAM_NAME_TAG_FROM, MoreInfoFragment.class.getSimpleName());
            selectContact.putParcelableArrayListExtra(ContactActivity.PARAM_NAME_CONTACT_DATA, result);
            selectContact.setClass(getActivity(), ContactActivity.class);
            startActivityForResult(selectContact, 0);
        }
    }
}
在doInbackground里面读取完成之后,然后我们再去onPostExcute判断读取的结果,根据结果我们就可以来判断应用的读取联系人权限是否被用户打开,如果打开了就直接去进行对应的操作,如果没有打开就弹出对话框引导用户去设置页面打开权限。OnPostExcute方法如下:

   protected void onPostExecute(ArrayList<Contact> result) {
        loadManager.dismiss();

        if (null == result) {
            // 没有权限
            // 我们前面的逻辑保证了只有OPPO R9会走到这儿
            final Dialog dialog = new Dialog(getActivity(), R.style.dialog);
            dialog.setContentView(R.layout.dialog_oppo_permission_help);
            dialog.setCancelable(false);
            TextView tv_step1 = (TextView) dialog.findViewById(R.id.tv_step1);
            TextView tv_step2 = (TextView) dialog.findViewById(R.id.tv_step2);
            Button btn_go = (Button) dialog.findViewById(R.id.btn_go);
            tv_step1.setText(Html.fromHtml(
                    "<font color=#ffffff>进入应用信息点击</font> <font color=#ee9516>权限管理</font>"));
            tv_step2.setText(Html.fromHtml(
                    "<font color=#ffffff>设置权限状态为&quot</font> <font color=#ee9516>允许</font> <font color=#ffffff>&quot</font>"));
            btn_go.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    dialog.dismiss();
                    Intent intent = SystemUtils.getAppDetailSettingIntent();
                    startActivityForResult(intent, 0);
                }
            });
            dialog.show();
        } else if (result.isEmpty()) {
            // 没有联系人
            Toast.makeText(context, "通讯录里没有联系人,请添加一个联系人后重试", Toast.LENGTH_SHORT).show();
        } else {
            // 读取联系人成功
            Intent selectContact = new Intent();
            selectContact.putExtra(ContactActivity.PARAM_NAME_TAG_FROM, MoreInfoFragment.class.getSimpleName());
            selectContact.putParcelableArrayListExtra(ContactActivity.PARAM_NAME_CONTACT_DATA, result);
            selectContact.setClass(getActivity(), ContactActivity.class);
            startActivityForResult(selectContact, 0);
        }
    }
}

另外,由于市场上由于OPPO手机比较多,教给大家一个判断手机是否是OPPO手机的方法如下:

private static boolean isOppoR9() {
    String model = Build.MODEL.toLowerCase();
    return model.contains("oppo") && model.contains("r9");
}

进入到设置页面打开权限的代码如下:

Intent intent = SystemUtils.getAppDetailSettingIntent();
startActivityForResult(intent, 0);


希望能够帮助到大家,谢谢!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值