1e41f4b71Sopenharmony_ci# Deferred Photo Delivery (ArkTS) 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ciAs an important feature of the camera, deferred photo delivery enables the system, after receiving a photographing task from an application, to report images of different quality in multiple phases. 4e41f4b71Sopenharmony_ci- In the first phase, the system quickly reports a low-quality image. The application receives a **PhotoAsset** object through the callback. Through this object, the application can call the mediaLibrary APIs to read the image or flush the image to the disk. 5e41f4b71Sopenharmony_ci- In the second phase, the deferred photo delivery subservice performs scheduling based on the system pressure and custom scenarios, and sends the postprocessed original image to the mediaLibrary to replace the low-quality image. 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciDeferred photo delivery further reduces the response delay, delivering a better user experience. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ciTo develop deferred photo delivery, perform the following steps: 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci- Listen for the **photoAssetAvailable** event through **PhotoOutput** to obtain a **PhotoAsset** object of [photoAccessHelper](../../reference/apis-media-library-kit/js-apis-photoAccessHelper.md). 12e41f4b71Sopenharmony_ci- Call the mediaLibrary APIs to read or flush images to the disk through the **PhotoAsset** object. 13e41f4b71Sopenharmony_ci 14e41f4b71Sopenharmony_ci> **NOTE** 15e41f4b71Sopenharmony_ci> 16e41f4b71Sopenharmony_ci> - Deferred photo delivery varies according to the device and type. Therefore, if the device or type is changed, the deferred photo delivery capability may change. 17e41f4b71Sopenharmony_ci> - Applications do not need to proactively enable deferred photo delivery. Instead, the camera framework checks whether the device and type support deferred photo delivery during stream assignment and if so, automatically enables deferred photo delivery. 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci## How to Develop 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ciRead [Camera](../../reference/apis-camera-kit/js-apis-camera.md) for the API reference. 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci1. Import dependencies. Specifically, import the camera, image, and mediaLibrary modules. 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ci ```ts 26e41f4b71Sopenharmony_ci import { camera } from '@kit.CameraKit'; 27e41f4b71Sopenharmony_ci import { BusinessError } from '@kit.BasicServicesKit'; 28e41f4b71Sopenharmony_ci import { common } from '@kit.AbilityKit'; 29e41f4b71Sopenharmony_ci import { photoAccessHelper } from '@kit.MediaLibraryKit'; 30e41f4b71Sopenharmony_ci ``` 31e41f4b71Sopenharmony_ci 32e41f4b71Sopenharmony_ci2. Determine the photo output stream. 33e41f4b71Sopenharmony_ci 34e41f4b71Sopenharmony_ci You can use the **photoProfiles** attribute of the [CameraOutputCapability](../../reference/apis-camera-kit/js-apis-camera.md#cameraoutputcapability) class to obtain the photo output streams supported by the device and use [createPhotoOutput](../../reference/apis-camera-kit/js-apis-camera.md#createphotooutput11) to create a photo output stream. 35e41f4b71Sopenharmony_ci 36e41f4b71Sopenharmony_ci ```ts 37e41f4b71Sopenharmony_ci function getPhotoOutput(cameraManager: camera.CameraManager, 38e41f4b71Sopenharmony_ci cameraOutputCapability: camera.CameraOutputCapability): camera.PhotoOutput | undefined { 39e41f4b71Sopenharmony_ci let photoProfilesArray: Array<camera.Profile> = cameraOutputCapability.photoProfiles; 40e41f4b71Sopenharmony_ci if (!photoProfilesArray) { 41e41f4b71Sopenharmony_ci console.error("createOutput photoProfilesArray == null || undefined"); 42e41f4b71Sopenharmony_ci } 43e41f4b71Sopenharmony_ci let photoOutput: camera.PhotoOutput | undefined = undefined; 44e41f4b71Sopenharmony_ci try { 45e41f4b71Sopenharmony_ci photoOutput = cameraManager.createPhotoOutput(photoProfilesArray[0]); 46e41f4b71Sopenharmony_ci } catch (error) { 47e41f4b71Sopenharmony_ci let err = error as BusinessError; 48e41f4b71Sopenharmony_ci console.error(`Failed to createPhotoOutput. error: ${JSON.stringify(err)}`); 49e41f4b71Sopenharmony_ci } 50e41f4b71Sopenharmony_ci return photoOutput; 51e41f4b71Sopenharmony_ci } 52e41f4b71Sopenharmony_ci ``` 53e41f4b71Sopenharmony_ci 54e41f4b71Sopenharmony_ci3. Set the **photoAssetAvailable** callback. 55e41f4b71Sopenharmony_ci 56e41f4b71Sopenharmony_ci > **NOTE** 57e41f4b71Sopenharmony_ci > If the **photoAssetAvailable** callback has been registered and the **photoAvailable** callback is registered after the session starts, the stream will be restarted. Therefore, you are not advised to register both **photoAvailable** and **photoAssetAvailable**. 58e41f4b71Sopenharmony_ci 59e41f4b71Sopenharmony_ci ```ts 60e41f4b71Sopenharmony_cifunction photoAssetAvailableCallback(err: BusinessError, photoAsset: photoAccessHelper.PhotoAsset): void { 61e41f4b71Sopenharmony_ci if (err) { 62e41f4b71Sopenharmony_ci console.error(`photoAssetAvailable error: ${JSON.stringify(err)}.`); 63e41f4b71Sopenharmony_ci return; 64e41f4b71Sopenharmony_ci } 65e41f4b71Sopenharmony_ci console.info('photoOutPutCallBack photoAssetAvailable'); 66e41f4b71Sopenharmony_ci // You can call mediaLibrary APIs through photoAsset to customize image processing. 67e41f4b71Sopenharmony_ci // Processing method 1: 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. 68e41f4b71Sopenharmony_ci // Processing method 2: Call the mediaLibrary API to request an image and register the buffer callback to receive the low-quality or high-quality image. 69e41f4b71Sopenharmony_ci } 70e41f4b71Sopenharmony_ci 71e41f4b71Sopenharmony_ci function onPhotoOutputPhotoAssetAvailable(photoOutput: camera.PhotoOutput): void { 72e41f4b71Sopenharmony_ci photoOutput.on('photoAssetAvailable', photoAssetAvailableCallback); 73e41f4b71Sopenharmony_ci } 74e41f4b71Sopenharmony_ci ``` 75e41f4b71Sopenharmony_ci 76e41f4b71Sopenharmony_ci For details about the mediaLibrary API used to flush images to the disk, see [saveCameraPhoto](../../reference/apis-media-library-kit/js-apis-photoAccessHelper.md#savecameraphoto12). 77e41f4b71Sopenharmony_ci 78e41f4b71Sopenharmony_ci For details about the mediaLibrary API used to request images, see [requestimagedata](../../reference/apis-media-library-kit/js-apis-photoAccessHelper.md#requestimagedata11) and [ondataprepare](../../reference/apis-media-library-kit/js-apis-photoAccessHelper.md#ondataprepared11). 79e41f4b71Sopenharmony_ci 80e41f4b71Sopenharmony_ci4. The session configuration and photography triggering mode are the same as those in the common photographing mode. For details, see steps 4-5 in [Camera Photographing (ArkTS)](camera-shooting.md). 81e41f4b71Sopenharmony_ci 82e41f4b71Sopenharmony_ci## Status Listening 83e41f4b71Sopenharmony_ci 84e41f4b71Sopenharmony_ciDuring camera application development, you can listen for the status of the photo output stream, including the start of the photo stream, the start and end of the photo frame, and errors of the photo output stream. 85e41f4b71Sopenharmony_ci 86e41f4b71Sopenharmony_ci- Register the **'captureStart'** event to listen for photographing start events. This event can be registered when a **PhotoOutput** instance is created and is triggered when the bottom layer starts exposure for photographing for the first time. The capture ID is returned. 87e41f4b71Sopenharmony_ci 88e41f4b71Sopenharmony_ci ```ts 89e41f4b71Sopenharmony_ci function onPhotoOutputCaptureStart(photoOutput: camera.PhotoOutput): void { 90e41f4b71Sopenharmony_ci photoOutput.on('captureStartWithInfo', (err: BusinessError, captureStartInfo: camera.CaptureStartInfo) => { 91e41f4b71Sopenharmony_ci if (err !== undefined && err.code !== 0) { 92e41f4b71Sopenharmony_ci return; 93e41f4b71Sopenharmony_ci } 94e41f4b71Sopenharmony_ci console.info(`photo capture started, captureId : ${captureStartInfo.captureId}`); 95e41f4b71Sopenharmony_ci }); 96e41f4b71Sopenharmony_ci } 97e41f4b71Sopenharmony_ci ``` 98e41f4b71Sopenharmony_ci 99e41f4b71Sopenharmony_ci- Register the **'captureEnd'** event to listen for photographing end events. This event can be registered when a **PhotoOutput** instance is created and is triggered when the photographing is complete. [CaptureEndInfo](../../reference/apis-camera-kit/js-apis-camera.md#captureendinfo) is returned. 100e41f4b71Sopenharmony_ci 101e41f4b71Sopenharmony_ci ```ts 102e41f4b71Sopenharmony_ci function onPhotoOutputCaptureEnd(photoOutput: camera.PhotoOutput): void { 103e41f4b71Sopenharmony_ci photoOutput.on('captureEnd', (err: BusinessError, captureEndInfo: camera.CaptureEndInfo) => { 104e41f4b71Sopenharmony_ci if (err !== undefined && err.code !== 0) { 105e41f4b71Sopenharmony_ci return; 106e41f4b71Sopenharmony_ci } 107e41f4b71Sopenharmony_ci console.info(`photo capture end, captureId : ${captureEndInfo.captureId}`); 108e41f4b71Sopenharmony_ci console.info(`frameCount : ${captureEndInfo.frameCount}`); 109e41f4b71Sopenharmony_ci }); 110e41f4b71Sopenharmony_ci } 111e41f4b71Sopenharmony_ci ``` 112e41f4b71Sopenharmony_ci 113e41f4b71Sopenharmony_ci- Register the **'error'** event to listen for photo output errors. The callback function returns an error code when an API is incorrectly used. For details about the error code types, see [CameraErrorCode](../../reference/apis-camera-kit/js-apis-camera.md#cameraerrorcode). 114e41f4b71Sopenharmony_ci 115e41f4b71Sopenharmony_ci ```ts 116e41f4b71Sopenharmony_ci function onPhotoOutputError(photoOutput: camera.PhotoOutput): void { 117e41f4b71Sopenharmony_ci photoOutput.on('error', (error: BusinessError) => { 118e41f4b71Sopenharmony_ci console.error(`Photo output error code: ${error.code}`); 119e41f4b71Sopenharmony_ci }); 120e41f4b71Sopenharmony_ci } 121e41f4b71Sopenharmony_ci ``` 122