鸿蒙开发权限指南:从小白到大神的进阶之路

鸿蒙开发权限指南:从小白到大神的进阶之路

注:适用版本(HarmonyOS NEXT/5.0/API12+)

一、鸿蒙开发权限初相识

家人们,在鸿蒙开发里,应用权限这部分可太重要啦!它就像一道关卡,管着应用能不能访问系统资源和各种能力。为啥这么讲呢?举个简单例子,就说地图应用吧。当你打开地图,想看看自己在哪,规划去目的地的路线,地图应用就得获取你的位置信息。这时候,应用权限就派上用场啦。要是没拿到获取位置信息的权限,地图应用根本不知道你在哪,那肯定没法给你提供精准的导航服务。这不但影响咱用户体验,应用的一些核心功能说不定都用不了。还有啊,像拍照应用得调用摄像头权限,录音应用得要麦克风权限,这些都是应用权限在实际使用中的体现。所以说,弄懂并掌握好应用权限,可是开发出功能齐全、用户体验超棒的鸿蒙应用的基础哦!

二、权限分类大揭秘

(一)敏感权限与普通权限

在鸿蒙开发里,权限主要分为敏感权限和普通权限 ,这二者的区别还是很明显的。敏感权限,一听这名字就知道不简单,它和用户隐私密切相关,像位置信息、相机、麦克风、日历、健身运动数据、身体传感器数据、音乐文件、图片视频这些权限都属于敏感权限。就拿位置信息来说吧,如果一个恶意应用获取了你的位置权限,它就可能追踪你的行踪,把你的位置信息泄露出去,这多可怕呀。再比如相机和麦克风权限,要是被不良应用获取了,它就能在你毫不知情的情况下偷偷拍照、录音,侵犯你的隐私。

而普通权限呢,相对来说就没那么敏感啦,对用户隐私的影响也比较小。就比如网络权限,很多应用都需要网络权限来加载数据、更新内容等 ,它是应用正常运行的基础权限之一。像一些简单的工具类应用,可能只需要网络权限就可以正常工作了,它不会涉及到用户的敏感信息。

从授权方式来看,普通权限中的 system_grant 类型权限,在应用安装时系统就会自动授予,不需要用户手动操作。而敏感权限大多属于user_grant类型权限,需要应用在运行时通过弹窗的方式向用户请求授权,用户可以根据自己的意愿选择允许或者拒绝。比如说,当你打开一个拍照应用时,它会弹出一个弹窗,询问你是否允许它使用相机权限,这时候你就可以根据自己的需求来决定是否授权。

(二)system_grant 和 user_grant

system_grant,也就是系统自动授予的权限。当应用在配置文件中声明了这类权限后,在用户安装应用的过程中,系统就会自动把相应的权限授予应用,整个过程用户是无感知的,开发者也不需要在代码中额外处理授权逻辑 。就像我们刚才提到的网络权限 ohos.permission.INTERNET,很多应用都需要网络连接来获取数据、展示内容等,在配置文件中声明这个权限后,系统在安装应用时就会自动授予,应用就可以直接使用网络功能了。在 module.json5 文件中声明system_grant权限的代码示例如下:

{
    "module": {
        "requestPermissions": [
            {
                "name": "ohos.permission.INTERNET"
            }
        ]
    }
}

user_grant 则是用户手动授权的权限。这类权限涉及到用户或设备的敏感信息,应用不仅需要在安装包的配置文件中申请权限,还需要在应用动态运行时,通过发送弹窗的方式请求用户授权 ,只有用户手动允许授权后,应用才会真正获取相应权限,从而成功访问操作目标对象。以获取位置信息的权限 ohos.permission.LOCATION 为例,在配置文件中声明时,除了要填写权限名称,还需要填写权限使用理由 reason 和使用场景 usedScene,如下所示:

{
    "module": {
        "requestPermissions": [
            {
                "name": "ohos.permission.LOCATION",
                "reason": "$string:reason_location",
                "usedScene": {
                    "abilities": ["EntryAbility"],
                    "when": "inuse"
                }
            }
        ]
    }
}

在代码中动态申请 user_grant 权限时,需要使用相关的 API 来请求授权,并处理授权结果 。示例代码如下:

import abilityAccessCtrl from '@ohos.abilityAccessCtrl';

async function requestLocationPermission() {
    const atManager = abilityAccessCtrl.createAtManager();
    const permissions = ['ohos.permission.LOCATION'];
    try {
        const result = await atManager.requestPermissionsFromUser(this.context, permissions);
        if (result.authResults.every(item => item === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)) {
            console.info('用户已授权');
            // 执行需要位置权限的操作
        } else {
            console.info('用户拒绝授权');
            // 处理用户拒绝授权的情况,比如提示用户去设置中打开权限
        }
    } catch (error) {
        console.error('请求权限失败', error);
    }
}

