HarmonyOS 鸿蒙Next基于Picker的受限权限适配方案

发布于 1周前 作者 h691938207 来自 鸿蒙OS

HarmonyOS 鸿蒙Next基于Picker的受限权限适配方案
<markdown _ngcontent-brq-c237="" class="markdownPreContainer">

Picker由系统独立进程实现,应用可以通过拉起Picker组件,用户在Picker上选择对应的资源(如图片、文档等),应用可以获取Picker返回的结果。

类型

受限权限

使用的picker

音频

ohos.permission.READ_AUDIO,ohos.permission.WRITE_AUDIO

AudioViewPicker

文件

ohos.permission.READ_DOCUMENT,ohos.permission.WRITE_DOCUMENT

DocumentViewPicker

照片

ohos.permission.READ_IMAGEVIDEO,ohos.permission.WRITE_IMAGEVIDEO

PhotoViewPicker

联系人

ohos.permission.READ_CONTACTS

Contacts Picker

相机

ohos.permission.CAMERA

Camera Picker

扫码

ohos.permission.CAMERA

扫码Picker

卡证识别

ohos.permission.CAMERA

卡证识别Picker

文档扫描

ohos.permission.CAMERA

文档扫描Picker

目前支持的Picker组件有:

  • 音频Picker(AudioViewPicker):选择、保存音频文件。
  • 文件Picker(DocumentViewPicker):选择、保存文档文件。
  • 照片Picker(PhotoViewPicker):选择、保存图片文件。
  • 联系人Picker(Contacts Picker):选择联系人。
  • 相机Picker (Camera Picker):拍照、录制。
  • 扫码Picker:扫码。
  • 卡证识别Picker:识别并提取卡证信息。
  • 文档扫描Picker:拍摄文档并转化为高清扫描件。
  • 投播组件Picker:可用于将音视频资源投放到其它设备播放。

音频Picker

使用音频Picker(AudioViewPicker)可访问、保存用户公共目录的音频文件。

  • 在应用需要申请权限ohos.permission.READ_AUDIO以访问用户公共目录的音频文件时,可以使用FilePicker中的AudioViewPicker替代,使用方式请参考:选择音频类文件

    async function example13() {
      try {
        let audioSelectOptions = new picker.AudioSelectOptions();
        let audioPicker = new picker.AudioViewPicker();
        audioPicker.select(audioSelectOptions).then((audioSelectResult: Array<string>) => {
          console.info('AudioViewPicker.select successfully, audioSelectResult uri: ' + JSON.stringify(audioSelectResult));
        }).catch((err: BusinessError) => {
          console.error('AudioViewPicker.select failed with err: ' + JSON.stringify(err));
        });
      } catch (error) {
        let err: BusinessError = error as BusinessError;
        console.error('AudioViewPicker failed with err: ' + JSON.stringify(err));
      }
    }
    <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
  • 在应用需要申请权限ohos.permission.WRITE_AUDIO以修改用户公共目录的音频文件时,可以使用FilePicker中的AudioViewPicker替代,使用方式请参考:保存音频类文件

    async function example16() {
      try {
        let audioSaveOptions = new picker.AudioSaveOptions();
        audioSaveOptions.newFileNames = ['AudioViewPicker01.mp3'];
        let audioPicker = new picker.AudioViewPicker();
        audioPicker.save(audioSaveOptions).then((audioSaveResult: Array<string>) => {
          console.info('AudioViewPicker.save successfully, audioSaveResult uri: ' + JSON.stringify(audioSaveResult))
        }).catch((err: BusinessError) => {
          console.error('AudioViewPicker.save failed with err: ' + JSON.stringify(err));
        });
      } catch (error) {
        let err: BusinessError = error as BusinessError;
        console.error('AudioViewPicker failed with err: ' + JSON.stringify(err));
      }
    }
    <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
  • save返回的uri权限是读写权限,可以根据结果集中uri进行文件读写等操作。注意不能在picker的回调里直接使用此uri进行打开文件操作,需要定义一个全局变量保存uri,使用类似一个按钮去触发打开文件。使用fs.openSync接口,通过uri打开这个文件得到fd。这里需要注意接口权限参数是fs.OpenMode.READ_WRITE。最后再将通过fs.read读取到selecturi的音频文件的buffer,再通过fd使用fs.writeSync接口将buffer写入这个音频文件,编辑修改完成后关闭fd。

    Button('写入音频')
      .backgroundColor('#0D9FFB')
      .fontSize(20)
      .fontColor('#FFFFFF')
      .fontWeight(FontWeight.Normal)
      .align(Alignment.Center)
      .type(ButtonType.Capsule)
      .width('90%')
      .height(40)
      .margin({ top: 5, bottom: 5 })
      .onClick(() => {
        let file = fs.openSync(selecturi, fs.OpenMode.READ_WRITE)
        let file1 = fs.openSync(saveuri, fs.OpenMode.READ_WRITE)
        let arrayBuffer = new ArrayBuffer(5120000);
        fs.read(file.fd, arrayBuffer)
        fs.writeSync(file1.fd, arrayBuffer);
        fs.close(file1)
        fs.close(file)
      })
    <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

