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