自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

向用戶動(dòng)態(tài)申請(qǐng)授權(quán)

系統(tǒng) OpenHarmony
Nothing theoretical can be clearer than the code. 本期筆者將以一個(gè)Demo為例,與讀者們共同探討在ArkUI的框架中如何實(shí)現(xiàn)動(dòng)態(tài)申請(qǐng)授權(quán)的功能。

想了解更多關(guān)于開(kāi)源的內(nèi)容,請(qǐng)?jiān)L問(wèn):

51CTO 開(kāi)源基礎(chǔ)軟件社區(qū)

https://ost.51cto.com

前言

應(yīng)用向用戶動(dòng)態(tài)申請(qǐng)授權(quán),是指在用戶使用應(yīng)用的過(guò)程中,應(yīng)用方會(huì)根據(jù)應(yīng)用場(chǎng)景和業(yè)務(wù)向用戶動(dòng)態(tài)地請(qǐng)求相應(yīng)的權(quán)限。例如,當(dāng)應(yīng)用需要訪問(wèn)用戶的相機(jī)或麥克風(fēng)時(shí),會(huì)向用戶彈出一個(gè)授權(quán)請(qǐng)求框,詢問(wèn)用戶是否允許應(yīng)用訪問(wèn)這些設(shè)備,而用戶可以選擇允許或拒絕此次授權(quán)請(qǐng)求。這種方式可以提高應(yīng)用的安全性,在一定程度上保護(hù)用戶的隱私信息安全。

Nothing theoretical can be clearer than the code.  本期筆者將以一個(gè)Demo為例,與讀者們共同探討在ArkUI的框架中如何實(shí)現(xiàn)動(dòng)態(tài)申請(qǐng)授權(quán)的功能

正文

通常情況下,一些提供基礎(chǔ)功能的權(quán)限可以通過(guò)靜態(tài)的方式獲?。粗苯訉㈤_(kāi)發(fā)者需要的權(quán)限在模塊級(jí)別的module.json5文件中聲明),如聯(lián)網(wǎng)權(quán)限。而對(duì)于一些能夠?yàn)閼?yīng)用提供用戶的隱私數(shù)據(jù)的敏感權(quán)限,則需要以動(dòng)態(tài)的方式可視化地向用戶申請(qǐng)。本期的Demo以申請(qǐng)獲取大致位置權(quán)限(即"ohos.permission.APPROXIMATELY_LOCATION")為例,實(shí)現(xiàn)動(dòng)態(tài)申請(qǐng)權(quán)限的功能。

新建工程

打開(kāi)DevEco Studio(開(kāi)發(fā)工具的版本必須支持API9),創(chuàng)建一個(gè)新的project,相關(guān)勾選如下

在module.json5中添加相應(yīng)的權(quán)限

成功創(chuàng)建工程后,在工程文件目錄中打開(kāi)目錄:entry/src/main/module.json5, 添加兩個(gè)權(quán)限——定位權(quán)限( "ohos.permission.LOCATION")和獲取大致位置的權(quán)限("ohos.permission.APPROXIMATELY_LOCATION" )。

{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": [
      "phone"
    ],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",

    //添加模塊所需的相關(guān)權(quán)限
    "requestPermissions": [
      {
        "name": "ohos.permission.APPROXIMATELY_LOCATION",
        "usedScene": {
          "abilities": [
            "EntryAbility"
          ],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.LOCATION",
        "usedScene": {
          "abilities": [
            "EntryAbility"
          ],
          "when": "inuse"
        }
      },
    ],
    
    ......

  }
}

事實(shí)上,當(dāng)應(yīng)用同時(shí)獲取以上兩種權(quán)限后,應(yīng)用可以獲取設(shè)備的精準(zhǔn)位置,精準(zhǔn)度在米級(jí)別。

集成功能模塊

要實(shí)現(xiàn)向用戶動(dòng)態(tài)申請(qǐng)授權(quán)的功能,我們需要制作兩個(gè)功能模塊,分別是檢查是否已獲得所需權(quán)限的功能和向用戶發(fā)起權(quán)限申請(qǐng)的功能。為了達(dá)到公共調(diào)用和功能模塊化,我們需要將這兩個(gè)功能模塊集成到兩個(gè)不同的TypeScript文件中,并將可調(diào)用接口導(dǎo)出。

