当前位置:   article > 正文

鸿蒙实战开发:【相机和媒体库】_鸿蒙相机开发

鸿蒙相机开发

介绍

在ArkTS中调用相机拍照和录像,以及如何使用媒体库接口进行媒体文件的增、删、改、查操作。本示例用到了

  • 权限管理能力
  • 相机模块能力接口
  • 图片处理接口
  • 音视频相关媒体业务能力接口
  • 媒体库管理接口
  • 设备信息能力接口
  • 文件存储管理能力接口
  • 弹窗能力接口

效果预览

首页
main

使用说明

1.启动应用,在权限弹窗中授权后返回应用,首页显示当前设备的相册信息,首页监听相册变化会刷新相册列表。

2.点击  +  按钮,弹出相机、录音、文本文件三个图标。

3.安装相机应用[Camera]应用后,点击相机图标,进入相机界面,默认是拍照模式,点击底部拍照按钮可以拍照,拍照完成会在底部左侧显示照片预览图。点击录像切换到录像模式,点击底部按钮开始录像,点击结束按钮结束录像,结束录像后底部左侧显示视频图标。点击系统Back键或界面顶部返回按钮返回首页。

4.点击录音图标进入录音界面,点击右侧开始按钮开始录音,按钮变为暂停按钮,点击可以暂停和继续录音,点击左侧结束按钮结束录音返回首页。

5.点击文本图标进入文本编辑界面,输入文本内容后点击Save按钮,会创建并写入文本文件,完成后返回首页。

6.点击相册进入文件列表界面,展示相册内的文件,列表中有删除重命名按钮,点击可以删除文件和重命名文件。

7.安装视频播放[VideoPlayer]应用后,点击视频文件可以调起视频播放界面播放该视频。

相关概念

媒体库管理:媒体库管理提供接口对公共媒体资源文件进行管理,包括文件的增、删、改、查等。 相机:相机模块支持相机相关基础功能的开发,主要包括预览、拍照、录像等。

工程目录

entry/src/main/ets/
|---MainAbility
|   |---MainAbility.ts                      // 主程序入口,应用启动时获取相应权限
|---pages
|   |---index.ets                           // 首页
|   |---AlbumPage.ets                       // 相册页面
|   |---CameraPage.ets                      // 相机页面
|   |---RecordPage.ets                      // 录音页面
|   |---DocumentPage.ets                    // 存储文件页面
|---model                                  
|   |---CameraService.ts                    // 相机模块(拍照录像模式)
|   |---DateTimeUtil.ts                     // 日期工具包
|   |---MediaUtils.ts                       // 媒体工具模块
|   |---RecordModel.ts                      // 录音模块(底层能力实现)
|   |---TimeUtils.ts                        // 时间工具包
|---view                                    
|   |---BasicDataSource.ets                 // 初始化媒体服务数组
|   |---MediaItem.ets                       // 定义具体的某一媒体模块页面 
|   |---MediaView.ets                       // 媒体模块的前置模块(判断是否有展示的媒体内容)
|   |---RenameDialog.ets                    // 重命名文件模块 
|   |---TitleBar.ets                        // 标题栏                                                           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

具体实现

  • 布局原理:定义@ObjectLink 装饰的数组变量album存放资源文件,使用list()组件中ListItem()循环数组展示,加号Button(),点击后触发 animateTo({ duration: 500, curve: Curve.Ease })控制动画展示,[源码参考]。
/*

 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */



import mediaLibrary from '@ohos.multimedia.mediaLibrary';

import common from '@ohos.app.ability.common';

import Want from '@ohos.app.ability.Want';

import router from '@ohos.router';

import TitleBar from '../view/TitleBar';

import MediaUtils from '../model/MediaUtils';

import { MediaView } from '../view/MediaView';

import Logger from '../model/Logger';



@Observed

export default class Album {

  constructor(public albumName: string, public count: number, public mediaType?: mediaLibrary.MediaType) {

    this.albumName = albumName;

    this.count = count;

    this.mediaType = mediaType;

  }

}



@Entry

@Component

struct Index {

  private mediaUtils: MediaUtils = MediaUtils.getInstance(getContext(this))

  @State albums: Array<Album> = []

  @State selectIndex: number = 0

  @State operateVisible: boolean = false



