鸿蒙应用权限控制与位置服务(Location Kit)
11_11日学习笔记
一、应用权限管控
概述:
Ability Kit提供了一种允许应用访问系统资源
(如:通讯录等)和系统能力
(如:访问摄像头、麦克风等)的通用权限访问方式,来保护系统数据(包括用户个人数据)或功能,避免它们被不当或恶意使用。
快影app后台播放!
鸿蒙系统为每个应用提供一个tokenid(令牌),作为 应用的唯一标识。
应用权限保护的对象可以分为数据和功能:
● 数据
包括个人数据(如照片、通讯录、日历、位置等)、设备数据(如设备标识、相机、麦克风等)。
● 功能
包括设备功能(如访问摄像头/麦克风、打电话、联网等)、应用功能(如弹出悬浮窗、创建快捷方式等)。
系统采用**
TokenID
**作为应用的唯一标识。权限管理服务通过应用的TokenID来管理应用的AT(Access Token)信息,包括应用身份标识APP ID、子用户ID、应用分身索引信息、应用APL、应用权限授权状态等。在资源使用时,系统将通过TokenID作为唯一身份标识映射获取对应应用的权限授权状态信息,并依此进行鉴权,从而管控应用的资源访问行为。系统支持多用户特性和应用分身特性,同一个应用在不同的子用户下和不同的应用分身下会有各自的AT,这些AT的TokenID也是不同的。
授权方式分类:
1、system_grant(系统授权)
(module.json5)申请权限
应用被允许访问的数据不会涉及到用户或设备的敏感信息。
(如果在应用中申请了system_grant权限,那么系统会在用户安装应用时,自动把相应权限授予给应用。)
2、user_grant(用户授权)
(module.json5)申请权限 + 运行时弹窗请求授权
涉及用户敏感信息
该类型权限不仅需要①在安装包中申请权限,还需要在应用动态运行时,②通过发送弹窗的方式请求用户授权。
面试题:请问那些是用户授权的权限?那些是系统授权的权限?
系统授权权限:
ohos.permission.INTERNET | 允许使用网络资源 |
---|---|
ohos.permission.KEEP_BACKGROUND_RUNNING | 允许Ability在后台持续运行 |
ohos.permission.USE_BLUETOOTH | 允许应用查看蓝牙的配置 |
ohos.permission.PRINT | 允许应用获取打印框架的能力 |
ohos.permission.ACCELEROMETER | 允许应用读取加速度传感器的数据 |
ohos.permission.VIBRATE | 允许应用控制马达振动 |
用户授权的权限:
ohos.permission.APP_TRACKING_CONSENT | 允许应用读取开放匿名设备标识符 |
---|---|
ohos.permission.CAMERA | 允许应用使用相机 |
ohos.permission.DISTRIBUTED_DATASYNC | 允许不同设备间的数据交换 |
ohos.permission.APPROXIMATELY_LOCATION | 允许应用获取设备模糊位置信息 |
ohos.permission.LOCATION | 允许应用获取设备位置信息 |
ohos.permission.WRITE_MEDIA | 允许应用读写用户外部存储中的媒体文件信息 |
配置过程:
系统授权配置
配置文件授权:
1、首先需要在项目的配置文件(module.json5)中,申请系统授予权限:
//当前应用模块向用户申请各种权限(系统授予+用户授予)
"requestPermissions": [
// ①向系统申请 ‘系统授予权限’
{
"name": "ohos.permission.INTERNET" , //互联网访问权限(系统权限)
},
{
"name": "ohos.permission.KEEP_BACKGROUND_RUNNING" //后台运行(系统权限),应用在后台可以继续运行
}
],
(前应用模块向用户申请各种权限(系统授予+用户授予))
当应用申请user_grant权限时,需要完成以下步骤:
① 在配置文件(module.json5)中,声明应用需要请求的权限。
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/4e47317452464e08814e2678734cdfd4.png#pic_center
"requestPermissions": [
//②向用户申请 “用户授予权限”
{
"name": "ohos.permission.APPROXIMATELY_LOCATION", //模糊定位
"reason": '$string:Location_Reason', //申请当前权限的原因说明
"usedScene": { //申请的权限具体使用场景说明
"when": "always", //何时使用该权限! inuse在使用中,always总是
"abilities": ["EntryAbility"] //哪些组件需要使用该权限
}
},
{
"name": "ohos.permission.LOCATION", //精准定位
"reason": '$string:Location_Reason',
"usedScene": {
"abilities": ["EntryAbility"],
"when": "always"
}
}
],
② 将应用中需要申请权限的目标对象与对应目标权限进行关联,让用户明确地知道,哪些操作需要用户向应用授予指定的权限。
③ 运行应用时,在用户触发访问操作目标对象时应该调用接口,精准触发动态授权弹框。该接口的内部会检查当前用户是否已经授权应用所需的权限,如果当前用户尚未授予应用所需的权限,该接口会拉起动态授权弹框,向用户请求授权。
④ 检查用户的授权结果,确认用户已授权才可以进行下一步操作。
每次执行需要目标权限的操作时,应用都必须使用checkAccessToken()函数检查自己是否已经具有该权限每次访问受目标权限保护的接口之前,都需要使用requestPermissionsFromUser()接口请求相应的权限
页面现实时,弹出 “ 定位授权对话框
创建onpageShow()方法
//页面现实时,弹出 “ 定位授权对话框 ”
onPageShow() {
}
1、声明需要用户授权的权限列表
2、检查之前是否对这些权限授权过
3、如果之前从未授权过,则弹出“授权请求对话框”
完整代码:
import { Permissions } from '@ohos.privacyManager'
import { abilityAccessCtrl, bundleManager } from '@kit.AbilityKit'
@Entry
@Component
struct Index {
//页面现实时,弹出 “ 定位授权对话框 ”
async onPageShow() {
// 1、声明需要用户授权的权限列表
let list:Permissions[] = [
"ohos.permission.APPROXIMATELY_LOCATION", //模糊定位
"ohos.permission.LOCATION" //精确定位 ---》用精确定位,必须要有模糊定位为前提!
]
// 2、检查之前是否对这些权限进行过授权 TokenID => AccessManager => AccessToken => 过往的授权记录
let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION) //得到资源报信息
let tokenID = bundleInfo.appInfo.accessTokenId //从资源包信息中获取 权限令牌编号
let acsMgr = abilityAccessCtrl.createAtManager() //AT表示AccessToken
let grantStatus0 = acsMgr.checkAccessTokenSync(tokenID,list[0]) //检查访问令牌,返回值是授权状态
let grantStatus1 = acsMgr.checkAccessTokenSync(tokenID,list[1]) //检查访问令牌,返回值是授权状态
// 3、如果之前从未授权过,则弹出请求对话框
// console.log('--授权状态:',grantStatus0)
if (grantStatus0 === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) { //-1表示尚未授权过DENIED,0表示已经授权
let result = await acsMgr.requestPermissionsFromUser(getContext(),list) //list表示两个权限 --> 权限列表 ---permissionList:permissions
if (result.authResults[0] === 0) { //授权结果,authResults[]两个权限
console.log('---定位相关的两个权限通过了用户授权')
} else { //-1表示DENIED
console.log('---用户拒绝了定位相关的两个权限授权')
}
}
}
build() {
Column() {
Text('首页')
.fontSize(30)
}
.height('100%')
.width('100%')
}
}
运行结果:
二、定位服务(Location Kit):
一次性获取用户当前位置
获取当前位置:
let location = await geoLocationManager.getCurrentLocation({})
原因:没有把当前位置打开
在获取用户当前地理位置之后,进一步通过经纬度信息反编码出具体的地理位置信息。
完整代码:
完整代码:
import { Permissions } from '@ohos.privacyManager'
import { abilityAccessCtrl, bundleManager } from '@kit.AbilityKit'
import { geoLocationManager } from '@kit.LocationKit'
import { JSON } from '@kit.ArkTS'
@Entry
@Component
struct Index {
//页面现实时,弹出 “ 定位授权对话框 ”
async onPageShow() {
// 1、声明需要用户授权的权限列表
let list:Permissions[] = [
"ohos.permission.APPROXIMATELY_LOCATION", //模糊定位
"ohos.permission.LOCATION" //精确定位 ---》用精确定位,必须要有模糊定位为前提!
]
// 2、检查之前是否对这些权限进行过授权 TokenID => AccessManager => AccessToken => 过往的授权记录
let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION) //得到资源报信息
let tokenID = bundleInfo.appInfo.accessTokenId //从资源包信息中获取 权限令牌编号
let acsMgr = abilityAccessCtrl.createAtManager() //AT表示AccessToken
let grantStatus0 = acsMgr.checkAccessTokenSync(tokenID,list[0]) //检查访问令牌,返回值是授权状态
let grantStatus1 = acsMgr.checkAccessTokenSync(tokenID,list[1]) //检查访问令牌,返回值是授权状态
// 3、如果之前从未授权过,则弹出请求对话框
// console.log('--授权状态:',grantStatus0)
if (grantStatus0 === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) { //-1表示尚未授权过DENIED,0表示已经授权
let result = await acsMgr.requestPermissionsFromUser(getContext(),list) //list表示两个权限 --> 权限列表 ---permissionList:permissions
if (result.authResults[0] === 0) { //授权结果,authResults[]两个权限
console.log('---定位相关的两个权限通过了用户授权')
} else { //-1表示DENIED
console.log('---用户拒绝了定位相关的两个权限授权')
}
}
}
build() {
Column() {
Text('首页')
.fontSize(30)
Button('1、一次性获取用户当前位置').onClick(async _=>{
try {
let location = await geoLocationManager.getCurrentLocation({})
console.log('获取位置信息成功!',JSON.stringify(location))
} catch (err) {
console.log('获取定位信息失败!:',JSON.stringify(err))
}
})
Button('1-2、一次性获取用户当前位置').onClick(async _=>{
try {
let loc = await geoLocationManager.getCurrentLocation()
// 根据经纬度信息反编码出地理信息 --- 需要在真机才有效
let request:geoLocationManager.ReverseGeoCodeRequest= {
latitude: loc.latitude,
longitude: loc.longitude
}
let list = await geoLocationManager.getAddressesFromLocation(request)
console.log('当前坐标所表示的地理位置',JSON.stringify(list))
} catch (err) {
console.log('获取定位信息失败!',JSON.stringify(err))
}
})
Button('2、持续获取用户位置的改变').onClick(_=> {
})
}
.height('100%')
.width('100%')
}
}