在ets文件夾下新建目錄,并將其命名為Service。

在Service目錄下新建兩個(gè)TypeScript文件(右鍵Service目錄,選擇新建,再選擇TypeScript),分別命名為Detector與Applicant。

在編輯器中打開(kāi)Detector.ts,加入以下代碼以集成檢查應(yīng)用是否已獲得所需權(quán)限的功能,各代碼塊的具體功能已寫(xiě)注解

//導(dǎo)入程序訪問(wèn)控制管理模塊
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';

//導(dǎo)入包管理模塊
import bundleManager from '@ohos.bundle.bundleManager';

///定義待檢測(cè)的權(quán)限列表
const permissionsList: Array<Permissions> = ['ohos.permission.APPROXIMATELY_LOCATION']     //權(quán)限數(shù)據(jù)的列表

//模塊的日志標(biāo)簽
const TAG = '------[Detector] '

const APPROVAL:number = 0

//默認(rèn)導(dǎo)出的模塊接口
export default async function Check_Access(){

  //創(chuàng)建AtManager實(shí)例
  let atManager = abilityAccessCtrl.createAtManager()

  //定義局部變量grantStatus
  let grantStatus:abilityAccessCtrl.GrantStatus

  //定義局部變量tokenId
  let tokenId:number

  try{

    //等待包管理模塊獲取本模塊所在的包的BundleInfo
    let bundleInfo:bundleManager.BundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION)
    //獲取上述BundleInfo中攜帶的ApplicationInfo
    let appInfo:bundleManager.ApplicationInfo = bundleInfo.appInfo
    //獲上述ApplicationInfo攜帶的accessTokenId
    tokenId = appInfo.accessTokenId
    
  }catch (err){
    console.error(TAG+`getBundleInfoForSelf failed, code is ${err.code}, message is ${err.message}`)
  }

  try{
    //利用AManager實(shí)例檢查是否已獲得所需權(quán)限
    grantStatus = await atManager.checkAccessToken(tokenId,permissionsList[0])
  }catch (err){
    console.error(TAG+`checkAccessToken failed, code is ${err.code}, message is ${err.message}`)
  }

  //根據(jù)不同的檢查結(jié)果做不同的輸出
  if(grantStatus == APPROVAL){
    console.info(TAG+'Accessible')
    return true
  }else {
    console.error(TAG+'Inaccessible')
    return false
  }

}

因?yàn)楣P者已給代碼添加了注釋,所以筆者就不對(duì)這個(gè)模塊做太多啰嗦的分析了。這個(gè)模塊的大致執(zhí)行邏輯是,通過(guò)調(diào)用系統(tǒng)能力@ohos.bundle.bundleManager獲取本包的accessTokenId,再調(diào)用系統(tǒng)能力@ohos.abilityAccessCtrl,在傳入accessTokenId和權(quán)限列表的條件下檢查module是否已獲取權(quán)限列表中的每個(gè)權(quán)限。當(dāng)atManager的異步方法checkAccessToken返回結(jié)果為0時(shí),表示所需權(quán)限均已被提供。

在編輯器中打開(kāi)Applicant.ts,加入以下代碼以集成向用戶發(fā)起權(quán)限申請(qǐng)的功能,各代碼塊的具體功能已寫(xiě)注解。

//導(dǎo)入程序訪問(wèn)控制管理模塊
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl'

//導(dǎo)入common
import common from '@ohos.app.ability.common';

//定義待動(dòng)態(tài)申請(qǐng)的權(quán)限列表
const permissionsList: Array<Permissions> = ['ohos.permission.APPROXIMATELY_LOCATION']

const APPROVAL:number = 0

//模塊的日志標(biāo)簽
const TAG = '------[Applicant] '

