diff --git a/camera/src/main/ets/cameramanagers/CameraManager.ets b/camera/src/main/ets/cameramanagers/CameraManager.ets index d79bf722b7f8168b21014586c95ea2613deb6b0a..693d0115bdd56a8cdf639645332cd381c6f948bb 100644 --- a/camera/src/main/ets/cameramanagers/CameraManager.ets +++ b/camera/src/main/ets/cameramanagers/CameraManager.ets @@ -21,21 +21,25 @@ import OutputManager, { CreateOutputConfig } from './OutputManager'; const TAG = 'CameraManager'; export class CameraManager { - private cameraManager: camera.CameraManager; + private cameraManager?: camera.CameraManager; session?: camera.PhotoSession | camera.VideoSession; private cameraInput?: camera.CameraInput; private outputManagers: OutputManager[] = []; constructor(context: Context, outputManagers: OutputManager[]) { - // [Start cameraManager] - this.cameraManager = camera.getCameraManager(context); - // [End cameraManager] - this.outputManagers = outputManagers; - this.addCameraStatusListener(); + try { + // [Start cameraManager] + this.cameraManager = camera.getCameraManager(context); + // [End cameraManager] + this.outputManagers = outputManagers; + this.addCameraStatusListener(); + } catch (exception) { + Logger.error(TAG, `constructor failed, code is ${exception.code}, message is ${exception.message}`); + } } addCameraStatusListener() { - this.cameraManager.on('cameraStatus', (err: BusinessError, statusInfo: camera.CameraStatusInfo) => { + this.cameraManager?.on('cameraStatus', (err: BusinessError, statusInfo: camera.CameraStatusInfo) => { if (err && err.message) { Logger.error(TAG, 'cameraStatus with errorMessage = ' + err.message); return; @@ -60,13 +64,13 @@ export class CameraManager { return; } // [Start cameraInput] - this.cameraInput = this.cameraManager.createCameraInput(device); - await this.cameraInput.open(); + this.cameraInput = this.cameraManager?.createCameraInput(device); + await this.cameraInput?.open(); // [End cameraInput] // [Start session] - const session = this.cameraManager.createSession(sceneMode); - session.beginConfig(); - session.addInput(this.cameraInput); + const session = this.cameraManager?.createSession(sceneMode); + session?.beginConfig(); + session?.addInput(this.cameraInput); // [StartExclude session] const config: CreateOutputConfig = { cameraManager: this.cameraManager, @@ -79,11 +83,11 @@ export class CameraManager { for (const outputManager of this.outputManagers) { if (outputManager.isActive) { const output = await outputManager.createOutput(config); - session.addOutput(output); + session?.addOutput(output); } } - await session.commitConfig(); - await session.start(); + await session?.commitConfig(); + await session?.start(); // [End session] this.session = session as (camera.PhotoSession | camera.VideoSession); this.setFocusMode(camera.FocusMode.FOCUS_MODE_AUTO); @@ -126,7 +130,11 @@ export class CameraManager { // [Start getCameraDevice] getCameraDevice(cameraPosition: camera.CameraPosition) { - const cameraDevices = this.cameraManager.getSupportedCameras(); + const cameraDevices = this.cameraManager?.getSupportedCameras(); + if (!cameraDevices) { + Logger.error(TAG, `Failed to get camera device. cameraPosition: ${cameraPosition}}`); + return; + } const device = cameraDevices?.find(device => device.cameraPosition === cameraPosition) || cameraDevices[0]; if (!device) { Logger.error(TAG, `Failed to get camera device. cameraPosition: ${cameraPosition}}`); diff --git a/camera/src/main/ets/cameramanagers/ImageReceiverManager.ets b/camera/src/main/ets/cameramanagers/ImageReceiverManager.ets index f3ad00e938b0b0f07d99bfd3abe873c2791d59be..556b7c344fdef60d631ca5e93a07343e5a676ddd 100644 --- a/camera/src/main/ets/cameramanagers/ImageReceiverManager.ets +++ b/camera/src/main/ets/cameramanagers/ImageReceiverManager.ets @@ -34,10 +34,10 @@ export class ImageReceiverManager implements OutputManager { } async createOutput(config: CreateOutputConfig) { - const cameraOutputCap = config.cameraManager.getSupportedOutputCapability(config.device, config.sceneMode); + const cameraOutputCap = config.cameraManager?.getSupportedOutputCapability(config.device, config.sceneMode); const displayRatio = config.profile.size.width / config.profile.size.height; const profileWidth = config.profile.size.width; - const previewProfile = cameraOutputCap.previewProfiles + const previewProfile = cameraOutputCap?.previewProfiles .sort((a, b) => Math.abs(a.size.width - profileWidth) - Math.abs(b.size.width - profileWidth)) .find(pf => { const pfDisplayRatio = pf.size.width / pf.size.height; @@ -50,7 +50,7 @@ export class ImageReceiverManager implements OutputManager { } const surfaceId = await this.init(config.profile.size); try { - this.output = config.cameraManager.createPreviewOutput(previewProfile, surfaceId); + this.output = config.cameraManager?.createPreviewOutput(previewProfile, surfaceId); } catch (exception) { Logger.error(TAG, `createPreviewOutput failed, code is ${exception.code}, message is ${exception.message}`); } @@ -122,7 +122,13 @@ export class ImageReceiverManager implements OutputManager { const stride = imgComponent.rowStride; Logger.info(TAG, `getComponent with width:${width} height:${height} stride:${stride}`); const pixelMap = await this.getPixelMap(imgComponent, width, height, stride); - const displayRotation = display.getDefaultDisplaySync().rotation * camera.ImageRotation.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 displayRotation = (displayDefault?.rotation ?? 0) * camera.ImageRotation.ROTATION_90; const rotation = this.output!.getPreviewRotation(displayRotation); if (this.position === camera.CameraPosition.CAMERA_POSITION_FRONT) { if (displayRotation === 90 || displayRotation === 270) { diff --git a/camera/src/main/ets/cameramanagers/OutputManager.ets b/camera/src/main/ets/cameramanagers/OutputManager.ets index c476ae134b6c41de7df7b61c0cd47eb2700dfd2b..cf636eefe9ff43a033af25be5ac5b9717507d6b4 100644 --- a/camera/src/main/ets/cameramanagers/OutputManager.ets +++ b/camera/src/main/ets/cameramanagers/OutputManager.ets @@ -16,7 +16,7 @@ import { camera } from '@kit.CameraKit'; export interface CreateOutputConfig { - cameraManager: camera.CameraManager; + cameraManager?: camera.CameraManager; device: camera.CameraDevice; profile: camera.Profile; sceneMode?: camera.SceneMode; diff --git a/camera/src/main/ets/cameramanagers/PhotoManager.ets b/camera/src/main/ets/cameramanagers/PhotoManager.ets index 967cfc88a2f3942b0ef4b9d6c92b4cd1531b9916..42f0fc0f4364b0ae1b4b972f79972774c546e47d 100644 --- a/camera/src/main/ets/cameramanagers/PhotoManager.ets +++ b/camera/src/main/ets/cameramanagers/PhotoManager.ets @@ -62,11 +62,11 @@ export class PhotoManager implements OutputManager { // [Start create_photo_output] // Create photo output - public createPhotoOutput(cameraManager: camera.CameraManager, cameraDevice: camera.CameraDevice, + public createPhotoOutput(cameraManager: camera.CameraManager|undefined, cameraDevice: camera.CameraDevice, profile: camera.Profile) { let cameraPhotoOutput: camera.PhotoOutput | undefined = undefined; const cameraOutputCapability = - cameraManager.getSupportedOutputCapability(cameraDevice, camera.SceneMode.NORMAL_PHOTO); + cameraManager?.getSupportedOutputCapability(cameraDevice, camera.SceneMode.NORMAL_PHOTO); let photoProfilesArray: camera.Profile[] | undefined = cameraOutputCapability?.photoProfiles; if (photoProfilesArray?.length) { try { @@ -83,7 +83,7 @@ export class PhotoManager implements OutputManager { Logger.error(TAG_LOG, 'Failed to get photo profile'); return; } - cameraPhotoOutput = cameraManager.createPhotoOutput(PhotoProfile); + cameraPhotoOutput = cameraManager?.createPhotoOutput(PhotoProfile); } catch (error) { Logger.error(TAG_LOG, `Failed to createPhotoOutput. error: ${JSON.stringify(error)}`); } @@ -181,18 +181,23 @@ export class PhotoManager implements OutputManager { let options: photoAccessHelper.CreateOptions = { title: 'testPhoto' } - let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest = - photoAccessHelper.MediaAssetChangeRequest.createAssetRequest(context, photoType, extension, options); - assetChangeRequest.addResource(photoAccessHelper.ResourceType.IMAGE_RESOURCE, buffer) - assetChangeRequest.saveCameraPhoto(); - let accessHelper: photoAccessHelper.PhotoAccessHelper = - photoAccessHelper.getPhotoAccessHelper(context); - await accessHelper.applyChanges(assetChangeRequest); - let imageSource = image.createImageSource(buffer); - let pixelmap = imageSource.createPixelMapSync(); - this.callback(pixelmap, assetChangeRequest.getAsset().uri); - accessHelper.release(); - imageObj.release(); + try { + let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest = + photoAccessHelper.MediaAssetChangeRequest.createAssetRequest(context, photoType, extension, options); + assetChangeRequest.addResource(photoAccessHelper.ResourceType.IMAGE_RESOURCE, buffer) + assetChangeRequest.saveCameraPhoto(); + let accessHelper: photoAccessHelper.PhotoAccessHelper = + photoAccessHelper.getPhotoAccessHelper(context); + await accessHelper.applyChanges(assetChangeRequest); + let imageSource = image.createImageSource(buffer); + let pixelmap = imageSource.createPixelMapSync(); + this.callback(pixelmap, assetChangeRequest.getAsset().uri); + accessHelper.release(); + imageObj.release(); + } catch (exception) { + Logger.error(TAG_LOG, + `mediaLibSavePhotoSingle failed, code is ${exception.code}, message is ${exception.message}`); + } }); } @@ -382,10 +387,14 @@ export class PhotoManager implements OutputManager { private getPhotoDegree() { const promise: Promise = new Promise(resolve => { - sensor.once(sensor.SensorId.ACCELEROMETER, (data: sensor.AccelerometerResponse) => { - let degree = this.calculateDeviceDegree(data.x, data.y, data.z); - resolve(degree); - }); + try { + sensor.once(sensor.SensorId.ACCELEROMETER, (data: sensor.AccelerometerResponse) => { + let degree = this.calculateDeviceDegree(data.x, data.y, data.z); + resolve(degree); + }); + } catch (exception) { + Logger.error(TAG_LOG, `getPhotoDegree failed, code is ${exception.code}, message is ${exception.message}`); + } }) return promise; } diff --git a/camera/src/main/ets/cameramanagers/PreviewManager.ets b/camera/src/main/ets/cameramanagers/PreviewManager.ets index 679e3efe83153e7fd65de57f3127d22c3f207e12..d11877b13b86730c451318102032cc94496e91ea 100644 --- a/camera/src/main/ets/cameramanagers/PreviewManager.ets +++ b/camera/src/main/ets/cameramanagers/PreviewManager.ets @@ -33,10 +33,10 @@ export class PreviewManager implements OutputManager { // [Start createOutput] async createOutput(config: CreateOutputConfig) { - const cameraOutputCap = config.cameraManager.getSupportedOutputCapability(config.device, config.sceneMode); + const cameraOutputCap = config.cameraManager?.getSupportedOutputCapability(config.device, config.sceneMode); const displayRatio = config.profile.size.width / config.profile.size.height; const profileWidth = config.profile.size.width; - const previewProfile = cameraOutputCap.previewProfiles + const previewProfile = cameraOutputCap?.previewProfiles .sort((a, b) => Math.abs(a.size.width - profileWidth) - Math.abs(b.size.width - profileWidth)) .find(pf => { const pfDisplayRatio = pf.size.width / pf.size.height; @@ -48,8 +48,10 @@ export class PreviewManager implements OutputManager { return; } try { - this.output = config.cameraManager.createPreviewOutput(previewProfile, config.surfaceId); - this.addOutputListener(this.output); + this.output = config.cameraManager?.createPreviewOutput(previewProfile, config.surfaceId); + if (this.output) { + this.addOutputListener(this.output); + } } catch (exception) { Logger.error(TAG_LOG, `createPreviewOutput failed, code is ${exception.code}, message is ${exception.message}`); } diff --git a/camera/src/main/ets/cameramanagers/VideoManager.ets b/camera/src/main/ets/cameramanagers/VideoManager.ets index ff800b8c0ae10cad12f21cb4f66c83ea88e12a6b..c075098815b61ab8c9a993d2f932d04da5d9a155 100644 --- a/camera/src/main/ets/cameramanagers/VideoManager.ets +++ b/camera/src/main/ets/cameramanagers/VideoManager.ets @@ -196,7 +196,7 @@ export class VideoManager implements OutputManager { } // [Start create_video_output] - async createVideoOutput(cameraManager: camera.CameraManager) { + async createVideoOutput(cameraManager: camera.CameraManager|undefined) { if (!this.avRecorder || this.avRecorder.state !== AVRecorderState.PREPARED) { return; } @@ -204,18 +204,18 @@ export class VideoManager implements OutputManager { // [Start get_surface_id] let videoSurfaceId = await this.avRecorder.getInputSurface(); // [End get_surface_id] - this.output = cameraManager.createVideoOutput(this.videoProfile, videoSurfaceId); + this.output = cameraManager?.createVideoOutput(this.videoProfile, videoSurfaceId); } catch (error) { Logger.error(TAG_LOG, `Failed to create the output instance. error code: ${error.code}`); } } - setVideoProfile(cameraManager: camera.CameraManager, targetProfile: camera.Profile, + setVideoProfile(cameraManager: camera.CameraManager|undefined, targetProfile: camera.Profile, device: camera.CameraDevice) { this.cameraPosition = device.cameraPosition; let cameraOutputCap: camera.CameraOutputCapability | undefined = - cameraManager.getSupportedOutputCapability(device, + cameraManager?.getSupportedOutputCapability(device, camera.SceneMode.NORMAL_VIDEO); let videoProfilesArray: camera.VideoProfile[] | undefined = cameraOutputCap?.videoProfiles; if (videoProfilesArray?.length) { diff --git a/camera/src/main/ets/components/LevelIndicator.ets b/camera/src/main/ets/components/LevelIndicator.ets index 66cab17196b04c14756dd3a8db7e7fc9ddb3a605..da5302a37312d6f5162f073a41f4ccb70dd7ef48 100644 --- a/camera/src/main/ets/components/LevelIndicator.ets +++ b/camera/src/main/ets/components/LevelIndicator.ets @@ -18,7 +18,7 @@ import { sensor } from '@kit.SensorServiceKit'; import { Logger } from 'commons'; const ANGLE_DIFFERENCE: number = 3; -const TAG = 'LevelIndicator' +const TAG = 'LevelIndicator'; // [Start LevelIndicator] @Component diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index f68104a094a4b7d7fcb41d12e055a6958924a693..8b3f6d214d58f1e93b0c260227ed23c76224191b 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -17,6 +17,7 @@ import { sensor } from '@kit.SensorServiceKit'; import { common } from '@kit.AbilityKit'; import { display } from '@kit.ArkUI'; import { curves } from '@kit.ArkUI'; +import { BusinessError } from '@kit.BasicServicesKit'; import { CameraManager, GridLine, @@ -190,11 +191,9 @@ struct Index { // [End registerApplicationStateChange] exitApp() { - try { - this.applicationContext.killAllProcesses(); - } catch (exception) { - Logger.error(TAG, `exitApp failed, code is ${exception.code}, message is ${exception.message}`); - } + this.applicationContext.killAllProcesses().catch((err: BusinessError) => { + Logger.error('showToast', `showToast failed, code is ${err.code}, message is ${err.message}`); + }); } onPreviewStart() { diff --git a/entry/src/main/ets/utils/CommonUtil.ets b/entry/src/main/ets/utils/CommonUtil.ets index 9decaf42f64d78e781cd285e271b16a955ea7212..dc1a899d345721c0acbae23979a93d0e78d1c96f 100644 --- a/entry/src/main/ets/utils/CommonUtil.ets +++ b/entry/src/main/ets/utils/CommonUtil.ets @@ -16,6 +16,7 @@ import { Point } from '@kit.TestKit'; import { camera } from '@kit.CameraKit'; import { display } from '@kit.ArkUI'; +import { BusinessError } from '@kit.BasicServicesKit'; import { Logger } from 'commons'; export function limitNumberInRange(src: number, range: number[]) { @@ -86,16 +87,14 @@ export function showToast( alignment = Alignment.Top, offset: Offset = { dx: 0, dy: 300 } ) { - try { - UIContext.getPromptAction().openToast({ - message, - duration, - alignment, - offset - }); - } catch (exception) { - Logger.error('showToast', `showToast failed, code is ${exception.code}, message is ${exception.message}`); - } + UIContext.getPromptAction().openToast({ + message, + duration, + alignment, + offset + }).catch((err: BusinessError) => { + Logger.error('showToast', `showToast failed, code is ${err.code}, message is ${err.message}`); + }); } // [Start calCameraPoint] diff --git a/entry/src/main/ets/viewmodels/PreviewViewModel.ets b/entry/src/main/ets/viewmodels/PreviewViewModel.ets index 3f87a897049e5c95fb9ceb9aeb12f23b6a70ba59..87dcf0f760c6bd7d7b926c6a1d74a13fd701a141 100644 --- a/entry/src/main/ets/viewmodels/PreviewViewModel.ets +++ b/entry/src/main/ets/viewmodels/PreviewViewModel.ets @@ -17,12 +17,15 @@ import { curves, display } from '@kit.ArkUI'; import { camera } from '@kit.CameraKit'; import WindowUtil from '../utils/WindowUtil'; import CameraConstant from '../constants/Constants'; +import { Logger } from 'commons'; export enum CameraMode { PHOTO, VIDEO } +const TAG = 'PreviewViewModel'; + /** * States and methods related to preview. */ @@ -38,7 +41,7 @@ class PreviewViewModel { rates?: number[] = []; currentRate: number = 0; blurRadius: number = 0; - blurRotation: RotateOptions = { y: 0.5, angle: 0}; + blurRotation: RotateOptions = { y: 0.5, angle: 0 }; constructor(uiContext: UIContext) { this.uiContext = uiContext; @@ -50,6 +53,7 @@ class PreviewViewModel { ? camera.CameraPosition.CAMERA_POSITION_FRONT : camera.CameraPosition.CAMERA_POSITION_BACK; } + // [End isFront] getPreviewRatio() { @@ -67,7 +71,13 @@ class PreviewViewModel { // [Start getProfile] getProfile: (cameraOrientation: number) => camera.Profile = cameraOrientation => { const displaySize: Size = WindowUtil.getMaxDisplaySize(this.getPreviewRatio()); - const displayRotation = 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 displayRotation = (displayDefault?.rotation ?? 0) * 90; const isRevert = (cameraOrientation + displayRotation) % 180 !== 0; return { format: camera.CameraFormat.CAMERA_FORMAT_YUV_420_SP, @@ -77,6 +87,7 @@ class PreviewViewModel { } }; } + // [End getProfile] // [Start setPreviewSize] @@ -88,6 +99,7 @@ class PreviewViewModel { surfaceHeight: displaySize.height }); } + // [End setPreviewSize] getPreviewTop() { diff --git a/entry/src/main/ets/views/OperateButtonsView.ets b/entry/src/main/ets/views/OperateButtonsView.ets index a9a73575239b4b1bc5bdbf374519aeddf961de4a..7de83e3bfa7f117ea8554d6cfd0b0e3338d40f5c 100644 --- a/entry/src/main/ets/views/OperateButtonsView.ets +++ b/entry/src/main/ets/views/OperateButtonsView.ets @@ -15,8 +15,12 @@ import { image } from '@kit.ImageKit'; import { common } from '@kit.AbilityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; import { AVRecorderState, CameraManager, PhotoManager, VideoManager } from 'camera'; import PreviewViewModel from '../viewmodels/PreviewViewModel'; +import { Logger } from 'commons'; + +const TAG = 'OperateButtonsView'; @Component struct OperateButtonsView { @@ -27,7 +31,7 @@ struct OperateButtonsView { @Require photoManager: PhotoManager; @Prop @Require photoDelayTime: number; @Link photoRemainder: number; - private photoDelayTimer:number = 0; + private photoDelayTimer: number = 0; @State thumbnail: image.PixelMap | string = ''; @State thumbnailUrl: string = ''; @Require syncButtonSettings: () => void; @@ -67,15 +71,15 @@ struct OperateButtonsView { if (this.photoDelayTime) { this.isDelayTakePhoto = true; this.photoRemainder = this.photoDelayTime; - this.photoDelayTimer = setInterval(()=>{ + this.photoDelayTimer = setInterval(() => { this.photoRemainder--; - if(this.photoRemainder === 0){ + if (this.photoRemainder === 0) { this.photoManager.capture(this.previewVM.isFront); this.captureClickFlag++; this.isDelayTakePhoto = false; clearTimeout(this.photoDelayTimer); } - },1000) + }, 1000) } else { this.photoManager.capture(this.previewVM.isFront); this.captureClickFlag++; @@ -178,13 +182,15 @@ struct OperateButtonsView { .borderWidth(this.thumbnail ? 1 : 0) .borderColor(Color.White) .clip(true) - .onClick(()=>{ - if(this.thumbnailUrl){ + .onClick(() => { + if (this.thumbnailUrl) { this.context.startAbility({ parameters: { uri: this.thumbnailUrl }, action: 'ohos.want.action.viewData', bundleName: 'com.huawei.hmos.photos', abilityName: 'com.huawei.hmos.photos.MainAbility' + }).catch((err: BusinessError) => { + Logger.error(TAG, `showToast failed, code is ${err.code}, message is ${err.message}`); }); } }) @@ -229,6 +235,7 @@ struct OperateButtonsView { // [EndExclude toggleCameraPositionButton] }) } + // [End toggleCameraPositionButton] build() {