Android进阶之旅android 开发程序员

Android权限的坑

2017-10-23  本文已影响106人  ArsenicBing

这篇是日记,反省日记。顺便吐槽下有些国产系统的权限管理的漏洞。

近日接到一个小需求---读取手机通讯录并分页传给H5。

直接上代码:

1. 权限部分

if(selfPermissionGranted(android.Manifest.permission.READ_CONTACTS)){

getUserPhoneContacts(start, size);

}else{

//申请权限

if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.M) {

//6.0 以上开启

ActivityCompat.requestPermissions(BannerActivity.this,newString[]{android.Manifest.permission.READ_CONTACTS},1);

}else{  ... }

}

}

2.权限判断

//判断本app是否开启了手机联系人权限

public booleanselfPermissionGranted(String permission) {

// For Android < Android M, self permissions are always granted.

booleanresult =true;

inttargetSdkVersion =0;

if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.M) {

try{

finalPackageInfo info =this.getPackageManager().getPackageInfo(

this.getPackageName(),0);

targetSdkVersion = info.applicationInfo.targetSdkVersion;

}catch(PackageManager.NameNotFoundException e) {

e.printStackTrace();

}

if(targetSdkVersion >= Build.VERSION_CODES.M) {

// targetSdkVersion >= Android M, we can

// use Context#checkSelfPermission

result =this.checkSelfPermission(permission)

== PackageManager.PERMISSION_GRANTED;

}else{

// targetSdkVersion < Android M, we have to use PermissionChecker

result = PermissionChecker.checkSelfPermission(this, permission) == PermissionChecker.PERMISSION_GRANTED;

}

}else{

//6.0以下判断

PackageManager pm = getPackageManager();

result = (PackageManager.PERMISSION_GRANTED== pm.checkPermission("android.permission.READ_CONTACTS", getPackageName()));

}

returnresult;

}

此处不得不吐槽一下,6.0以下的Android机的适配是个问题,测试了包括锤子5.1.1,小米等手机,6.0以下的机器有询问弹出窗口且点击了拒绝之后,其默认的的权限还是允许的状态。尝试了GitHub上面的AndPermission、TedPermission的开源库后,仍是如此,有些不知所以,有经验的望指教(target 是22,项目中不好改动)。

3.读取联系人操作

一开始考虑到是分页读取上传,所以就按照Contacts._ID分段读取,以为这样会很快(实际上也很快😄)。于是直接粘贴部分代码。

先贴上开始的代码:

//--------------获取手机通讯录--------------    

private void getPhoneContacts(int start,int size){            //先清空之前的数据              if(list!=null){                list.clear();            }            

Uri uri = ContactsContract.Contacts.CONTENT_URI;            //获取ContentResolver            ContentResolver contentResolver = this.getContentResolver();            

//根据row查询数据,返回Cursor           

 String limitOffSet="limit  "+start+","+size+"";          

  Cursor cursor = contentResolver.query(uri, null, null, null, ContactsContract.Contacts._ID+" desc "+limitOffSet);            

if (cursor!=null){              

    while (cursor.moveToNext()){               

    PhoneContactsBean bean = new PhoneContactsBean();                

  String contactId = cursor.getString(cursor                        .getColumnIndex(ContactsContract.Contacts._ID));                // 获取联系人的名字                String name = cursor.getString(cursor.getColumnIndex(                        ContactsContract.Contacts.DISPLAY_NAME));               

 bean.setName(name);                

// 使用ContentResolver查找联系人的电话号码                

Cursor phones = mContext.getContentResolver().query(                        ContactsContract.CommonDataKinds.Phone.CONTENT_URI,                        null,                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID                                + " = " + contactId, null, null);                // 遍历查询结果,获取该联系人的多个电话号码                ArrayListphonelist = new ArrayList();

while (phones.moveToNext())

{

int j=0;

// 获取查询结果中电话号码列中数据。

String phoneNumber = phones.getString(phones

.getColumnIndex(ContactsContract

.CommonDataKinds.Phone.NUMBER));

phonelist.add(j,phoneNumber);

}

bean.setPhoneNumList(phonelist);

phones.close();

list.add(bean);

}

cursor.close();

}

}

一开始的代码,但是在测试了几十个数据的时候还不明显,于是自己写个demo给测试机的联系人列表加入了10000条数据,读取速度非常慢。问题出在查询电话号码的查询,循环的次数太多。

改进后:

public voidgetUserPhoneContacts(intstart,intsize) {

if(start ==0) {

//联系人集合

ContentResolver resolver =this.getContentResolver();

//搜索字段

String[] projection =newString[]{

ContactsContract.CommonDataKinds.Phone.CONTACT_ID,

ContactsContract.CommonDataKinds.Phone.NUMBER,

ContactsContract.Contacts.DISPLAY_NAME};

// 获取手机联系人

Cursor contactsCursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,

projection,null,null,null);

if(contactsCursor !=null) {

//key: contactId,value: 该contactId在联系人集合data的index

Map contactIdMap =newHashMap<>();

while(contactsCursor.moveToNext()) {

//获取联系人的ID

intcontactId = contactsCursor.getInt(0);

//获取联系人的姓名

String name = contactsCursor.getString(2);

//获取联系人的号码

String phoneNumber = contactsCursor.getString(1);

//号码处理

String replace = phoneNumber.replace(" ","|").replace("-","").replace("+","");

//如果联系人Map已经包含该contactId

if(contactIdMap.containsKey(contactId)) {

//得到该contactId在data的index

Integer index = contactIdMap.get(contactId);

//重新设置号码数组

PhoneContactsBean bean =list.get(index);

bean.phoneNumList.add(replace);

}else{

PhoneContactsBean bean =newPhoneContactsBean();

//如果联系人Map不包含该contactId

bean.setName(name);

bean.phoneNumList.add(replace);

list.add(bean);

contactIdMap.put(contactId,list.size() -1);

}

}

//如果联系人Map不包含该contactId

contactsCursor.close();

}

}

upLoadData(list, start, size,cbMethod);

}

读取速率上明显不在一个量级上。

这个日记告诫自己,简单的问题也要自己实地的分析下,不能简单的复制粘贴了事。

上一篇 下一篇

猜你喜欢

热点阅读