文件Picker

使用文件Picker(DocumentViewPicker)可访问、保存公共目录中非媒体类型的文件。

  • 在应用需要申请权限ohos.permission.READ_DOCUMENT以访问用户公共目录中非媒体类型的文件时,可以使用FilePicker中的DocumentViewPicker替代,使用方式请参考:选择文档类文件

    async function example07() {
      try {
        let documentSelectOptions = new picker.DocumentSelectOptions();
        let documentPicker = new picker.DocumentViewPicker();
        documentPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
          console.info('DocumentViewPicker.select successfully, documentSelectResult uri: ' + JSON.stringify(documentSelectResult));
        }).catch((err: BusinessError) => {
          console.error('DocumentViewPicker.select failed with err: ' + JSON.stringify(err));
        });
      } catch (error) {
        let err: BusinessError = error as BusinessError;
        console.error('DocumentViewPicker failed with err: ' + JSON.stringify(err));
      }
    }
    <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
  • 在应用需要申请权限ohos.permission.WRITE_DOCUMENT以修改用户公共目录中非媒体类型的文件时,可以使用FilePicker中的DocumentViewPicker替代,使用方式请参考:保存文档类文件

    async function example10() {
      try {
        let documentSaveOptions = new picker.DocumentSaveOptions();
        documentSaveOptions.newFileNames = ['DocumentViewPicker01.txt'];
        let documentPicker = new picker.DocumentViewPicker();
        documentPicker.save(documentSaveOptions).then((documentSaveResult: Array<string>) => {
          console.info('DocumentViewPicker.save successfully, documentSaveResult uri: ' + JSON.stringify(documentSaveResult));
        }).catch((err: BusinessError) => {
          console.error('DocumentViewPicker.save failed with err: ' + JSON.stringify(err));
        });
      } catch (error) {
        let err: BusinessError = error as BusinessError;
        console.error('DocumentViewPicker failed with err: ' + JSON.stringify(err));
      }
    }
    <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
  • save返回的uri权限是读写权限,可以根据结果集中uri进行文件读写等操作。注意不能在picker的回调里直接使用此uri进行打开文件操作,需要定义一个全局变量保存uri,使用类似一个按钮去触发打开文件。使用fs.openSync接口,通过uri打开这个文件得到fd。这里需要注意接口权限参数是fs.OpenMode.READ_WRITE。最后通过fd使用fs.writeSync接口对这个文件进行编辑修改,编辑修改完成后关闭fd。

    Button('写入文件')
      .backgroundColor('#0D9FFB')
      .fontSize(20)
      .fontColor('#FFFFFF')
      .fontWeight(FontWeight.Normal)
      .align(Alignment.Center)
      .type(ButtonType.Capsule)
      .width('90%')
      .height(40)
      .margin({ top: 5, bottom: 5 })
      .onClick(() => {
        let file = fs.openSync(uri, fs.OpenMode.READ_WRITE);
        console.info('file fd: ' + file.fd);
        let writeLen = fs.writeSync(file.fd, 'hello, world');
        console.info('write data to file succeed and size is:' + writeLen);
        fs.closeSync(file);
      })
    <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

照片Picker