//默認(rèn)導(dǎo)出的模塊接口
export default async function Request_Permission_From_Users(context:common.UIAbilityContext){

  //預(yù)定義函數(shù)執(zhí)行結(jié)果的狀態(tài)
  let isFinished:boolean = false

  //創(chuàng)建AtManager實(shí)例
  let atManager = abilityAccessCtrl.createAtManager()

  //等待程序訪問(wèn)控制模塊完成權(quán)限請(qǐng)求的異步操作,完成后根據(jù)返回結(jié)果執(zhí)行then()或catch()
  await atManager.requestPermissionsFromUser(context, permissionsList).then((result)=>{

    //將API返回的數(shù)據(jù)存儲(chǔ)到變量grantStatus中
    let grantStatus: Array<number> = result.authResults

    //判斷用戶是否提供所有相關(guān)權(quán)限
    for(let i = 0 ; i < grantStatus.length ; i++){
      if(grantStatus[i] === APPROVAL){   //用戶提供所有權(quán)限, ===指的是全等
        console.info(TAG+'Succeed! Obtain all the permissions')
        isFinished = true   //將函數(shù)執(zhí)行結(jié)果的狀態(tài)設(shè)置為true
      }else{   //用戶未提供所有權(quán)限
        console.error(TAG+'User denies providing the permissions')
      }
    }
  }).catch((err)=>{
    console.error(TAG+`Request permission failed, code is ${err.code}, message is ${err.message}`)
  })

  return isFinished

}

這個(gè)模塊的大致執(zhí)行邏輯是,在atManager的異步方法requestPermissionsFromUser

中傳入所需的上下文對(duì)象和待申請(qǐng)權(quán)限列表,并等待其異步過(guò)程的結(jié)束。在requestPermissionsFromUser的異步過(guò)程中,系統(tǒng)會(huì)彈出選擇框,詢問(wèn)用戶是否提供權(quán)限。當(dāng)用戶點(diǎn)擊選擇框中的允許或禁止時(shí),權(quán)限會(huì)被授予或否,異步過(guò)程隨即結(jié)束(此處指的是申請(qǐng)單個(gè)權(quán)限的場(chǎng)景),requestPermissionsFromUser將申請(qǐng)結(jié)果以number型數(shù)組的形式輸出。當(dāng)此數(shù)組中的每個(gè)元素的值都為0時(shí),表示所有權(quán)限都成功獲得,否則,用戶拒絕授權(quán)了至少一個(gè)權(quán)限。

Detector.ts和Applicant.ts均默認(rèn)導(dǎo)出了接口,想要在其他地方調(diào)用它們的功能,只需導(dǎo)入接口即可。

編輯頁(yè)面UI

添加圖片資源

在工程文件目錄中打開(kāi)目錄:src/main/resources/rawfile, 添加兩張任意的圖片(可以在IDE中將待添加的圖片資源直接粘貼至rawfile目錄下,也可以在文件資源管理器中通過(guò)文件路徑打開(kāi)rawfile目錄并添加圖片資源),分別命名為image1和image2。當(dāng)然,圖片的格式?jīng)]有要求,只要在之后的步驟中能被正確引用即可。

設(shè)計(jì)頁(yè)面UI

打開(kāi)Index.ts,刪除原有的Text組件,新增兩個(gè)Button組件和一個(gè)Image組件(相關(guān)屬性設(shè)置如下),并聲明一個(gè)用@state修飾的布爾變量ifAccessible。

@Entry
@Component
struct Index {

  //將應(yīng)用是否獲取權(quán)限這條信息用布爾型變量ifAccessible儲(chǔ)存
  @State ifAccessible:boolean = false

  build() {
    Row() {
      Column() {

        //添加兩個(gè)Button組件和一個(gè)Image組件

        //條件渲染Image組件
        if(this.ifAccessible){
          Image($rawfile('image2.png'))
            .height(200)
            .width(200)
        }else{
          Image($rawfile('image1.png'))
            .height(200)
            .width(200)
        }

				//第一個(gè)Button組件
        Button('檢查應(yīng)用是否獲得權(quán)限')
          .fontSize(20)
          .width('70%')
          .margin({
            top:40
          })
          .backgroundColor(Color.Pink)

				//第二個(gè)Button組件
        Button('向用戶動(dòng)態(tài)申請(qǐng)權(quán)限')
          .fontSize(20)
          .width('70%')
          .margin({
            top:20
          })
          .backgroundColor(Color.Pink)

      }
      .width('100%')
    }
    .height('100%')
  }
}