通过上面的介绍,相信大家对 system_grant user_grant 这两种授权方式有了更清晰的认识。在实际开发中,我们要根据权限的类型和应用的需求,合理地使用这两种授权方式,既能保证应用功能的正常实现,又能保护用户的隐私安全 。

三、权限申请实战

(一)配置文件声明权限

在鸿蒙应用开发中,配置文件声明权限是权限管理的基础,而且在 module.json5 文件中进行声明 。这里以申请麦克风权限为例,给大家详细讲讲。

{
    "module": {
        "requestPermissions": [
            {
                "name": "ohos.permission.MICROPHONE",
                "reason": "$string:reason_microphone",
                "usedScene": {
                    "abilities": ["EntryAbility"],
                    "when": "inuse"
                }
            }
        ]
    }
}

在这个代码示例里,“name” 字段指定了要申请的权限名称,这里是 ohos.permission.MICROPHONE,也就是麦克风权限 。“reason” 字段是必填项,它用于说明申请权限的原因,这里通过 "\$string:reason\_microphone" 引用了 strings.json 文件中定义的原因描述 ,这样做的好处是方便进行多语言适配,当应用需要支持不同语言时,只需要在 strings.json 文件中对应语言的部分修改原因描述即可 。比如在 strings.json 中可以这样定义:

{
    "string": [
        {
            "name": "reason_microphone",
            "value": "用于语音聊天功能"
        }
    ]
}

"usedScene" 字段则描述了权限的使用场景 。其中,"abilities" 数组指定了哪些 Ability 会使用这个权限,这里只有 "EntryAbility",表示只有EntryAbility会用到麦克风权限 。"when" 字段指定了权限的调用时机,"inuse" 表示在使用相关功能时才申请权限,这样可以更好地保护用户隐私,只有在真正需要使用麦克风时才向用户申请权限,而不是一打开应用就申请 。

(二)代码中动态申请权限

在代码中动态申请权限,我们需要使用 abilityAccessCtrl 模块提供的 API 。还是以申请麦克风权限为例,下面是具体的代码实现:

import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import { getContext } from '@ohos.app.ability';

async function requestMicrophonePermission() {
    const atManager = abilityAccessCtrl.createAtManager();
    const permissions = ['ohos.permission.MICROPHONE'];
    try {
        const result = await atManager.requestPermissionsFromUser(getContext(), permissions);
        if (result.authResults.every(item => item === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)) {
            console.info('用户已授权,可以使用麦克风');
            // 这里可以执行需要麦克风权限的操作,比如开始录音
        } else {
            console.info('用户拒绝授权');
            // 处理用户拒绝授权的情况,比如提示用户去设置中打开权限
            const shouldShowRequestPermissionRationale = await atManager.shouldShowRequestPermissionRationale(getContext(), permissions[0]);
            if (shouldShowRequestPermissionRationale) {
                // 向用户解释为什么需要这个权限
                console.info('向用户解释需要麦克风权限的原因');
            } else {
                // 引导用户去设置中打开权限
                console.info('引导用户去设置中打开麦克风权限');
            }
        }
    } catch (error) {
        console.error('请求权限失败', error);
    }
}

在这段代码中,首先通过 abilityAccessCtrl.createAtManager () 创建了一个权限管理对象 atManager 。然后定义了要申请的权限数组 permissions,这里只申请了麦克风权限 。接着使用 atManager.requestPermissionsFromUser () 方法向用户申请权限,这个方法会返回一个 Promise,通过 await 等待用户的授权结果 。如果用户授权,authResults 数组中的所有元素都会是 abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED,此时就可以执行需要麦克风权限的操作了 。如果用户拒绝授权,authResults 数组中会有元素是 abilityAccessCtrl.GrantStatus.PERMISSION_DENIED,这时我们需要处理用户拒绝授权的情况 。通过 atManager.shouldShowRequestPermissionRationale () 方法可以判断是否需要向用户解释为什么需要这个权限,如果返回 true,就向用户解释原因,比如可以弹出一个弹窗,告知用户开启麦克风权限后可以使用语音聊天、语音输入等功能 ;如果返回 false,就引导用户去设置中打开权限,比如可以提供一个按钮,点击后跳转到系统设置中应用的权限设置页面 。这样,我们就完成了在代码中动态申请权限以及处理授权结果的过程 。

四、权限管理优化技巧