  async onPageShow() {

    this.albums = [];

    this.albums = await this.mediaUtils.getAlbums();

  }



  @Builder OperateBtn(src, zIndex, translate, handleClick) {

    Button() {

      Image(src)

        .width('70%')

        .height('70%')

    }

    .type(ButtonType.Circle)

    .width('40%')

    .height('40%')

    .backgroundColor('#0D9FFB')

    .zIndex(zIndex)

    .translate({ x: translate.x, y: translate.y })

    .transition({ type: TransitionType.Insert, translate: { x: 0, y: 0 } })

    .transition({ type: TransitionType.Delete, opacity: 0 })

    .onClick(handleClick)

  }



  build() {

    Stack({ alignContent: Alignment.BottomEnd }) {

      Column() {

        TitleBar()

        List() {

          ForEach(this.albums, (item: Album, index) => {

            ListItem() {

              MediaView({ album: item })

                .id(`mediaType${index}`)

            }

          }, item => item.albumName)

        }

        .divider({ strokeWidth: 1, color: Color.Gray, startMargin: 16, endMargin: 16 })

        .layoutWeight(1)

      }

      .width('100%')

      .height('100%')



      Stack({ alignContent: Alignment.Center }) {

        Button() {

          Image($r('app.media.add'))

            .width('100%')

            .height('100%')

        }

        .width(60)

        .height(60)

        .padding(10)

        .id('addBtn')

        .type(ButtonType.Circle)

        .backgroundColor('#0D9FFB')

        .onClick(() => {

          animateTo({ duration: 500, curve: Curve.Ease }, () => {

            this.operateVisible = !this.operateVisible

          })

        })



        Button() {

          Image($r('app.media.icon_camera'))

            .id('camera')

            .width('100%')

            .height('100%')

        }

        .width(60)

        .height(60)

        .padding(10)

        .type(ButtonType.Circle)

        .backgroundColor('#0D9FFB')

        .translate({ x: 0, y: -80 })

        .visibility(this.operateVisible ? Visibility.Visible : Visibility.None)

        .onClick(() => {

          this.operateVisible = !this.operateVisible;

          let context: common.UIAbilityContext | undefined = AppStorage.Get('context');

          let want: Want = {

            bundleName: "com.samples.camera_page",

            abilityName: "EntryAbility",

          };

          context && context.startAbility(want,  (err) => {

            if (err.code) {

              Logger.error('StartAbility', `Failed to startAbility. Code: ${err.code}, message: ${err.message}`);

            }

          });

        })



        Button() {

          Image($r('app.media.icon_record'))

            .id('record')

            .width('100%')

            .height('100%')

        }

        .width(60)

        .height(60)

        .padding(10)

        .type(ButtonType.Circle)

        .backgroundColor('#0D9FFB')

        .translate({ x: -80, y: 0 })

        .visibility(this.operateVisible ? Visibility.Visible : Visibility.None)

        .onClick(() => {

          this.operateVisible = !this.operateVisible

          router.push({ url: 'pages/RecordPage' })

        })



        Button() {

          Image($r('app.media.icon_document'))

            .width('100%')

            .height('100%')

        }

        .width(60)

        .height(60)

        .padding(10)

        .id('document')

        .type(ButtonType.Circle)

        .backgroundColor('#0D9FFB')

        .translate({ x: 0, y: 80 })

        .visibility(this.operateVisible ? Visibility.Visible : Visibility.None)

        .onClick(() => {

          this.operateVisible = !this.operateVisible

          router.pushUrl({ url: 'pages/DocumentPage' })

        })

      }

      .width(180)

      .height(220)

      .margin({ right: 40, bottom: 120 })

    }

    .width('100%')

    .height('100%')

  }



  aboutToDisappear() {

    this.mediaUtils.offDateChange()

  }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 获取资源文件:通过引入媒体库实例(入口)接口@ohos.multimedia.medialibrary,例如通过this.getFileAssetsFromType(mediaLibrary.MediaType.FILE)获取FILE类型的文件资源,并通过albums.push()添加至album数组中。
  • 展示系统资源文件:当album内的值被修改时,只会让用 @ObjectLink 装饰的变量album所在的组件被刷新,当前组件不会刷新。
  • 录音功能:通过引入音视频接口@ohos.multimedia.media,例如通过media.createAudioRecorder()创建音频录制的实例来控制音频的录制,通过this.audioRecorder.on(‘prepare’, () => {this.audioRecorder.start()})异步方式开始音频录制,[源码参考]
/*

 * Copyright (c) 2022 Huawei Device Co., Ltd.

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */

import media from '@ohos.multimedia.media'

import Logger from '../model/Logger'



let audioConfig = {

  audioSourceType: 1,

  audioEncoder: 3,

  audioEncodeBitRate: 22050,

  audioSampleRate: 22050,

  numberOfChannels: 2,

  format: 6,

  uri: ''

}



export default class RecordModel {

