diff --git a/README.en.md b/README.en.md index cfe900c96221d1f0c9d6f6a78e92b296419b5d19..94a46c51b65153e8421b6204a5dfd18e55475214 100644 --- a/README.en.md +++ b/README.en.md @@ -11,8 +11,8 @@ Based on the Camera Kit, this sample implements a range of core camera functiona How to use: 1. After launching the application and completing authorization, the preview UI is displayed. -2. The buttons from left to right at the top of the screen are as follows: flash setting, delayed shooting mode setting, motion photo mode setting, and single/dual-stage shutter mode setting. (The single-stage shutter mode does not support motion photo shooting.) -3. When switched to video recording mode, the top buttons from left to right are: flash setting and image stabilization mode setting. +2. The buttons from left to right at the top of the screen are as follows: preview frame rate setting, flash setting, delayed shooting mode setting, motion photo mode setting, and single/dual-stage shutter mode setting. (The single-stage shutter mode does not support motion photo shooting.) +3. When switched to video recording mode, the top buttons from left to right are: preview frame rate setting, flash setting and image stabilization mode setting. 4. On the right side, the buttons are grid line, level, and dual-channel preview in order. 5. At the bottom, the buttons can be used to take photos, record videos, and switch between the front and rear cameras. @@ -69,7 +69,8 @@ How to use: - ohos.permission.MICROPHONE: required to access the microphone for video recording. - ohos.permission.MEDIA_LOCATION: required to obtain geographical information. - ohos.permission.WRITE_IMAGEVIDEO: required to write media files. -- hos.permission.READ_IMAGEVIDEO: required to read media files. +- ohos.permission.READ_IMAGEVIDEO: required to read media files. +- ohos.permission.APPROXIMATELY_LOCATION: required to obtain approximate location information of the device. - ohos.permission.ACCELEROMETER: required for the acceleration sensor. ### Constraints diff --git a/README.md b/README.md index 459ede13b5db7c15204bb750b637c891507851e8..0e423c84bf94c590e2f5503d53e92ecea3c6c366 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ 使用说明: 1. 打开应用,授权后展示预览界面。 -2. 上方从左至右按钮功能依次为:闪光灯设置、延迟拍照模式设置、动态拍照模式设置、单双段拍照模式设置(单段拍照模式不支持动态拍摄)。 -3. 切换录像模式,上方按钮依次为:闪关灯设置、防抖模式设置(模式不支持变焦)。 +2. 上方从左至右按钮功能依次为:预览帧率设置、闪光灯设置、延迟拍照模式设置、动态拍照模式设置、单双段拍照模式设置(单段拍照模式不支持动态拍摄)。 +3. 切换录像模式,上方按钮依次为:预览帧率设置、闪关灯设置、防抖模式设置(模式不支持变焦)。 4. 右侧按钮依次为:网格线、水平仪、双路预览(获取预览帧数据)。 5. 下方按钮可拍照,录像,切换前后置摄像头。 @@ -68,7 +68,8 @@ - ohos.permission.MICROPHONE:麦克风权限,用于录像 - ohos.permission.MEDIA_LOCATION: 用于获取地理信息 - ohos.permission.WRITE_IMAGEVIDEO:用于写入媒体文件 -- hos.permission.READ_IMAGEVIDEO:用于读取媒体文件 +- ohos.permission.READ_IMAGEVIDEO:用于读取媒体文件 +- ohos.permission.APPROXIMATELY_LOCATION:用于获取设备模糊位置信息 - ohos.permission.ACCELEROMETER:用于加速度传感器 diff --git a/camera/src/main/ets/cameramanagers/CameraManager.ets b/camera/src/main/ets/cameramanagers/CameraManager.ets index 2300c3bacc64001c73ff20ed27149d3220dc5039..d79bf722b7f8168b21014586c95ea2613deb6b0a 100644 --- a/camera/src/main/ets/cameramanagers/CameraManager.ets +++ b/camera/src/main/ets/cameramanagers/CameraManager.ets @@ -81,7 +81,7 @@ export class CameraManager { const output = await outputManager.createOutput(config); session.addOutput(output); } - }; + } await session.commitConfig(); await session.start(); // [End session] @@ -94,25 +94,34 @@ export class CameraManager { } async refreshOutput(oldOutput: camera.CameraOutput, newOutput: camera.CameraOutput) { - await this.session?.stop(); - this.session?.beginConfig(); - this.session?.removeOutput(oldOutput); - this.session?.addOutput(newOutput); - await this.session?.commitConfig(); - await this.session?.start(); + try { + await this.session?.stop(); + this.session?.beginConfig(); + this.session?.removeOutput(oldOutput); + this.session?.addOutput(newOutput); + await this.session?.commitConfig(); + await this.session?.start(); + } catch (exception) { + Logger.error(TAG, `refreshOutput failed, code is ${exception.code}, message is ${exception.message}`); + } } // [Start release] async release() { - await this.session?.stop(); - for (const outputManager of this.outputManagers) { - if (outputManager.isActive) { - await outputManager.release(); + try { + await this.session?.stop(); + for (const outputManager of this.outputManagers) { + if (outputManager.isActive) { + await outputManager.release(); + } } - }; - await this.cameraInput?.close(); - await this.session?.release(); + await this.cameraInput?.close(); + await this.session?.release(); + } catch (exception) { + Logger.error(TAG, `release failed, code is ${exception.code}, message is ${exception.message}`); + } } + // [End release] // [Start getCameraDevice] @@ -124,12 +133,19 @@ export class CameraManager { } return device; } + // [End getCameraDevice] // [Start getZoomRange] getZoomRange() { - return this.session!.getZoomRatioRange(); + try { + return this.session!.getZoomRatioRange(); + } catch (exception) { + Logger.error(TAG, `getZoomRange failed, code is ${exception.code}, message is ${exception.message}`); + return []; + } } + // [End getZoomRange] // [Start setFocusMode] @@ -141,20 +157,22 @@ export class CameraManager { return; } this.session?.setFocusMode(focusMode); - } catch(e) { + } catch (e) { Logger.error(TAG, 'setFocusMode error ' + JSON.stringify(e)); } } + // [End setFocusMode] // [Start setFocusPoint] setFocusPoint(point: camera.Point) { try { this.session?.setFocusPoint(point); - } catch(e) { + } catch (e) { Logger.error(TAG, 'setFocusPoint error ' + JSON.stringify(e)); } } + // [End setFocusPoint] // [Start setExposureMode] @@ -166,26 +184,28 @@ export class CameraManager { return; } this.session?.setExposureMode(exposureMode); - } catch(e) { + } catch (e) { Logger.error(TAG, 'setExposureMode error ' + JSON.stringify(e)); } } + // [End setExposureMode] // [Start setMeteringPoint] setMeteringPoint(point: camera.Point) { try { this.session?.setMeteringPoint(point); - } catch(e) { + } catch (e) { Logger.error(TAG, 'setMeteringPoint error ' + JSON.stringify(e)); } } + // [End setMeteringPoint] setZoomRatio(zoom: number) { try { this.session?.setZoomRatio(zoom); - } catch(e) { + } catch (e) { Logger.error(TAG, 'setZoomRatio error ' + JSON.stringify(e)); } } @@ -194,10 +214,11 @@ export class CameraManager { setSmoothZoom(zoom: number) { try { this.session?.setSmoothZoom(zoom); - } catch(e) { + } catch (e) { Logger.error(TAG, 'setSmoothZoom error ' + JSON.stringify(e)); } } + // [End setSmoothZoom] // [Start setFlashMode] @@ -209,10 +230,11 @@ export class CameraManager { return; } this.session?.setFlashMode(flashMode); - } catch(e) { + } catch (e) { Logger.error(TAG, 'setFlashMode error ' + JSON.stringify(e)); } } + // [End setFlashMode] setVideoStabilizationMode(stabilizationMode: camera.VideoStabilizationMode) { diff --git a/camera/src/main/ets/cameramanagers/ImageReceiverManager.ets b/camera/src/main/ets/cameramanagers/ImageReceiverManager.ets index 2fc79bcd036503e7bacb97bba2b26b0a7b890bd6..f3ad00e938b0b0f07d99bfd3abe873c2791d59be 100644 --- a/camera/src/main/ets/cameramanagers/ImageReceiverManager.ets +++ b/camera/src/main/ets/cameramanagers/ImageReceiverManager.ets @@ -49,13 +49,21 @@ export class ImageReceiverManager implements OutputManager { return; } const surfaceId = await this.init(config.profile.size); - this.output = config.cameraManager.createPreviewOutput(previewProfile, surfaceId); + try { + this.output = config.cameraManager.createPreviewOutput(previewProfile, surfaceId); + } catch (exception) { + Logger.error(TAG, `createPreviewOutput failed, code is ${exception.code}, message is ${exception.message}`); + } this.position = config.device.cameraPosition; return this.output; } async release() { - await this.output?.release(); + try { + await this.output?.release(); + } catch (exception) { + Logger.error(TAG, `release failed, code is ${exception.code}, message is ${exception.message}`); + } this.output = undefined; } @@ -66,6 +74,7 @@ export class ImageReceiverManager implements OutputManager { this.onImageArrival(receiver); return surfaceId; } + // [End init] // [Start getPixelMap] @@ -87,6 +96,7 @@ export class ImageReceiverManager implements OutputManager { srcPixelFormat: image.PixelMapFormat.NV21, }); } + // [End getPixelMap] // [Start onImageArrival] @@ -142,5 +152,6 @@ export class ImageReceiverManager implements OutputManager { }); }); } + // [End onImageArrival] } diff --git a/camera/src/main/ets/cameramanagers/PhotoManager.ets b/camera/src/main/ets/cameramanagers/PhotoManager.ets index 88401e6727752b181acee40622200ec2be45b7bd..967cfc88a2f3942b0ef4b9d6c92b4cd1531b9916 100644 --- a/camera/src/main/ets/cameramanagers/PhotoManager.ets +++ b/camera/src/main/ets/cameramanagers/PhotoManager.ets @@ -61,6 +61,7 @@ export class PhotoManager implements OutputManager { } // [Start create_photo_output] + // Create photo output public createPhotoOutput(cameraManager: camera.CameraManager, cameraDevice: camera.CameraDevice, profile: camera.Profile) { let cameraPhotoOutput: camera.PhotoOutput | undefined = undefined; @@ -94,6 +95,7 @@ export class PhotoManager implements OutputManager { // [End create_photo_output] // [Start set_photo_cb_double] + // Save camera photo async mediaLibSavePhoto(photoAsset: photoAccessHelper.PhotoAsset, phAccessHelper: photoAccessHelper.PhotoAccessHelper): Promise { try { @@ -128,7 +130,11 @@ export class PhotoManager implements OutputManager { deliveryMode: photoAccessHelper.DeliveryMode.FAST_MODE, } const handler = new MediaDataHandler(); - await photoAccessHelper.MediaAssetManager.requestImageData(context, photoAsset, requestOptions, handler); + try { + await photoAccessHelper.MediaAssetManager.requestImageData(context, photoAsset, requestOptions, handler); + } catch (exception) { + Logger.error(TAG_LOG, `requestImageData failed, code is ${exception.code}, message is ${exception.message}`); + } } public setPhotoOutputCbDouble(cameraPhotoOutput: camera.PhotoOutput) { @@ -144,6 +150,7 @@ export class PhotoManager implements OutputManager { // [End set_photo_cb_double] // [Start set_photo_cb_single] + // Set photo callback single setPhotoOutputCbSingle(photoOutput: camera.PhotoOutput, context: Context) { photoOutput.on('photoAvailable', (errCode: BusinessError, photo: camera.Photo): void => { if (errCode || photo === undefined) { @@ -153,9 +160,11 @@ export class PhotoManager implements OutputManager { this.mediaLibSavePhotoSingle(context, photo.main) }); } + // [End set_photo_cb_single] // [Start save_photo_single] + // Save photo single mediaLibSavePhotoSingle(context: Context, imageObj: image.Image) { imageObj.getComponent(image.ComponentType.JPEG, async (errCode: BusinessError, component: image.Component) => { if (errCode || component === undefined) { @@ -186,6 +195,7 @@ export class PhotoManager implements OutputManager { imageObj.release(); }); } + // [End save_photo_single] setPhotoOutputCallback(isSingle: boolean) { @@ -210,6 +220,7 @@ export class PhotoManager implements OutputManager { } // [Start set_color_space] + // Set color space setColorSpaceBeforeCommitConfig(session: camera.PhotoSession, isHdr: boolean): void { let colorSpace: colorSpaceManager.ColorSpace = isHdr ? colorSpaceManager.ColorSpace.DISPLAY_P3 : colorSpaceManager.ColorSpace.SRGB; @@ -223,8 +234,12 @@ export class PhotoManager implements OutputManager { Logger.info(TAG_LOG, `colorSpace: ${colorSpace} is not support`); return; } - Logger.info(TAG_LOG, `setColorSpace: ${colorSpace}`); - session.setColorSpace(colorSpace); + try { + Logger.info(TAG_LOG, `setColorSpace: ${colorSpace}`); + session.setColorSpace(colorSpace); + } catch (exception) { + Logger.error(TAG_LOG, `setColorSpace failed, code is ${exception.code}, message is ${exception.message}`); + } try { let activeColorSpace: colorSpaceManager.ColorSpace = session.getActiveColorSpace(); Logger.info(TAG_LOG, `activeColorSpace: ${activeColorSpace}`); @@ -232,12 +247,17 @@ export class PhotoManager implements OutputManager { Logger.error(TAG_LOG, `getActiveColorSpace Faild: ${error.message}`); } } + // [End set_color_space] public checkFlash(photoSession: camera.PhotoSession) { let flashModeStatus: boolean = false; - if (photoSession.hasFlash()) { - flashModeStatus = photoSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO); + try { + if (photoSession.hasFlash()) { + flashModeStatus = photoSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO); + } + } catch (exception) { + Logger.error(TAG_LOG, `checkFlash failed, code is ${exception.code}, message is ${exception.message}`); } return flashModeStatus; } @@ -285,7 +305,11 @@ export class PhotoManager implements OutputManager { Logger.error(TAG_LOG, `Failed to get the zoom ratio range. error: ${JSON.stringify(error)}`); } } - photoSession.setZoomRatio(zoomRatio || photoZoomRatio); + try { + photoSession.setZoomRatio(zoomRatio || photoZoomRatio); + } catch (exception) { + Logger.error(TAG_LOG, `setZoomRatio failed, code is ${exception.code}, message is ${exception.message}`); + } } getSupportedColorSpaces(session: camera.PhotoSession): Array { @@ -293,12 +317,13 @@ export class PhotoManager implements OutputManager { try { colorSpaces = session.getSupportedColorSpaces(); } catch (error) { - Logger.error(TAG_LOG,`The getSupportedColorSpaces call failed. error code: ${error.code}`); + Logger.error(TAG_LOG, `The getSupportedColorSpaces call failed. error code: ${error.code}`); } return colorSpaces; } // [Start get_photo_rotation] + // Get photo rotation getPhotoRotation(photoOutput: camera.PhotoOutput, deviceDegree: number): camera.ImageRotation { let photoRotation: camera.ImageRotation = camera.ImageRotation.ROTATION_0; try { @@ -312,6 +337,7 @@ export class PhotoManager implements OutputManager { // [End get_photo_rotation] // [Start capture_photo] + // Capture photo public async capture(isFront: boolean) { const degree = await this.getPhotoDegree(); const rotation = this.getPhotoRotation(this.output!, degree); @@ -328,6 +354,7 @@ export class PhotoManager implements OutputManager { Logger.info(TAG_LOG, 'Callback invoked to indicate the photo capture request success.'); }); } + // [End capture_photo] private calculateDeviceDegree(x: number, y: number, z: number): number { @@ -336,14 +363,19 @@ export class PhotoManager implements OutputManager { if ((x * x + y * y) * 3 < z * z) { return deviceDegree; } else { - // Calculate the inverse tangent value - let sd: Decimal = Decimal.atan2(y, -x) - // Convert radian values to angle values; - let sc: Decimal = Decimal.round(Number(sd) / Math.PI * 180); - // Adjust angle to be relative to vertical orientation - deviceDegree = 90 - Number(sc); - // Normalize angle to 0-360 degrees range - deviceDegree = deviceDegree >= 0 ? deviceDegree % 360 : deviceDegree % 360 + 360; + try { + // Calculate the inverse tangent value + let sd: Decimal = Decimal.atan2(y, -x) + // Convert radian values to angle values; + let sc: Decimal = Decimal.round(Number(sd) / Math.PI * 180); + // Adjust angle to be relative to vertical orientation + deviceDegree = 90 - Number(sc); + // Normalize angle to 0-360 degrees range + deviceDegree = deviceDegree >= 0 ? deviceDegree % 360 : deviceDegree % 360 + 360; + } catch (exception) { + Logger.error(TAG_LOG, + `calculateDeviceDegree failed, code is ${exception.code}, message is ${exception.message}`); + } } return deviceDegree; } @@ -359,6 +391,7 @@ export class PhotoManager implements OutputManager { } // [Start is_moving_photo] + // Check whether support moving photo or not public isMovingPhotoSupported(photoOutput: camera.PhotoOutput): boolean { let isSupported: boolean = false; try { @@ -372,6 +405,7 @@ export class PhotoManager implements OutputManager { // [End is_moving_photo] // [Start enable_moving_photo] + // Enable moving photo public enableMovingPhoto(enabled: boolean): void { try { this.output?.enableMovingPhoto(enabled); @@ -383,8 +417,13 @@ export class PhotoManager implements OutputManager { // [End enable_moving_photo] // [Start photo_release] + // Release photo async release() { - await this.output?.release(); + try { + await this.output?.release(); + } catch (exception) { + Logger.error(TAG_LOG, `release failed, code is ${exception.code}, message is ${exception.message}`); + } if (this.isSingle) { this.output?.off('photoAvailable'); } else { @@ -392,5 +431,6 @@ export class PhotoManager implements OutputManager { } this.output = undefined; } + // [End photo_release] } diff --git a/camera/src/main/ets/cameramanagers/PreviewManager.ets b/camera/src/main/ets/cameramanagers/PreviewManager.ets index bcdb1db5c093f8b77e4dbca8b0082aac92a2bcd0..679e3efe83153e7fd65de57f3127d22c3f207e12 100644 --- a/camera/src/main/ets/cameramanagers/PreviewManager.ets +++ b/camera/src/main/ets/cameramanagers/PreviewManager.ets @@ -24,7 +24,8 @@ const TAG_LOG = 'PreviewManager' export class PreviewManager implements OutputManager { output?: camera.PreviewOutput; isActive: boolean = true; - onPreviewStart: () => void = () => {}; + onPreviewStart: () => void = () => { + }; constructor(onPreviewStart: () => void) { this.onPreviewStart = onPreviewStart; @@ -46,10 +47,15 @@ export class PreviewManager implements OutputManager { Logger.error(TAG_LOG, 'Failed to get preview profile'); return; } - this.output = config.cameraManager.createPreviewOutput(previewProfile, config.surfaceId); - this.addOutputListener(this.output); + try { + this.output = config.cameraManager.createPreviewOutput(previewProfile, config.surfaceId); + this.addOutputListener(this.output); + } catch (exception) { + Logger.error(TAG_LOG, `createPreviewOutput failed, code is ${exception.code}, message is ${exception.message}`); + } return this.output; } + // [End createOutput] addOutputListener(output: camera.PreviewOutput) { @@ -78,28 +84,36 @@ export class PreviewManager implements OutputManager { Logger.info(TAG_LOG, 'Preview frame end'); }); } + // [End onFrame] // [Start release] async release() { - await this.output?.release(); + try { + await this.output?.release(); + } catch (exception) { + Logger.error(TAG_LOG, `release failed, code is ${exception.code}, message is ${exception.message}`); + } this.output = undefined; } + // [End release] // [Start getSupportedFrameRates] getSupportedFrameRates() { return this.output?.getSupportedFrameRates(); } + // [End getSupportedFrameRates] // [Start setFrameRate] setFrameRate(minFps: number, maxFps: number) { try { this.output?.setFrameRate(minFps, maxFps); - } catch(e) { + } catch (e) { Logger.error(TAG_LOG, 'setFrameRate error ' + JSON.stringify(e)); } } + // [End setFrameRate] } diff --git a/camera/src/main/ets/cameramanagers/VideoManager.ets b/camera/src/main/ets/cameramanagers/VideoManager.ets index 805c9c8f372922451b9360fe4a35f58930615644..ff800b8c0ae10cad12f21cb4f66c83ea88e12a6b 100644 --- a/camera/src/main/ets/cameramanagers/VideoManager.ets +++ b/camera/src/main/ets/cameramanagers/VideoManager.ets @@ -120,6 +120,7 @@ export class VideoManager implements OutputManager { Logger.info(TAG_LOG, `Failed to start and catch error is ${error.message}`); } } + // [End start_video] // [Start stop_video] @@ -138,6 +139,7 @@ export class VideoManager implements OutputManager { Logger.info(TAG_LOG, `Failed to stop and catch error is ${error.message}`); } } + // [End stop_video] // [Start pause_video] @@ -151,6 +153,7 @@ export class VideoManager implements OutputManager { Logger.info(TAG_LOG, `Failed to pause and catch error is ${error.message}`); } } + // [End pause_video] // [Start resume_video] @@ -164,18 +167,24 @@ export class VideoManager implements OutputManager { Logger.info(TAG_LOG, `Failed to resume and catch error is ${error.message}`); } } + // [End resume_video] // [Start release_video] async release() { - await this.avRecorder?.release(); - await this.output?.release(); - this.file && await fileIo.close(this.file.fd); + try { + await this.avRecorder?.release(); + await this.output?.release(); + this.file && await fileIo.close(this.file.fd); + } catch (exception) { + Logger.error(TAG_LOG, `release failed, code is ${exception.code}, message is ${exception.message}`); + } this.avRecorder?.off('stateChange'); this.avRecorder = undefined; this.output = undefined; this.file = undefined; } + // [End release_video] getCurrentOutput() { @@ -230,6 +239,7 @@ export class VideoManager implements OutputManager { } } } + // [End create_video_output] getCameraImageRotation(): camera.ImageRotation { @@ -244,8 +254,12 @@ export class VideoManager implements OutputManager { title: Date.now().toString() }; let accessHelper: photoAccessHelper.PhotoAccessHelper = photoAccessHelper.getPhotoAccessHelper(this.context); - this.videoUri = await accessHelper.createAsset(photoAccessHelper.PhotoType.VIDEO, 'mp4', options); - this.file = fileIo.openSync(this.videoUri, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE); + try { + this.videoUri = await accessHelper.createAsset(photoAccessHelper.PhotoType.VIDEO, 'mp4', options); + this.file = fileIo.openSync(this.videoUri, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE); + } catch (exception) { + Logger.error(TAG_LOG, `createAsset failed, code is ${exception.code}, message is ${exception.message}`); + } // [End create_file] // [Start av_profile] @@ -269,7 +283,7 @@ export class VideoManager implements OutputManager { audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_CAMCORDER, videoSourceType: media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV, profile: this.avProfile, - url: `fd://${this.file.fd}`, + url: `fd://${this.file?.fd}`, metadata: { videoOrientation: this.getCameraImageRotation().toString() } @@ -286,14 +300,18 @@ export class VideoManager implements OutputManager { if ((x * x + y * y) * 3 < z * z) { return getDeviceDegree; } else { - // Calculate the inverse tangent value - let sd: Decimal = Decimal.atan2(y, -x); - // Convert radian values to angle values; - let sc: Decimal = Decimal.round(Number(sd) / 3.141592653589 * 180) - // Adjust angle to be relative to vertical orientation - getDeviceDegree = 90 - Number(sc); - // Normalize angle to 0-360 degrees range - getDeviceDegree = getDeviceDegree >= 0 ? getDeviceDegree % 360 : getDeviceDegree % 360 + 360; + try { + // Calculate the inverse tangent value + let sd: Decimal = Decimal.atan2(y, -x); + // Convert radian values to angle values; + let sc: Decimal = Decimal.round(Number(sd) / 3.141592653589 * 180) + // Adjust angle to be relative to vertical orientation + getDeviceDegree = 90 - Number(sc); + // Normalize angle to 0-360 degrees range + getDeviceDegree = getDeviceDegree >= 0 ? getDeviceDegree % 360 : getDeviceDegree % 360 + 360; + } catch (exception) { + Logger.error(TAG_LOG, `getRealData failed, code is ${exception.code}, message is ${exception.message}`); + } } return getDeviceDegree; } @@ -333,13 +351,14 @@ export class VideoManager implements OutputManager { getVideoRotation(deviceDegree: number): camera.ImageRotation { let videoRotation: camera.ImageRotation = this.getCameraImageRotation(); try { - videoRotation = this.output!.getVideoRotation(deviceDegree); - Logger.info(TAG_LOG, `Video rotation is: ${videoRotation}`); + videoRotation = this.output!.getVideoRotation(deviceDegree); + Logger.info(TAG_LOG, `Video rotation is: ${videoRotation}`); } catch (error) { Logger.info(TAG_LOG, `Failed to getVideoRotation and catch error is: ${error.message}`); } return videoRotation; } + // [End get_video_rotation] async getVideoThumbnail() { @@ -373,18 +392,25 @@ export class VideoManager implements OutputManager { setVideoStabilizationMode(session: camera.VideoSession): boolean { let mode: camera.VideoStabilizationMode = camera.VideoStabilizationMode.AUTO; // Check whether video stabilization is supported - let isSupported: boolean = session.isVideoStabilizationModeSupported(mode); - if (!isSupported) { - Logger.info(TAG_LOG, `videoStabilizationMode: ${mode} is not support`); + try { + let isSupported: boolean = session.isVideoStabilizationModeSupported(mode); + if (!isSupported) { + Logger.info(TAG_LOG, `videoStabilizationMode: ${mode} is not support`); + return false; + } + Logger.info(TAG_LOG, `setVideoStabilizationMode: ${mode}`); + // Set video stabilization + session.setVideoStabilizationMode(mode); + let activeVideoStabilizationMode = session.getActiveVideoStabilizationMode(); + Logger.info(TAG_LOG, `activeVideoStabilizationMode: ${activeVideoStabilizationMode}`); + return isSupported; + } catch (exception) { + Logger.error(TAG_LOG, + `setVideoStabilizationMode failed, code is ${exception.code}, message is ${exception.message}`); return false; } - Logger.info(TAG_LOG, `setVideoStabilizationMode: ${mode}`); - // Set video stabilization - session.setVideoStabilizationMode(mode); - let activeVideoStabilizationMode = session.getActiveVideoStabilizationMode(); - Logger.info(TAG_LOG, `activeVideoStabilizationMode: ${activeVideoStabilizationMode}`); - return isSupported; } + // [End set_video_stabilization] // [Start set_video_color_space] @@ -406,8 +432,12 @@ export class VideoManager implements OutputManager { Logger.info(TAG_LOG, `colorSpace: ${colorSpace} is not support`); return; } - Logger.info(TAG_LOG, `setColorSpace: ${colorSpace}`); - session.setColorSpace(colorSpace); + try { + Logger.info(TAG_LOG, `setColorSpace: ${colorSpace}`); + session.setColorSpace(colorSpace); + } catch (exception) { + Logger.error(TAG_LOG, `setColorSpace failed, code is ${exception.code}, message is ${exception.message}`); + } try { let activeColorSpace: colorSpaceManager.ColorSpace = session.getActiveColorSpace(); Logger.info(TAG_LOG, `activeColorSpace: ${activeColorSpace}`); @@ -415,5 +445,6 @@ export class VideoManager implements OutputManager { Logger.error(TAG_LOG, `getActiveColorSpace Faild: ${error.message}`); } } + // [Start set_video_color_space] } \ No newline at end of file diff --git a/camera/src/main/ets/components/LevelIndicator.ets b/camera/src/main/ets/components/LevelIndicator.ets index b3e6ac57d1c83d978e9842ad459dec00dfaf6791..66cab17196b04c14756dd3a8db7e7fc9ddb3a605 100644 --- a/camera/src/main/ets/components/LevelIndicator.ets +++ b/camera/src/main/ets/components/LevelIndicator.ets @@ -15,8 +15,10 @@ import { curves, display } from '@kit.ArkUI'; import { sensor } from '@kit.SensorServiceKit'; +import { Logger } from 'commons'; const ANGLE_DIFFERENCE: number = 3; +const TAG = 'LevelIndicator' // [Start LevelIndicator] @Component @@ -24,7 +26,13 @@ export struct LevelIndicator { @Prop acc: sensor.AccelerometerResponse; getRotate() { - const rotation = display.getDefaultDisplaySync().rotation * 90; + let displayDefault: display.Display | null = null; + try { + displayDefault = display.getDefaultDisplaySync(); + } catch (exception) { + Logger.error(TAG, `getDefaultDisplaySync failed, code is ${exception.code}, message is ${exception.message}`); + } + const rotation = (displayDefault?.rotation ?? 0) * 90; if (rotation === 90 || rotation === 270) { return -Math.atan2(-this.acc.y, this.acc.x) * (180 / Math.PI); } @@ -42,7 +50,7 @@ export struct LevelIndicator { width: 200, height: 1 }) - // [StartExclude LevelIndicator] + // [StartExclude LevelIndicator] .stroke(Color.White) .endPoint([200, 0]) // [EndExclude LevelIndicator] @@ -55,7 +63,7 @@ export struct LevelIndicator { playMode: PlayMode.Normal }) Circle() - // [StartExclude LevelIndicator] + // [StartExclude LevelIndicator] .width(48) .height(48) .stroke(Color.White) @@ -70,4 +78,5 @@ export struct LevelIndicator { .hitTestBehavior(HitTestMode.Transparent) } } + // [End LevelIndicator] diff --git a/entry/src/main/ets/entryability/EntryAbility.ets b/entry/src/main/ets/entryability/EntryAbility.ets index fe3138ba2df7682844b5eba1433f0a721afde588..3c346dc45817df9f8653bded83b97e44641ddf9b 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ets +++ b/entry/src/main/ets/entryability/EntryAbility.ets @@ -22,8 +22,12 @@ const DOMAIN = 0x0000; export default class EntryAbility extends UIAbility { onCreate(): void { - this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); - hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } catch (exception) { + hilog.error(DOMAIN, 'testTag', `setColorMode failed, code is ${exception.code}, message is ${exception.message}`); + } } onDestroy(): void { @@ -34,7 +38,12 @@ export default class EntryAbility extends UIAbility { // Main window is created, set main page for this ability hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); - WindowUtil.enterImmersive(windowStage.getMainWindowSync()); + try { + WindowUtil.enterImmersive(windowStage.getMainWindowSync()); + } catch (exception) { + hilog.error(DOMAIN, 'testTag', + `getMainWindowSync failed, code is ${exception.code}, message is ${exception.message}`); + } windowStage.loadContent('pages/Index', (err) => { if (err.code) { diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index 6226fa52527caef026c78dd789ee32714363abcb..f68104a094a4b7d7fcb41d12e055a6958924a693 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -35,6 +35,7 @@ import ModeButtonsView from '../views/ModeButtonsView'; import SettingButtonsView from '../views/SettingButtonsView'; import OperateButtonsView from '../views/OperateButtonsView'; import PreviewViewModel from '../viewmodels/PreviewViewModel'; +import { Logger } from 'commons'; @Extend(SymbolGlyph) function funcButtonStyle() { @@ -45,30 +46,30 @@ function funcButtonStyle() { .backgroundColor('#664D4D4D') } +const TAG = 'Index' + @Entry @Component struct Index { private context: Context = this.getUIContext().getHostContext()!; private applicationContext = this.context.getApplicationContext(); private windowClass = (this.context as common.UIAbilityContext).windowStage.getMainWindowSync(); - @State videoManager: VideoManager = new VideoManager(this.context); @State isSinglePhoto: boolean = false; @State isLivePhoto: boolean = false; private photoManager: PhotoManager = new PhotoManager(this.context, true, this.isSinglePhoto); - private previewManager: PreviewManager = new PreviewManager(() => { this.onPreviewStart() }); + private previewManager: PreviewManager = new PreviewManager(() => { + this.onPreviewStart() + }); private imageReceiverManager: ImageReceiverManager = new ImageReceiverManager(px => { this.onImageReceiver(px); }); private cameraManager: CameraManager = new CameraManager(this.context, [this.previewManager, this.photoManager, this.videoManager, this.imageReceiverManager]); - @State previewVM: PreviewViewModel = new PreviewViewModel(this.getUIContext()); - @State isGridLineVisible: boolean = false; @State isLevelIndicatorVisible: boolean = false; @State isPreviewImageVisible: boolean = false; - @State isFocusBoxVisible: boolean = false; @State focusBoxPosition: Edges = { top: 0, left: 0 }; private focusBoxSize: Size = { width: 80, height: 80 }; @@ -76,27 +77,23 @@ struct Index { this.isFocusBoxVisible = false; }, 3 * 1000); private exposureFontSize: number = 24; - @State isSleeping: boolean = false; private sleepTimer?: RefreshableTimer; - private zoomRange: number[] = []; @State zooms: number[] = [1, 5, 10]; @State currentZoom: number = 1; @State isZoomPinching: boolean = false; private originZoomBeforePinch: number = 1; // record zoom after pinch, sale base it. @State isStabilizationEnabled: boolean = false; - @State previewImage: PixelMap | ResourceStr = ''; private PreviewImageHeight: number = 80; - @State photoDelayTime: number = 0; @State photoRemainder: number = 0; - @State isDelayTakePhoto:boolean = false; - + @State isDelayTakePhoto: boolean = false; @State acc: sensor.AccelerometerResponse = { x: 0, y: 0, z: 0 } as sensor.AccelerometerResponse; - private setPreviewSize: () => void = () => { this.previewVM.setPreviewSize(); } - + private setPreviewSize: () => void = () => { + this.previewVM.setPreviewSize(); + } @State isShowBlack: boolean = false; @StorageLink('captureClick') @Watch('onCaptureClick') captureClickFlag: number = 0; @State flashBlackOpacity: number = 1; @@ -106,7 +103,13 @@ struct Index { this.initSleepTimer(); this.registerApplicationStateChange(); this.addOrientationChangeEventListener(); - display.on('foldStatusChange', () => { this.onFoldStatusChange() }); + try { + display.on('foldStatusChange', () => { + this.onFoldStatusChange() + }); + } catch (exception) { + Logger.error(TAG, `onFoldStatusChange failed, code is ${exception.code}, message is ${exception.message}`); + } } aboutToDisappear(): void { @@ -115,10 +118,15 @@ struct Index { // [Start addGravityEventListener] addGravityEventListener() { - sensor.on(sensor.SensorId.GRAVITY, (data) => { - this.acc = data; - }, { interval: 100 * 1000 * 1000 }); // 100ms + try { + sensor.on(sensor.SensorId.GRAVITY, (data) => { + this.acc = data; + }, { interval: 100 * 1000 * 1000 }); // 100ms + } catch (exception) { + Logger.error(TAG, `addGravityEventListener failed, code is ${exception.code}, message is ${exception.message}`); + } } + // [End addGravityEventListener] addOrientationChangeEventListener() { @@ -146,6 +154,7 @@ struct Index { this.sleepTimer?.refresh(); }); } + // [End initSleepTimer] async onFoldStatusChange() { @@ -177,10 +186,15 @@ struct Index { const sceneMode = this.previewVM.getSceneMode(); await this.cameraManager.start(this.previewVM.surfaceId, cameraPosition, sceneMode, this.previewVM.getProfile); } + // [End registerApplicationStateChange] exitApp() { - this.applicationContext.killAllProcesses(); + try { + this.applicationContext.killAllProcesses(); + } catch (exception) { + Logger.error(TAG, `exitApp failed, code is ${exception.code}, message is ${exception.message}`); + } } onPreviewStart() { @@ -204,7 +218,8 @@ struct Index { this.previewVM.rates = [minRate, maxRate]; this.previewVM.currentRate = maxRate; this.previewManager.setFrameRate(maxRate, maxRate); - }; + } + ; } syncButtonSettings() { @@ -244,12 +259,14 @@ struct Index { type: XComponentType.SURFACE, controller: this.previewVM.xComponentController }) - // [StartExclude Stack] - // [StartExclude XComponent_gesture] + // [StartExclude Stack] + // [StartExclude XComponent_gesture] .onLoad(async () => { // [StartExclude XComponent] await PermissionManager.request(CameraConstant.PERMISSIONS, this.context) - .catch(() => { this.exitApp() }); + .catch(() => { + this.exitApp() + }); // [EndExclude XComponent] this.previewVM.surfaceId = this.previewVM.xComponentController.getXComponentSurfaceId(); this.previewVM.setPreviewSize(); @@ -270,7 +287,9 @@ struct Index { this.sleepTimer?.refresh(); }) .onActionUpdate((event: GestureEvent) => { - if (this.previewVM.isVideoMode() && this.isStabilizationEnabled) return; + if (this.previewVM.isVideoMode() && this.isStabilizationEnabled) { + return; + } const targetZoom = this.originZoomBeforePinch * event.scale; this.currentZoom = limitNumberInRange(targetZoom, this.zoomRange); this.cameraManager.setZoomRatio(this.currentZoom); @@ -319,7 +338,7 @@ struct Index { .position(this.getExposurePosition()) } - if(this.isDelayTakePhoto){ + if (this.isDelayTakePhoto) { Text(`${this.photoRemainder}S`) .fontSize(44) .fontWeight(FontWeight.Regular) @@ -329,7 +348,7 @@ struct Index { if (this.isShowBlack) { Column() - .key('black') + .id('black') .width('100%') .height('100%') .backgroundColor(Color.Black) @@ -368,6 +387,7 @@ struct Index { this.syncButtonSettings(); }) } + // [End wakeupMask] @Builder @@ -402,13 +422,20 @@ struct Index { .funcButtonStyle() .onClick(() => { this.isPreviewImageVisible = !this.isPreviewImageVisible; - const message = this.isPreviewImageVisible ? $r('app.string.preview_image_open') : $r('app.string.preview_image_close'); + const message = + this.isPreviewImageVisible ? $r('app.string.preview_image_open') : $r('app.string.preview_image_close'); showToast(this.getUIContext(), message); }) } getPreviewImageWidth() { - const rotation = display.getDefaultDisplaySync().rotation * 90; + let displayDefault: display.Display | null = null; + try { + displayDefault = display.getDefaultDisplaySync(); + } catch (exception) { + Logger.error(TAG, `getDefaultDisplaySync failed, code is ${exception.code}, message is ${exception.message}`); + } + const rotation = (displayDefault?.rotation ?? 0) * 90; const ratio = this.previewVM.getPreviewRatio(); const displayRatio = rotation === 90 || rotation === 270 ? 1 / ratio : ratio; return this.PreviewImageHeight / displayRatio; @@ -519,6 +546,7 @@ struct Index { .height('100%') .width('100%') .backgroundColor(Color.Black) - .onClick(() => {}) + .onClick(() => { + }) } } \ No newline at end of file diff --git a/entry/src/main/ets/utils/CommonUtil.ets b/entry/src/main/ets/utils/CommonUtil.ets index fcf47ba52d1008455efad159b4c1ef32803399b5..9decaf42f64d78e781cd285e271b16a955ea7212 100644 --- a/entry/src/main/ets/utils/CommonUtil.ets +++ b/entry/src/main/ets/utils/CommonUtil.ets @@ -16,11 +16,18 @@ import { Point } from '@kit.TestKit'; import { camera } from '@kit.CameraKit'; import { display } from '@kit.ArkUI'; +import { Logger } from 'commons'; export function limitNumberInRange(src: number, range: number[]) { - if (range.length < 2) return src; - if (src < range[0]) return range[0]; - if (src > range[1]) return range[1]; + if (range.length < 2) { + return src; + } + if (src < range[0]) { + return range[0]; + } + if (src > range[1]) { + return range[1]; + } return src; } @@ -41,7 +48,7 @@ export function findRangeIndex(target: number, arr: number[]) { // Math floor float by digit // eg: toFixed(9.97, 1) -> 9.9 export function toFixed(num: number, digit: number): string { - const scale = 10 ** digit; + const scale = 10**digit; return (Math.floor(num * scale) / scale).toFixed(digit); } @@ -69,6 +76,7 @@ export function getClampedChildPosition(childSize: Size, parentSize: Size, point } return { left, top }; } + // [End getClampedChildPosition] export function showToast( @@ -78,17 +86,27 @@ export function showToast( alignment = Alignment.Top, offset: Offset = { dx: 0, dy: 300 } ) { - UIContext.getPromptAction().openToast({ - message, - duration, - alignment, - offset - }); + try { + UIContext.getPromptAction().openToast({ + message, + duration, + alignment, + offset + }); + } catch (exception) { + Logger.error('showToast', `showToast failed, code is ${exception.code}, message is ${exception.message}`); + } } // [Start calCameraPoint] export function calCameraPoint(eventX: number, eventY: number, width: number, height: number): camera.Point { - const displayRotation = display.getDefaultDisplaySync().rotation * 90; + let displayDefault: display.Display | null = null; + try { + displayDefault = display.getDefaultDisplaySync(); + } catch (exception) { + Logger.error('calCameraPoint', `calCameraPoint failed, code is ${exception.code}, message is ${exception.message}`); + } + const displayRotation = (displayDefault?.rotation ?? 0) * 90; if (displayRotation === 0) { return { x: eventY / height, y: 1 - eventX / width }; } @@ -100,4 +118,5 @@ export function calCameraPoint(eventX: number, eventY: number, width: number, he } return { x: eventX / width, y: eventY / height }; } + // [End calCameraPoint] \ No newline at end of file diff --git a/entry/src/main/ets/utils/PermissionManager.ets b/entry/src/main/ets/utils/PermissionManager.ets index c65190ea0ecc9ad527f4e576bd6db88a79d4ef40..95de42ca8d4f1063e501950295a02931f005205a 100644 --- a/entry/src/main/ets/utils/PermissionManager.ets +++ b/entry/src/main/ets/utils/PermissionManager.ets @@ -23,18 +23,23 @@ class PermissionManager { private static atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager(); static async request(permissions: Permissions[], context: Context) { - const data = await PermissionManager.atManager.requestPermissionsFromUser(context, permissions); - const grantStatus: number[] = data.authResults; - const deniedPermissions = permissions.filter((_, i) => grantStatus[i] !== 0); - for (const permission of deniedPermissions) { - const secondGrantStatus = await PermissionManager.atManager.requestPermissionOnSetting(context, [permission]); - if (secondGrantStatus[0] !== 0) { - Logger.error(TAG, 'permission denied'); - throw new Error('permission denied'); + try { + const data = await PermissionManager.atManager.requestPermissionsFromUser(context, permissions); + const grantStatus: number[] = data.authResults; + const deniedPermissions = permissions.filter((_, i) => grantStatus[i] !== 0); + for (const permission of deniedPermissions) { + const secondGrantStatus = await PermissionManager.atManager.requestPermissionOnSetting(context, [permission]); + if (secondGrantStatus[0] !== 0) { + Logger.error(TAG, 'permission denied'); + throw new Error('permission denied'); + } } + } catch (exception) { + Logger.error(TAG, `request failed, code is ${exception.code}, message is ${exception.message}`); } } } + // [End request_permissions] export default PermissionManager; \ No newline at end of file diff --git a/entry/src/main/ets/utils/WindowUtil.ets b/entry/src/main/ets/utils/WindowUtil.ets index 9d54a733dca804e4bf57fbf7831e3b4c50f6f284..0d9bc91690df90af78208f3c5b42f4799b155a8c 100644 --- a/entry/src/main/ets/utils/WindowUtil.ets +++ b/entry/src/main/ets/utils/WindowUtil.ets @@ -30,10 +30,16 @@ class WindowUtil { // Given a ratio, obtain the maximum display width and height based on the screen width and height. static getMaxDisplaySize(ratio: number): Size { - const defaultDisplay: display.Display = display.getDefaultDisplaySync(); - const windowWidth: number = defaultDisplay.width; - const windowHeight: number = defaultDisplay.height; - const rotation = display.getDefaultDisplaySync().rotation * 90; + let defaultDisplay: display.Display | null = null; + try { + defaultDisplay = display.getDefaultDisplaySync(); + } catch (exception) { + Logger.error(TAG, `getDefaultDisplaySync failed, code is ${exception.code}, message is ${exception.message}`); + } + //const defaultDisplay: display.Display = display.getDefaultDisplaySync(); + const windowWidth: number = defaultDisplay?.width ?? 0; + const windowHeight: number = defaultDisplay?.height ?? 0; + const rotation = (defaultDisplay?.rotation ?? 0) * 90; if (rotation === 90 || rotation === 270) { ratio = 1 / ratio; } @@ -53,8 +59,13 @@ class WindowUtil { } static getWindowRatio(): number { - const defaultDisplay: display.Display = display.getDefaultDisplaySync(); - return defaultDisplay.height / defaultDisplay.width; + try { + const defaultDisplay: display.Display = display.getDefaultDisplaySync(); + return defaultDisplay.height / defaultDisplay.width; + } catch (exception) { + Logger.error(TAG, `getWindowRatio failed, code is ${exception.code}, message is ${exception.message}`); + return 0; + } } } diff --git a/oh-package-lock.json5 b/oh-package-lock.json5 deleted file mode 100644 index 2857b556e1b879745efca26121d68bb5d43c38cf..0000000000000000000000000000000000000000 --- a/oh-package-lock.json5 +++ /dev/null @@ -1,10 +0,0 @@ -{ - "meta": { - "stableOrder": true, - "enableUnifiedLockfile": false - }, - "lockfileVersion": 3, - "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", - "specifiers": {}, - "packages": {} -} \ No newline at end of file