(一)权限分组管理

权限组是鸿蒙系统为了减少权限弹窗对用户的打扰而引入的一种管理机制 。它把逻辑紧密相关的 user_grant 权限组合在一起,当应用请求权限时,同一个权限组的权限会在一个弹窗内一起请求用户授权 。就好比把一系列相关的物品打包成一个包裹,一次性递送给用户,而不是逐个递送,这样能提高交互效率 。比如说位置信息权限组,它可能包含获取精确位置(ohos.permission.LOCATION)和获取模糊位置(ohos.permission.APPROXIMATELY_LOCATION)等相关权限 。当应用需要获取位置信息时,只需要弹出一个权限申请弹窗,向用户一次性说明应用获取位置信息的目的和所需的具体权限,而不是针对每个位置相关权限分别弹窗,这就大大减少了弹窗的数量,提升了用户体验 。再比如通讯录权限组,它包含读取联系人数据(ohos.permission.READ_CONTACTS)和添加、移除或更改联系人数据(ohos.permission.WRITE_CONTACTS)这两个权限 。当应用需要访问通讯录相关功能时,这两个权限会在同一个弹窗中请求用户授权 。

在代码实现上,以申请位置信息权限组和相机权限为例,假设我们的应用在一个功能中需要同时获取用户的位置信息和使用相机进行拍照操作 。按照权限组的方式申请权限,代码如下:

import { abilityAccessCtrl, common, Permissions } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

// 定义需要申请的权限列表,包含位置信息权限组和相机权限
const permissions: Array<Permissions> = ['ohos.permission.APPROXIMATELY_LOCATION', 'ohos.permission.LOCATION', 'ohos.permission.CAMERA'];

function reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext): void {
    let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
    atManager.requestPermissionsFromUser(context, permissions).then((data) => {
        let grantStatus: Array<number> = data.authResults;
        let length: number = grantStatus.length;
        for (let i = 0; i < length; i++) {
            if (grantStatus[i] === 0) {
                // 用户授权,可以继续访问目标操作
            } else {
                // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限
                return;
            }
        }
        // 授权成功
    }).catch((err: BusinessError) => {
        console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
    });
}

// 在应用启动或需要使用这些权限的地方调用 reqPermissionsFromUser() 函数来申请权限
reqPermissionsFromUser(permissions, globalThis.context as common.UIAbilityContext);

在这段代码中,我们把位置信息权限组中的两个权限(ohos.permission.APPROXIMATELY_LOCATIONohos.permission.LOCATION)以及相机权限(ohos.permission.CAMERA)一起放入权限列表中进行申请 。当应用执行到 requestPermissionsFromUser () 函数时,系统会根据权限组的规则,将位置信息相关的两个权限合并在一个弹窗中展示给用户,而相机权限则在另一个弹窗中展示(因为相机权限属于不同的权限组),这样就有效地减少了弹窗的数量,提升了用户体验 。

(二)避免过度申请权限

遵循最小权限原则可是相当重要的,它要求我们在开发应用时,只申请那些为了实现应用功能所真正必需的权限 ,坚决避免申请不必要的权限 。这是为啥呢?要是一个应用申请了过多不必要的权限,会让用户对应用的安全性产生担忧 。比如说,一个简单的天气应用,它只需要获取网络权限来获取天气数据就可以了 。但如果它还申请了通讯录、麦克风等与天气功能毫无关系的权限,用户肯定会觉得这个应用有问题,会不会在偷偷收集我的隐私信息呀 ?这样一来,用户对应用的信任度就会降低,甚至可能直接卸载应用,这对应用的安装率和留存率都会产生负面影响 。

那怎么检查和优化权限申请呢?我们可以定期对应用所申请的权限进行全面梳理 。仔细思考每个权限是否真的是应用正常运行所不可或缺的 。对于那些不确定是否需要的权限,可以先将其从申请列表中移除,然后进行功能测试 。如果发现移除某个权限后,应用的某些功能无法正常使用,那就说明这个权限是必要的,需要重新添加回来 。比如说,我们开发一个文件管理应用,一开始申请了相机权限 。但在检查时发现,相机权限与文件管理的核心功能并没有直接关系,那么就可以把相机权限从申请列表中去掉 。另外,我们还可以参考一些优秀应用的权限申请策略 ,学习它们是如何合理申请权限的 。同时,关注鸿蒙系统的权限管理规范和更新,确保我们的应用始终符合最新的要求 。

五、常见问题与解决方案

在鸿蒙开发的权限管理过程中,难免会遇到一些棘手的问题 。下面我就给大家分享一些常见问题以及对应的解决方案 。