  private tag: string = 'RecordModel'

  private audioRecorder: media.AudioRecorder = undefined



  initAudioRecorder(handleStateChange: () => void) {

    this.release();

    this.audioRecorder = media.createAudioRecorder()

    Logger.info(this.tag, 'create audioRecorder success')

    this.audioRecorder.on('prepare', () => {

      Logger.info(this.tag, 'setCallback  prepare case callback is called')

      this.audioRecorder.start()

    })

    this.audioRecorder.on('start', () => {

      Logger.info(this.tag, 'setCallback start case callback is called')

      handleStateChange()

    })

    this.audioRecorder.on('stop', () => {

      Logger.info(this.tag, 'audioRecorder stop called')

      this.audioRecorder.release()

    })

    this.audioRecorder.on('pause', () => {

      Logger.info(this.tag, 'audioRecorder pause finish')

      handleStateChange()

    })

    this.audioRecorder.on('resume', () => {

      Logger.info(this.tag, 'audioRecorder resume finish')

      handleStateChange()

    })

  }



  release() {

    if (typeof (this.audioRecorder) !== `undefined`) {

      Logger.info(this.tag, 'audioRecorder  release')

      this.audioRecorder.release()

      this.audioRecorder = undefined

    }

  }



  startRecorder(pathName: string) {

    Logger.info(this.tag, `startRecorder, pathName = ${pathName}`)

    if (typeof (this.audioRecorder) !== 'undefined') {

      Logger.info(this.tag, 'start prepare')

      audioConfig.uri = pathName

      this.audioRecorder.prepare(audioConfig)

    } else {

      Logger.error(this.tag, 'case failed, audioRecorder is null')

    }

  }



  pause() {

    Logger.info(this.tag, 'audioRecorder pause called')

    if (typeof (this.audioRecorder) !== `undefined`) {

      this.audioRecorder.pause()

    }

  }



  resume() {

    Logger.info(this.tag, 'audioRecorder resume called')

    if (typeof (this.audioRecorder) !== `undefined`) {

      this.audioRecorder.resume()

    }

  }



  finish() {

    if (typeof (this.audioRecorder) !== `undefined`) {

      this.audioRecorder.stop()

    }

  }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 拍照录像功能:通过引入相机模块接口@ohos.multimedia.camera,例如通过this.cameraManager.createCaptureSession()创建相机入口的实例来控制拍照和录像,通过this.captureSession.start()开始会话工作,[源码参考]
/*

 * Copyright (c) 2022 Huawei Device Co., Ltd.

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */



import camera from '@ohos.multimedia.camera'

import deviceInfo from '@ohos.deviceInfo'

import fileio from '@ohos.fileio'

import image from '@ohos.multimedia.image'

import media from '@ohos.multimedia.media'

import mediaLibrary from '@ohos.multimedia.mediaLibrary'

import Logger from '../model/Logger'

import MediaUtils from '../model/MediaUtils'



const CameraMode = {

  MODE_PHOTO: 0, // 拍照模式

  MODE_VIDEO: 1 // 录像模式

}



const CameraSize = {

  WIDTH: 1920,

  HEIGHT: 1080

}



export default class CameraService {

  private tag: string = 'CameraService'

  private context: any = undefined

  private mediaUtil: MediaUtils = undefined

  private cameraManager: camera.CameraManager = undefined

  private cameras: Array<camera.CameraDevice> = undefined

  private cameraId: string = ''

  private cameraInput: camera.CameraInput = undefined

  private previewOutput: camera.PreviewOutput = undefined

  private photoOutPut: camera.PhotoOutput = undefined

  private captureSession: camera.CaptureSession = undefined

  private mReceiver: image.ImageReceiver = undefined

  private photoUri: string = ''

