炫意html5
最早CSS3和HTML5移动技术网站之一

Android动态权限申请

更新:插件市场已经提供了封装更完善版本:https://ext.dcloud.net.cn/plugin?id=594

从HBuilderX1.9.4及以上版本开始,Android平台默认targetSdkVersion从21(Android5.0)调整为23(Android6.0)。

Android动态权限申请机制

Android6.0(API23)及以后,系统对权限的管理更加严格,放弃了以往manifest中注册所需权限,用户只要安装APP,便获取了所有注册权限的权限管理机制,而是改为除了需manifest中注册,部分危险权限另需在用户使用某项特殊功能时,向用户动态申请的机制。

当用户手机系统为Android6.0及以上,APP的targetSdkVersion>=23时,新的动态权限申请机制将会被触发,其它所有情况(1.系统版本>=6.0,targetSdkVersion<23;2.系统版本<6.0,targetSdkVersion>=23;3.系统版本<6.0,targetSdkVersion<23)都不会触发动态权限申请机制,因此,如果你不想在APP中动态申请权限,可以将targetSdkVersion设置为小于23。如不然,你就需要在使用某些涉及危险权限的功能(如读取通讯录)时通过系统弹窗的形式向用户动态申请该权限。动态申请权限下,如果用户在权限申请弹窗中拒绝了该申请,则用户将不能使用需要该权限的功能,再次申请该权限时依然会弹窗向用户申请;若用户在权限申请弹窗中勾选了“不再提示”并拒绝,那么再次申请该权限的时候将不会弹出系统弹窗向用户申请权限,此时需要APP引导用户打开设置,在设置中给与APP所需权限。
注意:云端打包targetSdkVersion默认值为26

5+APP中动态权限申请机制的实现

5+APP各独立模块中已经集成了功能所需权限的动态申请机制,开发者无需另做处理。但是如果需要使用某些尚未集成的特殊功能,如通过native.js调用原生方法获取手机扫描到的wifi列表,由于android可以通过访问wifi获取位置信息,因此需要在使用原生方法前先动态申请该功能所需的ACCESS_FINE_LOCATION权限。正因为有这样的需求,DCloud在native.js中为Android提供了动态申请权限的功能。

开发者通过调用plus.android.requestPermissions申请权限。参数permissions为所需权限数组;resultCallback为申请结果回调,将会返回已获取的权限、拒绝本次申请的权限、永久拒绝申请的权限3种结果的权限列表,开发者可以读取各权限申请结果并做相应处理;errorCallback为权限参数格式错误时调用,返回错误信息。

代码举例

依然以获取wifi列表为例,使用该功能前需要开发者先申请所需权限ACCESS_FINE_LOCATION:

function requestPermission() {
plus.android.requestPermissions(
["android.permission.ACCESS_FINE_LOCATION"],
function(resultObj){
for (var i = 0; i < resultObj.granted.length; i++) {
var grantedPermission = resultObj.granted[i];
console.log('已获取的权限:'+ grantedPermission);
}
for (var i = 0; i < resultObj.deniedPresent.length; i++) {
var deniedPresentPermission = resultObj.deniedPresent[i];
console.log('拒绝本次申请的权限:'+ deniedPresentPermission );
}
for (var i = 0; i < resultObj.deniedAlways.length; i++) {
var deniedAlwaysPermission = resultObj.deniedAlways[i];
console.log('永久拒绝申请的权限:'+ deniedAlwaysPermission);
}
// 若所需权限被永久拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
if (resultObj.deniedAlways.length > 0) {
var Intent = plus.android.importClass("android.content.Intent");
var Settings = plus.android.importClass("android.provider.Settings");
var Uri = plus.android.importClass("android.net.Uri");
var mainActivity = plus.android.runtimeMainActivity();
var intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
intent.setData(uri);
mainActivity.startActivity(intent);
}
},
function(error){
console.log('申请权限错误:'+ error.code+ " = "+ error.message);
});
}

引导用户打开所需权限的方法分析

当需要引导用户打开特定权限时,最理想的情况是打开一个只有该权限开关的页面让用户开启权限,但是Android会将应用申请的所有权限集中在一个页面,因此从Android系统提供的功能的角度讲,最好是能引导用户进入应用的权限管理页面,在这个页面中让用户根据提示打开相应权限。然而,国内厂商早在Android未提供动态权限申请功能时就对Android应用的权限申请进行了改造和封装,这就使开发者无法通过统一的入口进入应用权限管理页面,而需要通过各个厂商自己的入口进入,如

// 华为
Intent intent = new Intent(packageName);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName comp = new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity");
intent.setComponent(comp);
mContext.startActivity(intent);
// 魅族
Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.putExtra("packageName", packageName);
mContext.startActivity(intent);

这无疑加大了开发难度。而且各厂商更可能随着版本的升级更改权限管理入口,这就加大了开发的不确定性。因此,我们推荐的最理想的引导用户打开权限的入口是应用设置页面,然后用户通过点击“权限管理”自主进入权限管理页面进行相关权限的设置。
5+APP中利用native.js打开应用设置页面的方法见上方代码举例。

附Android危险权限列表

  • SMS(短信)
    android.permission.SEND_SMS
    android.permission.RECEIVE_SMS
    android.permission.READ_SMS
    android.permission.RECEIVE_WAP_PUSH
    android.permission.RECEIVE_MMS

  • STORAGE(存储卡,包括相册等)
    android.permission.READ_EXTERNAL_STORAGE
    android.permission.WRITE_EXTERNAL_STORAGE

  • CONTACTS(联系人)
    android.permission.READ_CONTACTS
    android.permission.WRITE_CONTACTS
    android.permission.GET_ACCOUNTS

  • PHONE(手机)
    android.permission.READ_PHONE_STATE
    android.permission.CALL_PHONE
    android.permission.READ_CALL_LOG
    android.permission.WRITE_CALL_LOG
    android.permission.ADD_VOICEMAIL
    android.permission.USE_SIP
    android.permission.PROCESS_OUTGOING_CALLS

  • CALENDAR(日历)
    android.permission.READ_CALENDAR
    android.permission.WRITE_CALENDAR

  • CAMERA(相机)
    android.permission.CAMERA

  • LOCATION(位置)
    android.permission.ACCESS_FINE_LOCATION
    android.permission.ACCESS_COARSE_LOCATION

  • SENSORS(传感器)
    android.permission.BODY_SENSORS

  • MICROPHONE(麦克风)
    android.permission.RECORD_AUDIO

Android官方权限概述(需翻墙)
Android官方权限列表(需翻墙)

相关问题

【报Bug】新版本hbuilder不支持安卓WIFI的扫描

iOS权限检查见:https://ask.dcloud.net.cn/article/35915

回答

炫意HTML5 » Android动态权限申请

Java基础教程Android基础教程