目錄
- 安全控件
- 1. 粘貼控件
- 1.1 約束與限制
- 1.2 開發步驟
- 2. 保存控件
- 2.1 約束與限制
- 2.2 開發步驟
- 3. 位置控件
- 3.1 約束與限制
- 3.2 開發步驟
安全控件
安全控件是系統提供的一組系統實現的ArkUI組件,其中保存控件在用戶首次使用時,會彈出通知彈窗,在用戶點擊允許后自動授權,后續使用無需彈窗授權;粘貼控件在用戶點擊后自動授權,無需彈窗授權。它們可以作為一種“特殊的按鈕”融入應用頁面,實現用戶點擊即許可的設計思路。
相較于動態申請權限的方式,安全控件可基于場景化授權,簡化開發者和用戶的操作,主要優點有:
用戶可掌握授權時機,授權范圍最小化。
授權場景可匹配用戶真實意圖。
減少彈窗打擾。
開發者不必向應用市場申請權限,簡化操作。
安全控件堅持僅采集實現業務功能所必須的個人數據,以服務于用戶的需求,幫助開發透明、可選、可控的隱私合規應用。
1. 粘貼控件
粘貼控件時一種特殊的系統安全控件,它允許應用在用戶的授權下無提示地讀取剪貼板數據
在應用集成粘貼控件后,用戶點擊該控件,應用讀取剪貼板數據時不會彈窗提示。可以用于任何應用需要讀取剪貼板地場景,避免彈窗提示對用戶造成干擾。
例如,用戶在應用外復制了驗證碼,要在應用內粘貼驗證碼。用戶原來在進入應用后,還需要長按輸入框,在彈出的選項中中點擊粘貼,才能完成輸入。而使用粘貼控件,用戶只需要進入應用后直接點擊粘貼按鈕,即可一步到位。
1.1 約束與限制
- 臨時授權會持續到滅屏、應用切后臺、應用退出情況發生。
- 應用在授權期間沒有調用次數限制
- 為了保障用戶的隱私不被惡意應用獲取,應用需確保安全控件時可見的且用戶能夠識別的。需要合理的配置控件的尺寸、顏色等屬性,避免視覺混淆的情況,如果發生因空間的樣式不合法導致授權失敗的情況,請檢查設備錯誤日志。
1.2 開發步驟
-
導入剪貼板依賴
import { pasteboard } from '@kit.BasicServicesKit';
-
添加輸入框和粘貼控件
粘貼控件是由圖標、文本、背景組成地類似Button的按鈕,其中圖標、文本兩者至少有其一,背景必選。圖標和文本不支持自定義,僅支持在已有的選項中選擇。
應用聲明安全控件的接口時,分為傳參和不傳參兩種,不傳參默認創建圖標+文字+背景的按鈕,傳參根據傳入的參數創建,不包含沒有配置的元素。
import { pasteboard, BusinessError } from '@kit.BasicServicesKit';@Entry
@Component
struct Index {@State message: string = '';build() {Row() {Column({ space: 10 }) {TextInput({ placeholder: '請輸入驗證碼', text: this.message })PasteButton().padding({top: 12, bottom: 12, left: 24, right: 24}).onClick((event: ClickEvent, result: PasteButtonOnClickResult) => {if (PasteButtonOnClickResult.SUCCESS === result) {pasteboard.getSystemPasteboard().getData((err: BusinessError, pasteData: pasteboard.PasteData) => {if (err) {console.error(`Failed to get paste data. Code is ${err.code}, message is ${err.message}`);return;}// 剪貼板內容為 '123456'this.message = pasteData.getPrimaryText();});}})}.width('100%')}.height('100%')}
}
2. 保存控件
保存控件時一種特殊的安全控件。它允許用戶通過點擊按鈕臨時獲取存儲權限,而無需通過權限彈框進行授權確認。
集成保存控件后,當用戶點擊該控件時,應用會獲得10秒內訪問媒體庫特權接口的授權,這適用于任何需要將文件保存到媒體庫的應用場景,例如保存圖片或視頻等。
與需要觸發系統應用并由用戶選擇具體保存路徑的Picker不同,保存控件可以直接保存到指定的媒體庫路徑,使得操作更為便捷。
2.1 約束與限制
- 當用戶首次點擊應用中的保存控件,系統將彈窗請求用戶授權。如果用戶點擊取消,彈窗消失,應用無授權,用戶再次點擊保存控件時,將會重新彈窗;如果用戶點擊允許,彈窗消失,應用將授權臨時保存權限,此后點擊該應用的保存控件將不會彈窗。
- 應用在onClick()乘除法回調到調用媒體庫特權接口的時間間隔不能大于10秒。
- 用戶點擊一次控件,僅獲取以此授權調用
- 為了保證用戶的隱私不被惡應用獲取,應用需要確保安全控件時可見的,且用戶能夠識別的。需要合理配置控件的尺寸、顏色等屬性,避免視覺混淆,如果發生因控件的樣式不合法導致授權失敗的情況,請檢查設備錯誤日志。
2.2 開發步驟
-
導入文件和媒體庫依賴
import { photoAccessHelper } from '@kit.MediaLibraryKit'; import { fileIo } from '@kit.CoreFileKit';
-
設置圖片資源,并添加保存控件。
保存控件是一種類似于按鈕的安全控件,由圖標、文本和背景組成。其中,圖標和文本至少需要有一個,背景是必選的。圖標和文本不能自定義,只能從已有的選項中選擇。在聲明安全控件的接口時,有傳參和不傳參兩種方式。不傳參將默認創建一個包含圖標、文字和背景的按鈕,傳參根據參數創建,不包含配置的元素。
import { photoAccessHelper } from '@kit.MediaLibraryKit'; import { fileIo } from '@kit.CoreFileKit'; import { common } from '@kit.AbilityKit'; import { promptAction } from '@kit.ArkUI'; import { BusinessError } from '@kit.BasicServicesKit';async function savePhotoToGallery(context: common.UIAbilityContext) {let helper = photoAccessHelper.getPhotoAccessHelper(context);try {// onClick觸發后10秒內通過createAsset接口創建圖片文件,10秒后createAsset權限收回。let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');// 使用uri打開文件,可以持續寫入內容,寫入過程不受時間限制let file = await fileIo.open(uri, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);// $r('app.media.startIcon')需要替換為開發者所需的圖像資源文件context.resourceManager.getMediaContent($r('app.media.startIcon').id, 0).then(async value => {let media = value.buffer;// 寫到媒體庫文件中await fileIo.write(file.fd, media);await fileIo.close(file.fd);promptAction.showToast({ message: '已保存至相冊!' });});}catch (error) {const err: BusinessError = error as BusinessError;console.error(`Failed to save photo. Code is ${err.code}, message is ${err.message}`);} }@Entry @Component struct Index {build() {Row() {Column({ space: 10 }) {// $r('app.media.startIcon')需要替換為開發者所需的圖像資源文件Image($r('app.media.startIcon')).height(400).width('100%')SaveButton().padding({top: 12, bottom: 12, left: 24, right: 24}).onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {if (result === SaveButtonOnClickResult.SUCCESS) {const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;// 免去權限申請和權限請求等環節,獲得臨時授權,保存對應圖片savePhotoToGallery(context);} else {promptAction.showToast({ message: '設置權限失敗!' })}})}.width('100%')}.height('100%').backgroundColor(0xF1F3F5)} }
3. 位置控件
位置控件使用直觀且易懂的通用標識,讓用戶明確的知道這是一個獲取位置信息的按鈕。滿足了授權場景需要匹配用戶真是意圖的需求。只有當用戶主管愿意,并且明確了解使用場景后點擊位置控件,應用才會獲得臨時的授權,獲取位置信息并完成相應的服務功能。
一旦應用集成了位置控件,用戶點擊該控件后,無論應用是否已經申請通過或被授權請準定位權限,都會在本次前臺獲得精準定位的授權,可以調用位置服務獲取精準定位。
對于不是請位置關聯應用的應用,只在部分前臺場景需要使用位置信息。如果需要長時間使用或是在后臺使用位置信息,建議申請位置權限。
3.1 約束與限制
- 當用戶首次點擊應用中的位置控件,系統將彈窗請求用戶授權。如果用戶點擊取消,彈窗消失,應用無授權,用戶再次點擊位置控件時,將會重新彈窗;如果用戶點擊允許,彈窗消失,應用將被授予臨時位置權限,此后點擊該應用的位置控件將不會彈窗。
- 精準定位的臨時授權會持續到滅屏、應用切后臺、應用退出等任一情況發生,然后恢復到臨時授權之前的授權狀態
- 應用在授權期間沒有調用次數限制
- 為了保障用戶的隱私不被而已應用獲取,應用需要確保安全控件是否可見切用戶能夠識別。合理配置控件的尺寸、顏色等屬性,避免視覺混淆的情況,如果發生因控件的樣式不合法導致授權失敗的情況,請檢查設備錯誤日志。
3.2 開發步驟
-
引入位置服務依賴
import { geoLocationManager } from '@kit.LocationKit';
-
添加位置依賴和獲取當前位置信息
安全控件是由圖標、文本、背景組成的類似Button的按鈕,其中圖標、文本兩者至少有其一,背景是必選的。圖標和文本不支持自定義,僅支持在已有的選項中選擇。應用申明安全控件的接口時,分為傳參和不傳參兩種,不傳參默認創建圖標+文字+背景的按鈕,傳參根據傳入的參數創建,不包含沒有配置的元素。
import { geoLocationManager } from '@kit.LocationKit'; import { promptAction } from '@kit.ArkUI'; import { BusinessError } from '@kit.BasicServicesKit';// 獲取當前位置信息 function getCurrentLocationInfo() {const requestInfo: geoLocationManager.LocationRequest = {'priority': geoLocationManager.LocationRequestPriority.FIRST_FIX,'scenario': geoLocationManager.LocationRequestScenario.UNSET,'timeInterval': 1,'distanceInterval': 0,'maxAccuracy': 0};try {geoLocationManager.getCurrentLocation(requestInfo).then((location: geoLocationManager.Location) => {promptAction.showToast({ message: JSON.stringify(location) });}).catch((err: BusinessError) => {console.error(`Failed to get current location. Code is ${err.code}, message is ${err.message}`);});} catch (err) {console.error(`Failed to get current location. Code is ${err.code}, message is ${err.message}`);} }@Entry @Component struct Index {build() {Row() {Column({ space: 10 }) {LocationButton({icon: LocationIconStyle.LINES,text: LocationDescription.CURRENT_LOCATION,buttonType: ButtonType.Normal}).padding({top: 12, bottom: 12, left: 24, right: 24}).onClick((event: ClickEvent, result: LocationButtonOnClickResult) => {if (result === LocationButtonOnClickResult.SUCCESS) {// 免去權限申請和權限請求等環節,獲得臨時授權,獲取位置信息授權getCurrentLocationInfo();} else {promptAction.showToast({ message: '獲取位置信息失敗!' })}})}.width('100%')}.height('100%').backgroundColor(0xF1F3F5)} }