  private fileAsset: mediaLibrary.FileAsset = undefined

  private fd: number = -1

  private curMode = CameraMode.MODE_PHOTO

  private videoRecorder: media.VideoRecorder = undefined

  private videoOutput: camera.VideoOutput = undefined

  private handleTakePicture: (photoUri: string) => void = undefined

  private cameraOutputCapability: camera.CameraOutputCapability = undefined

  private videoConfig: any = {

    audioSourceType: 1,

    videoSourceType: 0,

    profile: {

      audioBitrate: 48000,

      audioChannels: 2,

      audioCodec: 'audio/mp4v-es',

      audioSampleRate: 48000,

      durationTime: 1000,

      fileFormat: 'mp4',

      videoBitrate: 48000,

      videoCodec: 'video/mp4v-es',

      videoFrameWidth: 640,

      videoFrameHeight: 480,

      videoFrameRate: 30

    },

    url: '',

    orientationHint: 0,

    location: {

      latitude: 30, longitude: 130

    },

    maxSize: 10000,

    maxDuration: 10000

  }



  constructor(context: any) {

    this.context = context

    this.mediaUtil = MediaUtils.getInstance(context)

    this.mReceiver = image.createImageReceiver(CameraSize.WIDTH, CameraSize.HEIGHT, 4, 8)

    Logger.info(this.tag, 'createImageReceiver')

    this.mReceiver.on('imageArrival', () => {

      Logger.info(this.tag, 'imageArrival')

      this.mReceiver.readNextImage((err, image) => {

        Logger.info(this.tag, 'readNextImage')

        if (err || image === undefined) {

          Logger.error(this.tag, 'failed to get valid image')

          return

        }

        image.getComponent(4, (errMsg, img) => {

          Logger.info(this.tag, 'getComponent')

          if (errMsg || img === undefined) {

            Logger.info(this.tag, 'failed to get valid buffer')

            return

          }

          let buffer = new ArrayBuffer(4096)

          if (img.byteBuffer) {

            buffer = img.byteBuffer

          } else {

            Logger.error(this.tag, 'img.byteBuffer is undefined')

          }

          this.savePicture(buffer, image)

        })

      })

    })

  }



  async savePicture(buffer: ArrayBuffer, img: image.Image) {

    Logger.info(this.tag, 'savePicture')

    this.fileAsset = await this.mediaUtil.createAndGetUri(mediaLibrary.MediaType.IMAGE)

    this.photoUri = this.fileAsset.uri

    Logger.info(this.tag, `this.photoUri = ${this.photoUri}`)

    this.fd = await this.mediaUtil.getFdPath(this.fileAsset)

    Logger.info(this.tag, `this.fd = ${this.fd}`)

    await fileio.write(this.fd, buffer)

    await this.fileAsset.close(this.fd)

    await img.release()

    Logger.info(this.tag, 'save image done')

    if (this.handleTakePicture) {

      this.handleTakePicture(this.photoUri)

    }

  }



  async initCamera(surfaceId: string) {

    Logger.info(this.tag, 'initCamera')

    await this.releaseCamera()

    Logger.info(this.tag, `deviceInfo.deviceType = ${deviceInfo.deviceType}`)

    if (deviceInfo.deviceType === 'default') {

      this.videoConfig.videoSourceType = 1

    } else {

      this.videoConfig.videoSourceType = 0

    }

    this.cameraManager = await camera.getCameraManager(this.context)

    Logger.info(this.tag, 'getCameraManager')

    this.cameras = await this.cameraManager.getSupportedCameras()

    Logger.info(this.tag, `get cameras ${this.cameras.length}`)

    if (this.cameras.length === 0) {

      Logger.info(this.tag, 'cannot get cameras')

      return

    }



    let cameraDevice = this.cameras[0]

    this.cameraInput = await this.cameraManager.createCameraInput(cameraDevice)

    this.cameraInput.open()

    Logger.info(this.tag, 'createCameraInput')

    this.cameraOutputCapability = await this.cameraManager.getSupportedOutputCapability(cameraDevice)

    let previewProfile = this.cameraOutputCapability.previewProfiles[0]

    this.previewOutput = await this.cameraManager.createPreviewOutput(previewProfile, surfaceId)

    Logger.info(this.tag, 'createPreviewOutput')

    let mSurfaceId = await this.mReceiver.getReceivingSurfaceId()

    let photoProfile = this.cameraOutputCapability.photoProfiles[0]

    this.photoOutPut = await this.cameraManager.createPhotoOutput(photoProfile, mSurfaceId)

    this.captureSession = await this.cameraManager.createCaptureSession()

    Logger.info(this.tag, 'createCaptureSession')

    await this.captureSession.beginConfig()

    Logger.info(this.tag, 'beginConfig')

    await this.captureSession.addInput(this.cameraInput)

    await this.captureSession.addOutput(this.previewOutput)

    await this.captureSession.addOutput(this.photoOutPut)

    await this.captureSession.commitConfig()

    await this.captureSession.start()

    Logger.info(this.tag, 'captureSession start')

  }