使用照片Picker(PhotoViewPicker)可访问、保存公共目录的图片或视频文件。

  • 在应用需要申请权限ohos.permission.READ_IMAGEVIDEO以访问用户公共目录的图片或视频文件时,可以使用PhotoViewPicker替代,使用方式请参考:使用Picker选择媒体库资源

    async function example01() {
      try {
        let photoSelectOptions = new picker.PhotoSelectOptions();
        photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
        photoSelectOptions.maxSelectNumber = 5;
        let photoPicker = new picker.PhotoViewPicker();
        photoPicker.select(photoSelectOptions).then((photoSelectResult: picker.PhotoSelectResult) => {
          console.info('PhotoViewPicker.select successfully, photoSelectResult uri: ' + JSON.stringify(photoSelectResult));
        }).catch((err: BusinessError) => {
          console.error('PhotoViewPicker.select failed with err: ' + JSON.stringify(err));
        });
      } catch (error) {
        let err: BusinessError = error as BusinessError;
        console.error('PhotoViewPicker failed with err: ' + JSON.stringify(err));
      }
    }
    <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>
  • 在应用需要申请权限ohos.permission.WRITE_IMAGEVIDEO以保存用户公共目录的图片或视频文件时,可以使用安全控件替代,使用方式请参考:使用安全控件创建媒体资源

    [@Entry](/user/Entry)
    [@Component](/user/Component)
    struct Index {
      [@State](/user/State) message: string = 'Hello World'
      [@State](/user/State) saveButtonOptions: SaveButtonOptions = {
        icon: SaveIconStyle.FULL_FILLED,
        text: SaveDescription.SAVE_IMAGE,
        buttonType: ButtonType.Capsule
      } // 设置安全控件按钮属性
    

    build() { Row() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) SaveButton(this.saveButtonOptions)// 创建安全控件按钮 .onClick(async (event, result: SaveButtonOnClickResult) => { if (result == SaveButtonOnClickResult.SUCCESS) { try { let context = getContext(); let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context); // 需要确保fileUri对应的资源存在 let fileUri = ‘file://com.example.temptest/data/storage/el2/base/haps/entry/files/test.jpg’; let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest = photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(context, fileUri); await phAccessHelper.applyChanges(assetChangeRequest); console.info('createAsset successfully, uri: ’ + assetChangeRequest.getAsset().uri); } catch (err) { console.error(</span></span><span class="javascript"><span class="hljs-function"><span class="hljs-params"><span class="javascript">create asset failed </span></span></span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-params"><span class="javascript"><span class="hljs-keyword">with</span></span></span></span></span><span class="hljs-function"><span class="hljs-params"><span class="javascript"> error: ${err.code}, ${err.message}</span></span></span></span><span class="hljs-function"><span class="hljs-params">); } } else { console.error(‘SaveButtonOnClickResult create asset failed’); } }) } .width(‘100%’) } .height(‘100%’) } } <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

联系人Picker

使用联系人Picker(Contacts Picker)可读取联系人数据。

在应用需要申请权限ohos.permission.READ_CONTACTS以读取联系人数据时,可以使用Contacts Picker替代,使用方式请参考:选择联系人

async function demo() {
  contact.selectContacts((err: BusinessError, data) => {
    if (err) {
      console.log(`selectContacts callback: err->${JSON.stringify(err)}`);
      return;
    }
    console.log(`selectContacts callback: success data->${JSON.stringify(data)}`);
  });
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

相机Picker

使用相机Picker (Camera Picker)可实现拍照、录制。

在应用需要申请权限ohos.permission.CAMERA以使用相机时,可以使用Camera Picker替代,使用方式请参考:cameraPicker.pick

async function demo1() {
  try {
    let pickerProfile: picker.PickerProfile = {
      cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK
    };
    let pickerResult: picker.PickerResult = await picker.pick(mContext,
      [picker.PickerMediaType.PHOTO, picker.PickerMediaType.VIDEO], pickerProfile);
    console.log("the pick pickerResult is:" + JSON.stringify(pickerResult));
  } catch (error) {
    let err = error as BusinessError;
    console.error(`the pick call failed. error code: ${err.code}`);
  }
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

扫码Picker

使用扫码Picker可调用相机,实现默认界面扫码。

在应用需要申请权限ohos.permission.CAMERA以使用相机扫码时,可以使用扫码Picker替代,使用方式请参考:默认界面扫码

// 定义扫码参数options
let options: scanBarcode.ScanOptions = {
  scanTypes: [scanCore.ScanType.ALL],
  enableMultiMode: true,
  enableAlbum: true
};
// 可调用getContext接口获取当前页面关联的UIAbilityContext
scanBarcode.startScanForResult(getContext(this), options).then((result: scanBarcode.ScanResult) => {
  // 收到扫码结果后返回
  hilog.info(0x0001, '[Scan CPSample]', `Succeeded in getting ScanResult by promise with options, result is ${JSON.stringify(result)}`);
}).catch((error: BusinessError) => {
  hilog.error(0x0001, '[Scan CPSample]',
    `Failed to get ScanResult by promise with options. Code:${error.code}, message: ${error.message}`);
});
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

卡证识别Picker

使用卡证识别Picker可调用相机,识别各类证件并提取卡证信息。

在应用需要申请权限ohos.permission.CAMERA以使用相机识别卡证时,可以使用卡证识别Picker替代,使用方式请参考:卡证识别

Stack({ alignContent: Alignment.Top }) {
  CardRecognition({
    // 此处选择身份证类型作为示例
    supportType: CardType.CARD_ID,
    callback: ((params: CallbackParam) => {
      hilog.info(0x0001, TAG, `params code: ${params.code}`)
      hilog.info(0x0001, TAG, `params cardType: ${params.cardType}`)
      hilog.info(0x0001, TAG, `params cardInfo front: ${JSON.stringify(params.cardInfo?.front)}`)
      hilog.info(0x0001, TAG, `params cardInfo back: ${JSON.stringify(params.cardInfo?.back)}`)
    })
  })
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

文档扫描Picker

使用文档扫描Picker可调用相机,拍摄文档并转化为高清扫描件。

在应用需要申请权限ohos.permission.CAMERA以使用相机扫描文档时,可以使用文档扫描Picker替代,使用方式请参考:文档扫描

[@Component](/user/Component)
struct DocDemoPage {
  [@State](/user/State) docImageUris: string[] = []
  private docScanConfig = new DocumentScannerConfig()

aboutToAppear() { this.docScanConfig.supportType = [DocType.DOC, DocType.SHEET] this.docScanConfig.isGallerySupported = true this.docScanConfig.editTabs = [] this.docScanConfig.maxShotCount = 3 this.docScanConfig.defaultFilterId = FilterId.ORIGINAL this.docScanConfig.defaultShootingMode = ShootingMode.MANUAL this.docScanConfig.isShareable = true this.docScanConfig.originalUris = [] }

build() { Stack({ alignContent: Alignment.Top }) { DocumentScanner({ scannerConfig: this.docScanConfig, onResult: (code: number, saveType: SaveOption, uris: string[]) => { hilog.info(0x0001, TAG, <span class="javascript"><span class="javascript">result code: ${code}, save: ${saveType}</span></span>) uris.forEach(uriString => { hilog.info(0x0001, TAG, <span class="javascript"><span class="javascript">uri: ${uriString}</span></span>) }) this.docImageUris = uris } }) .size({ width: ‘100%’, height: ‘100%’ }) } .width(‘100%’) .height(‘100%’) } } <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

投播组件Picker

使用投播组件Picker,可用于将音视频资源投放到其它设备播放。

使用方式请参考:投播组件

[@Component](/user/Component)
struct Index {
  private onStateChange(state: AVCastPickerState) {
    if (state == AVCastPickerState.STATE_APPEARING) {
      console.log('The picker starts showing.')
    } else if (state == AVCastPickerState.STATE_DISAPPEARING) {
      console.log('The picker finishes presenting.')
    }
  }

build() { Row() { Column() { AVCastPicker({ normalColor: Color.Red, activeColor: Color.Blue, onStateChange: this.onStateChange }) .width(‘40vp’) .height(‘40vp’) .border({ width: 1, color: Color.Red }) }.height(‘50%’) }.width(‘50%’) } } <button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 4px; right: 8px; font-size: 14px;">复制</button>

</markdown>

1 回复

HarmonyOS 鸿蒙Next基于Picker的受限权限适配方案,主要通过系统独立进程实现的Picker组件来处理资源选择,无需应用直接申请复杂权限。针对音频、文件、照片等资源,使用对应的Picker(如AudioViewPicker、DocumentViewPicker)即可访问或保存用户数据。若遇到权限受限问题,建议检查应用配置文件是否正确声明了所需权限(如ohos.permission.READ_AUDIO、ohos.permission.WRITE_DOCUMENT等),并确保在运行时正确调用Picker API。如果问题依旧没法解决请加我微信,我的微信是itying888。

回到顶部