1# Deferred Photo Delivery Sample (ArkTS) 2 3This topic provides sample code that covers the complete deferred photo delivery process to help you understand the complete API calling sequence. 4 5Before referring to the sample code, you are advised to read [Deferred Photo Delivery (ArkTS)](camera-deferred-capture.md), [Device Input Management](camera-device-input.md), [Camera Session Management](camera-session-management.md), and [Camera Photographing](camera-shooting.md). 6 7## Development Process 8 9After obtaining the output stream capabilities supported by the camera, create a photo stream. The development process is as follows: 10 11 12 13## Sample Code 14 15For details about how to obtain the context, see [Obtaining the Context of UIAbility](../../application-models/uiability-usage.md#obtaining-the-context-of-uiability). 16 17```ts 18import { camera } from '@kit.CameraKit'; 19import { BusinessError } from '@kit.BasicServicesKit'; 20import { common } from '@kit.AbilityKit'; 21import { photoAccessHelper } from '@kit.MediaLibraryKit'; 22 23let context = getContext(this); 24let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context); 25 26class MediaDataHandler implements photoAccessHelper.MediaAssetDataHandler<ArrayBuffer> { 27 onDataPrepared(data: ArrayBuffer) { 28 if (data === undefined) { 29 console.error('Error occurred when preparing data'); 30 return; 31 } 32 console.info('on image data prepared'); 33 } 34} 35 36async function mediaLibRequestBuffer(photoAsset: photoAccessHelper.PhotoAsset) { 37 let requestOptions: photoAccessHelper.RequestOptions = { 38 deliveryMode: photoAccessHelper.DeliveryMode.HIGH_QUALITY_MODE, 39 } 40 const handler = new MediaDataHandler(); 41 await photoAccessHelper.MediaAssetManager.requestImageData(context, photoAsset, requestOptions, handler); 42 console.info('requestImageData successfully'); 43} 44 45async function mediaLibSavePhoto(photoAsset: photoAccessHelper.PhotoAsset): Promise<void> { 46 try { 47 let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest = new photoAccessHelper.MediaAssetChangeRequest(photoAsset); 48 assetChangeRequest.saveCameraPhoto(); 49 await phAccessHelper.applyChanges(assetChangeRequest); 50 console.info('apply saveCameraPhoto successfully'); 51 } catch (err) { 52 console.error(`apply saveCameraPhoto failed with error: ${err.code}, ${err.message}`); 53 } 54} 55 56function setPhotoOutputCb(photoOutput: camera.PhotoOutput): void { 57 // After the callback is set, call capture() of photoOutput to trigger the callback upon the receiving of a low-quality image. 58 photoOutput.on('photoAssetAvailable', (err: BusinessError, photoAsset: photoAccessHelper.PhotoAsset): void => { 59 console.info('getPhotoAsset start'); 60 console.info(`err: ${JSON.stringify(err)}`); 61 if ((err !== undefined && err.code !== 0) || photoAsset === undefined) { 62 console.error('getPhotoAsset failed'); 63 return; 64 } 65 // Call the mediaLibrary flush API to save the low-quality image in the first phase. After the real image in the second phase is ready, the mediaLibrary proactively replaces the image flushed. 66 mediaLibSavePhoto(photoAsset); 67 // Call the mediaLibrary API to register the buffer callback to receive low-quality or high-quality images for custom processing. 68 mediaLibRequestBuffer(photoAsset); 69 }); 70} 71 72async function deferredCaptureCase(baseContext: common.BaseContext, surfaceId: string): Promise<void> { 73 // Create a CameraManager object. 74 let cameraManager: camera.CameraManager = camera.getCameraManager(baseContext); 75 if (!cameraManager) { 76 console.error("camera.getCameraManager error"); 77 return; 78 } 79 // Listen for camera status changes. 80 cameraManager.on('cameraStatus', (err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) => { 81 if (err !== undefined && err.code !== 0) { 82 console.error('cameraStatus with errorCode = ' + err.code); 83 return; 84 } 85 console.info(`camera : ${cameraStatusInfo.camera.cameraId}`); 86 console.info(`status: ${cameraStatusInfo.status}`); 87 }); 88 89 // Obtain the camera list. 90 let cameraArray: Array<camera.CameraDevice> = cameraManager.getSupportedCameras(); 91 if (cameraArray.length <= 0) { 92 console.error("cameraManager.getSupportedCameras error"); 93 return; 94 } 95 96 for (let index = 0; index < cameraArray.length; index++) { 97 console.info('cameraId : ' + cameraArray[index].cameraId); // Obtain the camera ID. 98 console.info('cameraPosition : ' + cameraArray[index].cameraPosition); // Obtain the camera position. 99 console.info('cameraType : ' + cameraArray[index].cameraType); // Obtain the camera type. 100 console.info('connectionType : ' + cameraArray[index].connectionType); // Obtain the camera connection type. 101 } 102 103 // Create a camera input stream. 104 let cameraInput: camera.CameraInput | undefined = undefined; 105 try { 106 cameraInput = cameraManager.createCameraInput(cameraArray[0]); 107 } catch (error) { 108 let err = error as BusinessError; 109 console.error('Failed to createCameraInput errorCode = ' + err.code); 110 } 111 if (cameraInput === undefined) { 112 return; 113 } 114 115 // Listen for camera input errors. 116 let cameraDevice: camera.CameraDevice = cameraArray[0]; 117 cameraInput.on('error', cameraDevice, (error: BusinessError) => { 118 console.error(`Camera input error code: ${error.code}`); 119 }) 120 121 // Open a camera. 122 await cameraInput.open(); 123 124 // Obtain the supported modes. 125 let sceneModes: Array<camera.SceneMode> = cameraManager.getSupportedSceneModes(cameraArray[0]); 126 let isSupportPhotoMode: boolean = sceneModes.indexOf(camera.SceneMode.NORMAL_PHOTO) >= 0; 127 if (!isSupportPhotoMode) { 128 console.error('photo mode not support'); 129 return; 130 } 131 // Obtain the output streams supported by the camera. 132 let cameraOutputCap: camera.CameraOutputCapability = cameraManager.getSupportedOutputCapability(cameraArray[0], camera.SceneMode.NORMAL_PHOTO); 133 if (!cameraOutputCap) { 134 console.error("cameraManager.getSupportedOutputCapability error"); 135 return; 136 } 137 console.info("outputCapability: " + JSON.stringify(cameraOutputCap)); 138 139 let previewProfilesArray: Array<camera.Profile> = cameraOutputCap.previewProfiles; 140 if (!previewProfilesArray) { 141 console.error("createOutput previewProfilesArray == null || undefined"); 142 } 143 144 let photoProfilesArray: Array<camera.Profile> = cameraOutputCap.photoProfiles; 145 if (!photoProfilesArray) { 146 console.error("createOutput photoProfilesArray == null || undefined"); 147 } 148 149 // Create a preview output stream. For details about the surfaceId parameter, see the XComponent. The preview stream uses the surface provided by the XComponent. 150 let previewOutput: camera.PreviewOutput | undefined = undefined; 151 try { 152 previewOutput = cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId); 153 } catch (error) { 154 let err = error as BusinessError; 155 console.error(`Failed to create the PreviewOutput instance. error code: ${err.code}`); 156 } 157 if (previewOutput === undefined) { 158 return; 159 } 160 // Listen for preview output errors. 161 previewOutput.on('error', (error: BusinessError) => { 162 console.error(`Preview output error code: ${error.code}`); 163 }); 164 165 // Create a photo output stream. 166 let photoOutput: camera.PhotoOutput | undefined = undefined; 167 try { 168 photoOutput = cameraManager.createPhotoOutput(photoProfilesArray[0]); 169 } catch (error) { 170 let err = error as BusinessError; 171 console.error('Failed to createPhotoOutput errorCode = ' + err.code); 172 } 173 if (photoOutput === undefined) { 174 return; 175 } 176 177 // Register the photoAssetAvailable callback. 178 setPhotoOutputCb(photoOutput); 179 180 // Create a session. 181 let photoSession: camera.PhotoSession | undefined = undefined; 182 try { 183 photoSession = cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO) as camera.PhotoSession; 184 } catch (error) { 185 let err = error as BusinessError; 186 console.error('Failed to create the session instance. errorCode = ' + err.code); 187 } 188 if (photoSession === undefined) { 189 return; 190 } 191 // Listen for session errors. 192 photoSession.on('error', (error: BusinessError) => { 193 console.error(`Capture session error code: ${error.code}`); 194 }); 195 196 // Start configuration for the session. 197 try { 198 photoSession.beginConfig(); 199 } catch (error) { 200 let err = error as BusinessError; 201 console.error('Failed to beginConfig. errorCode = ' + err.code); 202 } 203 204 // Add the camera input stream to the session. 205 try { 206 photoSession.addInput(cameraInput); 207 } catch (error) { 208 let err = error as BusinessError; 209 console.error('Failed to addInput. errorCode = ' + err.code); 210 } 211 212 // Add the preview output stream to the session. 213 try { 214 photoSession.addOutput(previewOutput); 215 } catch (error) { 216 let err = error as BusinessError; 217 console.error('Failed to addOutput(previewOutput). errorCode = ' + err.code); 218 } 219 220 // Add the photo output stream to the session. 221 try { 222 photoSession.addOutput(photoOutput); 223 } catch (error) { 224 let err = error as BusinessError; 225 console.error('Failed to addOutput(photoOutput). errorCode = ' + err.code); 226 } 227 228 // Commit the session configuration. 229 await photoSession.commitConfig(); 230 231 // Start the session. 232 await photoSession.start().then(() => { 233 console.info('Promise returned to indicate the session start success.'); 234 }); 235 // Check whether the camera has flash. 236 let flashStatus: boolean = false; 237 try { 238 flashStatus = photoSession.hasFlash(); 239 } catch (error) { 240 let err = error as BusinessError; 241 console.error('Failed to hasFlash. errorCode = ' + err.code); 242 } 243 console.info('Returned with the flash light support status:' + flashStatus); 244 245 if (flashStatus) { 246 // Check whether the auto flash mode is supported. 247 let flashModeStatus: boolean = false; 248 try { 249 let status: boolean = photoSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO); 250 flashModeStatus = status; 251 } catch (error) { 252 let err = error as BusinessError; 253 console.error('Failed to check whether the flash mode is supported. errorCode = ' + err.code); 254 } 255 if(flashModeStatus) { 256 // Set the flash mode to auto. 257 try { 258 photoSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO); 259 } catch (error) { 260 let err = error as BusinessError; 261 console.error('Failed to set the flash mode. errorCode = ' + err.code); 262 } 263 } 264 } 265 266 // Check whether the continuous auto focus is supported. 267 let focusModeStatus: boolean = false; 268 try { 269 let status: boolean = photoSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO); 270 focusModeStatus = status; 271 } catch (error) { 272 let err = error as BusinessError; 273 console.error('Failed to check whether the focus mode is supported. errorCode = ' + err.code); 274 } 275 276 if (focusModeStatus) { 277 // Set the focus mode to continuous auto focus. 278 try { 279 photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO); 280 } catch (error) { 281 let err = error as BusinessError; 282 console.error('Failed to set the focus mode. errorCode = ' + err.code); 283 } 284 } 285 286 // Obtain the zoom ratio range supported by the camera. 287 let zoomRatioRange: Array<number> = []; 288 try { 289 zoomRatioRange = photoSession.getZoomRatioRange(); 290 } catch (error) { 291 let err = error as BusinessError; 292 console.error('Failed to get the zoom ratio range. errorCode = ' + err.code); 293 } 294 if (zoomRatioRange.length <= 0) { 295 return; 296 } 297 // Set a zoom ratio. 298 try { 299 photoSession.setZoomRatio(zoomRatioRange[0]); 300 } catch (error) { 301 let err = error as BusinessError; 302 console.error('Failed to set the zoom ratio value. errorCode = ' + err.code); 303 } 304 let photoCaptureSetting: camera.PhotoCaptureSetting = { 305 quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // Set the photo quality to high. 306 rotation: camera.ImageRotation.ROTATION_0 // Set the rotation angle of the photo to 0. 307 } 308 // Use the current photographing settings to take photos. 309 photoOutput.capture(photoCaptureSetting, (err: BusinessError) => { 310 if (err) { 311 console.error(`Failed to capture the photo ${err.message}`); 312 return; 313 } 314 console.info('Callback invoked to indicate the photo capture request success.'); 315 }); 316 // Stop the session. 317 photoSession.stop(); 318 319 // Release the camera input stream. 320 cameraInput.close(); 321 322 // Release the preview output stream. 323 previewOutput.release(); 324 325 // Release the photo output stream. 326 photoOutput.release(); 327 328 // Release the session. 329 photoSession.release(); 330 331 // Set the session to null. 332 photoSession = undefined; 333} 334``` 335