  setTakePictureCallback(callback) {

    this.handleTakePicture = callback

  }



  async takePicture() {

    Logger.info(this.tag, 'takePicture')

    if (this.curMode === CameraMode.MODE_VIDEO) {

      this.curMode = CameraMode.MODE_PHOTO

    }

    let photoSettings = {

      rotation: camera.ImageRotation.ROTATION_0,

      quality: camera.QualityLevel.QUALITY_LEVEL_MEDIUM,

      location: { // 位置信息,经纬度

        latitude: 12.9698,

        longitude: 77.7500,

        altitude: 1000

      },

      mirror: false

    }

    await this.photoOutPut.capture(photoSettings)

    Logger.info(this.tag, 'takePicture done')

    AppStorage.Set('isRefresh', true)

  }



  async startVideo() {

    Logger.info(this.tag, 'startVideo begin')

    await this.captureSession.stop()

    await this.captureSession.beginConfig()

    if (this.curMode === CameraMode.MODE_PHOTO) {

      this.curMode = CameraMode.MODE_VIDEO

      if (this.photoOutPut) {

        await this.captureSession.removeOutput(this.photoOutPut)

        this.photoOutPut.release()

      }

    } else {

      if (this.videoOutput) {

        await this.captureSession.removeOutput(this.videoOutput)

      }

    }

    if (this.videoOutput) {

      await this.captureSession.removeOutput(this.videoOutput)

      await this.videoOutput.release()

    }

    this.fileAsset = await this.mediaUtil.createAndGetUri(mediaLibrary.MediaType.VIDEO)

    this.fd = await this.mediaUtil.getFdPath(this.fileAsset)

    this.videoRecorder = await media.createVideoRecorder()

    this.videoConfig.url = `fd://${this.fd}`

    await this.videoRecorder.prepare(this.videoConfig)

    let videoId = await this.videoRecorder.getInputSurface()

    let videoProfile = this.cameraOutputCapability.videoProfiles[0];

    this.videoOutput = await this.cameraManager.createVideoOutput(videoProfile, videoId)

    await this.captureSession.addOutput(this.videoOutput)

    await this.captureSession.commitConfig()

    await this.captureSession.start()

    await this.videoOutput.start()

    await this.videoRecorder.start()

    Logger.info(this.tag, 'startVideo end')

  }



  async stopVideo() {

    Logger.info(this.tag, 'stopVideo called')

    await this.videoRecorder.stop()

    await this.videoOutput.stop()

    await this.videoRecorder.release()

    await this.fileAsset.close(this.fd)

  }



  async releaseCamera() {

    Logger.info(this.tag, 'releaseCamera')

    if (this.cameraInput) {

      await this.cameraInput.close()

    }

    if (this.previewOutput) {

      await this.previewOutput.release()

    }

    if (this.photoOutPut) {

      await this.photoOutPut.release()

    }

    if (this.videoOutput) {

      await this.videoOutput.release()

    }

    if (this.captureSession) {

      await this.captureSession.release()

    }

  }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505

鸿蒙NEXT开发知识已更新gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md可参考学习更多

image.png

约束与限制

1.rk3568底层录像功能有问题,暂不支持录像功能,当前拍照功能仅支持部分机型。

2.本示例仅支持标准系统上运行。

3.本示例为Stage模型,已适配API version 9版本SDK,版本号:3.2.11.9;

4.本示例需要使用DevEco Studio 3.1 Beta2 (Build Version: 3.1.0.400, built on April 7, 2023)及以上版本才可编译运行。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/974206?site
推荐阅读
相关标签
  

闽ICP备14008679号