預(yù)覽器效果如下:


添加自定義彈窗

首先,在組件Index之外用struct聲明一個(gè)新的自定義組件dialog,并用裝飾器@CustomDialog對(duì)其進(jìn)行修飾,使dialog擁有成為自定義彈窗的能力。接著,我們對(duì)彈窗顯示的內(nèi)容進(jìn)行自定義設(shè)置,在build函數(shù)中加入自定義UI聲明。其中,CustomDialogController類型的成員變量controller和字符串類型成員變量message皆必不可少,后者可用于對(duì)dialog的外部傳參。

之后,我們?cè)诮M件Index中new兩個(gè)彈窗控制器( CustomDialogController類的實(shí)例),并分別將它們賦予兩個(gè)私有成員變量(dialogController_Accessible和dialogController_Inaccessible)以供調(diào)用。當(dāng)然,我們是用兩個(gè)message不同的dialog組件來(lái)構(gòu)造這兩個(gè)彈窗控制器的,所以彈窗控制器dialogController_Accessible和彈窗控制器dialogController_Inaccessible可用于打開(kāi)和關(guān)閉它們所對(duì)應(yīng)的dialog。

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'

 	......

  //new兩個(gè)彈窗控制器
  private dialogController_Accessible : CustomDialogController = new CustomDialogController({
    builder:dialog({
      message:'暫未獲取權(quán)限'
    })
  })

  private dialogController_Inaccessible : CustomDialogController = new CustomDialogController({
    builder:dialog({
      message:'已獲取權(quán)限'
    })
  })




  build() {
		......
	}
  
}

//自定義彈窗
@CustomDialog
struct dialog{

  controller:CustomDialogController

  @State message:string = ''

  build(){
    Column() {
      Text(this.message)
        .fontSize(20)
        .height(40)
        .fontColor(Color.White)
    }
    .width('100%')
    .backgroundColor(Color.Gray)
  }

}

編寫(xiě)回調(diào)方法

首先,我們從先前步驟中已集成的功能模塊Detector導(dǎo)入異步函數(shù)Check_Access,并自定義異步方法detect。在detect的方法體中,我們通過(guò)關(guān)鍵字await等待異步過(guò)程,這意味者原本的異步任務(wù)變成了一個(gè)等價(jià)的延時(shí)同步任務(wù),保證了detect中操作語(yǔ)句的順序執(zhí)行。由于關(guān)鍵字await只能在異步方法或異步函數(shù)中出現(xiàn),所以detect必須是異步方法。根據(jù)Check_Access的不同返回結(jié)果(成功或失?。?,系統(tǒng)會(huì)生成不同內(nèi)容的彈窗與用戶交互。detect()編寫(xiě)完后,我們?cè)谟糜跈z查應(yīng)用是否獲得權(quán)限的Button組件的onclick事件中加入此異步方法。

import Check_Access from 'ets/Service/Detector'  //從模塊Detector中導(dǎo)入異步函數(shù)Check_Access

@Entry
@Component
struct Index {
  
  .....

  //編寫(xiě)異步方法detect,調(diào)用之前已寫(xiě)好的模塊文件Detector
  async detect(){
    let res = await Check_Access()
    this.ifAccessible = res
    if(res){
      this.dialogController_Accessible.open()
    }else{
      this.dialogController_Inaccessible.open()
    }

  }

	......


  build() {
    Row() {
      Column() {

				......


        Button('檢查應(yīng)用是否獲得權(quán)限')
          .fontSize(20)
          .width('70%')
          .margin({
            top:40
          })
          .backgroundColor(Color.Pink)
          //設(shè)置onclick回調(diào),并調(diào)用異步函數(shù)detect()
          .onClick(()=>{
            this.detect()
          })


			......

      }
      .width('100%')
    }
    .height('100%')
  }
}

......