(一)权限申请失败

权限申请失败可能由多种原因导致 。比如权限未在配置文件中声明,这就好比你要去一个地方,但没有告诉别人你的目的地,别人自然无法为你指路 。在鸿蒙开发中,如果应用在申请权限之前,没有在 module.json5 文件中声明需要申请的权限,系统就无法识别应用对该权限的需求,从而导致权限申请失败 。解决办法很简单,就是在 module.json5 文件的 requestPermissions 字段中正确声明权限 。例如申请相机权限,代码如下:

{
    "module": {
        "requestPermissions": [
            {
                "name": "ohos.permission.CAMERA",
                "reason": "$string:reason_camera",
                "usedScene": {
                    "abilities": ["EntryAbility"],
                    "when": "inuse"
                }
            }
        ]
    }
}

还有一种情况是权限已被其他应用程序占用 。鸿蒙系统中的权限是全局唯一的,同一权限只能被一个应用程序占用 。如果其他应用程序已经申请了某个权限,并且该权限与你的应用冲突,那么你的权限申请就会失败 。遇到这种情况,你可以考虑调整应用的功能设计,或者引导用户关闭占用该权限的其他应用 。

(二)用户频繁拒绝授权

有些用户可能出于隐私保护的考虑,会频繁拒绝应用的授权请求 ,这时候我们需要采取一些措施来提升用户的授权意愿 。可以提供更详细的权限使用说明,让用户清楚地了解应用获取权限后会如何使用这些信息 。比如在申请位置信息权限时,向用户说明应用获取位置信息是为了提供更精准的周边服务,如查找附近的餐厅、加油站等 。示例代码如下:

async function requestLocationPermission() {
    const atManager = abilityAccessCtrl.createAtManager();
    const permissions = ['ohos.permission.LOCATION'];
    try {
        const result = await atManager.requestPermissionsFromUser(this.context, permissions);
        if (result.authResults.every(item => item === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)) {
            console.info('用户已授权');
        } else {
            console.info('用户拒绝授权');
            // 向用户解释为什么需要这个权限
            const shouldShowRequestPermissionRationale = await atManager.shouldShowRequestPermissionRationale(this.context, permissions[0]);
            if (shouldShowRequestPermissionRationale) {
                promptAction.showToast({ message: '为了给您提供更精准的周边服务,需要获取您的位置信息,请您授权' });
            } else {
                // 引导用户去设置中打开权限
                console.info('引导用户去设置中打开位置权限');
            }
        }
    } catch (error) {
        console.error('请求权限失败', error);
    }
}

另外,还可以提供备选方案或降级功能 。比如当用户拒绝相机权限时,应用可以提供从相册选择图片的功能作为替代,确保用户在不授权的情况下也能继续使用应用的部分核心功能 ,这样能在一定程度上提升用户体验,减少用户因拒绝授权而流失的情况 。

六、总结与展望

到这里,关于鸿蒙开发中应用权限的内容就给大家分享得差不多啦 。从最开始对权限的初步认识,了解到权限在应用开发中的重要性,到深入剖析权限的分类,包括敏感权限和普通权限的区别,以及 system_grantuser_grant 这两种不同的授权方式 ;再到实战环节,学会在配置文件中声明权限,在代码中动态申请权限 ;还有权限管理的优化技巧,像权限分组管理和避免过度申请权限 ;最后还解决了一些常见问题,比如权限申请失败和用户频繁拒绝授权的应对方法 。这些内容都是我们在鸿蒙开发中进行权限管理的关键要点 。

在实际开发中,大家一定要重视权限管理 。它不仅关乎用户的隐私安全,还直接影响着应用的口碑和用户留存率 。我们要始终遵循最小权限原则,只申请应用真正需要的权限,并且在申请敏感权限时,一定要详细、准确地向用户说明使用理由 ,让用户清楚地知道应用获取这些权限的目的 。同时,合理利用权限分组管理等优化技巧,提升用户体验 。

随着鸿蒙系统的不断发展和完善,应用权限管理也会持续演进 。未来,可能会出现更智能、更便捷的权限管理方式,比如根据应用的使用场景自动调整权限授予情况 ,或者提供更细粒度的权限控制选项 。大家要持续关注鸿蒙开发的最新动态,不断学习和掌握新的权限管理知识和技能 ,这样才能在开发中紧跟时代步伐,为用户打造出更安全、更优质的应用 。好了,今天的分享就到这里,希望对大家有所帮助 ,如果在开发过程中有任何问题,欢迎在评论区留言交流 。

你可能感兴趣的:(鸿蒙HarmonyOS,harmonyos,华为)