接著,我們從先前步驟中已集成的功能模塊Applicant中導(dǎo)入異步函數(shù)Request_Permission_From_Users,并導(dǎo)入common。隨后,我們通過(guò)getContext方法獲取上下文對(duì)象,并將其轉(zhuǎn)化為UIAbilityContext類型,存入私有成員變量context中。之后,自定義異步方法apply,在方法體中將成員變量context傳入異步函數(shù)Request_Permission_From_Users中。這樣以后,我們便可在用于向用戶動(dòng)態(tài)申請(qǐng)權(quán)限的Button組件的onclick事件中加入自定義方法apply了。

......
import Request_Permission_From_Users from 'ets/Service/Applicant'
import common from '@ohos.app.ability.common'

@Entry
@Component
struct Index {
	
  ......

  //獲取上下文對(duì)象, 儲(chǔ)存在成員變量context中
  private context = getContext(this) as common.UIAbilityContext

  //編寫(xiě)異步方法,調(diào)用之前已寫(xiě)好的模塊文件Applicant
  async apply(){
    let res = await Request_Permission_From_Users(this.context)
    this.ifAccessible = res
    if(res){
      this.dialogController_Accessible.open()
    }else{
      this.dialogController_Inaccessible.open()
    }
  }
	......
  build() {
    Row() {
      Column() {
        ......
        Button('向用戶動(dòng)態(tài)申請(qǐng)權(quán)限')
          .fontSize(20)
          .width('70%')
          .margin({
            top:20
          })
          .backgroundColor(Color.Pink)
          //設(shè)置onclick回調(diào),并調(diào)用異步函數(shù)apply()
          .onClick(()=>{
            this.apply()
          })

      }
      .width('100%')
    }
    .height('100%')
  }
}

......

至此,本期的Demo完成了。

真機(jī)&模擬機(jī)調(diào)試

Demo完成之后,我們需要用模擬器或真機(jī)來(lái)運(yùn)行以查看效果。

事實(shí)上,變量ifAccessible的值應(yīng)該保存在本地的數(shù)據(jù)庫(kù)里,這樣每次重新創(chuàng)建此Demo的頁(yè)面實(shí)例時(shí),才能正確地顯示對(duì)應(yīng)圖像,讀者們可以自行修復(fù)這個(gè)bug。

當(dāng)然,我們也可以打開(kāi)日志欄,通過(guò)日志信息觀察功能模塊的運(yùn)行。打開(kāi)編輯器下方的Hilog,勾選'show only js log',并在標(biāo)簽篩選欄中輸入0FEFE,過(guò)濾后的日志信息如下。

文章相關(guān)附件可以點(diǎn)擊下面的原文鏈接前往下載:

https://ost.51cto.com/resource/3052

想了解更多關(guān)于開(kāi)源的內(nèi)容,請(qǐng)?jiān)L問(wèn):

51CTO 開(kāi)源基礎(chǔ)軟件社區(qū)

https://ost.51cto.com

責(zé)任編輯:jianghua 來(lái)源: 51CTO 開(kāi)源基礎(chǔ)軟件社區(qū)
相關(guān)推薦

2024-07-09 08:48:38

2013-12-10 11:07:06

OpenStack面向用戶

2011-05-04 17:00:54

2018-04-02 10:54:56

2009-04-09 09:16:19

微軟失誤緊急聲明

2021-09-15 23:28:20

開(kāi)源項(xiàng)目Jetbrains

2013-10-30 10:47:32

2011-05-03 10:37:51

亞馬遜網(wǎng)絡(luò)托管

2010-11-29 15:39:28

2015-07-28 10:26:03

Windows 10自動(dòng)更新

2013-07-05 13:33:37

安全補(bǔ)丁

2009-04-14 08:48:37

微軟IE8瀏覽器

2010-03-04 09:45:52

2013-04-22 09:41:02

垃圾短信

2022-01-19 10:34:46

數(shù)據(jù)泄露網(wǎng)絡(luò)欺詐

2013-03-19 10:15:43

Windows 7

2010-02-23 09:55:52

Windows 7主題

2020-07-27 07:41:23

Linux重定向數(shù)據(jù)流

2018-06-08 18:00:22

數(shù)據(jù)安全數(shù)據(jù)庫(kù)安全昂楷科技

2020-10-26 15:10:19

安全漏洞5G
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)