1# Practices for Camera Recovery from the Background (ArkTS) 2<!--Kit: Camera Kit--> 3<!--Subsystem: Multimedia--> 4<!--Owner: @qano--> 5<!--SE: @leo_ysl--> 6<!--TSE: @xchaosioda--> 7 8This sample demonstrates the complete process for transitioning a camera application from the background to the foreground, providing you with a clear understanding of the entire sequence of API calls. 9 10The state changes during the camera application's transition between foreground and background are as follows: 11- When the camera application transitions to the background, it is forcibly disconnected due to security policies, and the camera status callback returns the camera available state, indicating that the camera device is now idle. 12- When the camera application returns to the foreground, the camera status callback returns the camera unavailable state, indicating that the camera device is now busy. 13- Upon transitioning from the background to the foreground, the camera application must restart the preview stream, photo stream, and camera session management accordingly. 14 15Before referring to the sample code, you are advised to read [Camera Device Management](camera-device-management.md), [Device Input Management](camera-device-input.md), [Camera Session Management](camera-session-management.md), and other related topics in [Camera Development (ArkTS)](camera-preparation.md). 16 17## Development Process 18 19The figure below shows the process of transitioning a camera application from the background to the foreground. 20 21 22 23## Sample 24 25For details about how to obtain the context, see [Obtaining the Context of UIAbility](../../application-models/uiability-usage.md#obtaining-the-context-of-uiability). 26 27During the transition of the camera application from the background to the foreground, call the **onPageShow** callback function to re-initialize the camera device. 28 29 ```ts 30 import { camera } from '@kit.CameraKit'; 31 import { BusinessError } from '@kit.BasicServicesKit'; 32 import { common } from '@kit.AbilityKit'; 33 34 let context: common.BaseContext; 35 let surfaceId: string = ''; 36 async function onPageShow(): Promise<void> { 37 // Reinitialize the camera when the application transitions from the background to the foreground. 38 await initCamera(context, surfaceId); 39 } 40 41 async function initCamera(baseContext: common.BaseContext, surfaceId: string): Promise<void> { 42 console.info('onForeGround recovery begin.'); 43 let cameraManager: camera.CameraManager = camera.getCameraManager(context); 44 if (!cameraManager) { 45 console.error("camera.getCameraManager error"); 46 return; 47 } 48 // Listen for camera status changes. 49 cameraManager.on('cameraStatus', (err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) => { 50 if (err !== undefined && err.code !== 0) { 51 console.error('cameraStatus with errorCode = ' + err.code); 52 return; 53 } 54 console.info(`camera : ${cameraStatusInfo.camera.cameraId}`); 55 console.info(`status: ${cameraStatusInfo.status}`); 56 }); 57 58 // Obtain the camera list. 59 let cameraArray: Array<camera.CameraDevice> = cameraManager.getSupportedCameras(); 60 if (cameraArray.length <= 0) { 61 console.error("cameraManager.getSupportedCameras error"); 62 return; 63 } 64 65 for (let index = 0; index < cameraArray.length; index++) { 66 console.info('cameraId : ' + cameraArray[index].cameraId); // Obtain the camera ID. 67 console.info('cameraPosition : ' + cameraArray[index].cameraPosition); // Obtain the camera position. 68 console.info('cameraType : ' + cameraArray[index].cameraType); // Obtain the camera type. 69 console.info('connectionType : ' + cameraArray[index].connectionType); // Obtain the camera connection type. 70 } 71 72 // Create a camera input stream. 73 let cameraInput: camera.CameraInput | undefined = undefined; 74 try { 75 cameraInput = cameraManager.createCameraInput(cameraArray[0]); 76 } catch (error) { 77 let err = error as BusinessError; 78 console.error('Failed to createCameraInput errorCode = ' + err.code); 79 } 80 if (cameraInput === undefined) { 81 return; 82 } 83 84 // Listen for camera input errors. 85 let cameraDevice: camera.CameraDevice = cameraArray[0]; 86 cameraInput.on('error', cameraDevice, (error: BusinessError) => { 87 console.error(`Camera input error code: ${error.code}`); 88 }); 89 90 // Open the camera. 91 await cameraInput.open(); 92 93 // Obtain the supported modes. 94 let sceneModes: Array<camera.SceneMode> = cameraManager.getSupportedSceneModes(cameraArray[0]); 95 let isSupportPhotoMode: boolean = sceneModes.indexOf(camera.SceneMode.NORMAL_PHOTO) >= 0; 96 if (!isSupportPhotoMode) { 97 console.error('photo mode not support'); 98 return; 99 } 100 // Obtain the output stream capability supported by the camera. 101 let cameraOutputCap: camera.CameraOutputCapability = cameraManager.getSupportedOutputCapability(cameraArray[0], camera.SceneMode.NORMAL_PHOTO); 102 if (!cameraOutputCap) { 103 console.error("cameraManager.getSupportedOutputCapability error"); 104 return; 105 } 106 console.info("outputCapability: " + JSON.stringify(cameraOutputCap)); 107 108 let previewProfilesArray: Array<camera.Profile> = cameraOutputCap.previewProfiles; 109 if (!previewProfilesArray) { 110 console.error("createOutput previewProfilesArray == null || undefined"); 111 } 112 113 let photoProfilesArray: Array<camera.Profile> = cameraOutputCap.photoProfiles; 114 if (!photoProfilesArray) { 115 console.error("createOutput photoProfilesArray == null || undefined"); 116 } 117 118 // Create a preview output stream. For details about the surfaceId parameter, see the XComponent. The preview stream uses the surface provided by the XComponent. 119 let previewOutput: camera.PreviewOutput | undefined = undefined; 120 try { 121 previewOutput = cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId); 122 } catch (error) { 123 let err = error as BusinessError; 124 console.error(`Failed to create the PreviewOutput instance. error code: ${err.code}`); 125 } 126 if (previewOutput === undefined) { 127 return; 128 } 129 // Listen for preview output errors. 130 previewOutput.on('error', (error: BusinessError) => { 131 console.error(`Preview output error code: ${error.code}`); 132 }); 133 134 // Create a photo output stream. 135 let photoOutput: camera.PhotoOutput | undefined = undefined; 136 try { 137 photoOutput = cameraManager.createPhotoOutput(photoProfilesArray[0]); 138 } catch (error) { 139 let err = error as BusinessError; 140 console.error('Failed to createPhotoOutput errorCode = ' + err.code); 141 } 142 if (photoOutput === undefined) { 143 return; 144 } 145 146 // Create a session. 147 let photoSession: camera.PhotoSession | undefined = undefined; 148 try { 149 photoSession = cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO) as camera.PhotoSession; 150 } catch (error) { 151 let err = error as BusinessError; 152 console.error('Failed to create the session instance. errorCode = ' + err.code); 153 } 154 if (photoSession === undefined) { 155 return; 156 } 157 // Listen for session errors. 158 photoSession.on('error', (error: BusinessError) => { 159 console.error(`Capture session error code: ${error.code}`); 160 }); 161 162 // Start configuration for the session. 163 try { 164 photoSession.beginConfig(); 165 } catch (error) { 166 let err = error as BusinessError; 167 console.error('Failed to beginConfig. errorCode = ' + err.code); 168 } 169 170 // Add the camera input stream to the session. 171 try { 172 photoSession.addInput(cameraInput); 173 } catch (error) { 174 let err = error as BusinessError; 175 console.error('Failed to addInput. errorCode = ' + err.code); 176 } 177 178 // Add the preview output stream to the session. 179 try { 180 photoSession.addOutput(previewOutput); 181 } catch (error) { 182 let err = error as BusinessError; 183 console.error('Failed to addOutput(previewOutput). errorCode = ' + err.code); 184 } 185 186 // Add the photo output stream to the session. 187 try { 188 photoSession.addOutput(photoOutput); 189 } catch (error) { 190 let err = error as BusinessError; 191 console.error('Failed to addOutput(photoOutput). errorCode = ' + err.code); 192 } 193 194 // Commit the session configuration. 195 await photoSession.commitConfig(); 196 197 // Start the session. 198 await photoSession.start().then(() => { 199 console.info('Promise returned to indicate the session start success.'); 200 }); 201 // Check whether the camera has flash. 202 let flashStatus: boolean = false; 203 try { 204 flashStatus = photoSession.hasFlash(); 205 } catch (error) { 206 let err = error as BusinessError; 207 console.error('Failed to hasFlash. errorCode = ' + err.code); 208 } 209 console.info('Returned with the flash light support status:' + flashStatus); 210 211 if (flashStatus) { 212 // Check whether the auto flash mode is supported. 213 let flashModeStatus: boolean = false; 214 try { 215 let status: boolean = photoSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO); 216 flashModeStatus = status; 217 } catch (error) { 218 let err = error as BusinessError; 219 console.error('Failed to check whether the flash mode is supported. errorCode = ' + err.code); 220 } 221 if(flashModeStatus) { 222 // Set the flash mode to auto. 223 try { 224 photoSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO); 225 } catch (error) { 226 let err = error as BusinessError; 227 console.error('Failed to set the flash mode. errorCode = ' + err.code); 228 } 229 } 230 } 231 232 // Check whether the continuous auto focus is supported. 233 let focusModeStatus: boolean = false; 234 try { 235 let status: boolean = photoSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO); 236 focusModeStatus = status; 237 } catch (error) { 238 let err = error as BusinessError; 239 console.error('Failed to check whether the focus mode is supported. errorCode = ' + err.code); 240 } 241 242 if (focusModeStatus) { 243 // Set the focus mode to continuous auto focus. 244 try { 245 photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO); 246 } catch (error) { 247 let err = error as BusinessError; 248 console.error('Failed to set the focus mode. errorCode = ' + err.code); 249 } 250 } 251 252 // Obtain the zoom ratio range supported by the camera. 253 let zoomRatioRange: Array<number> = []; 254 try { 255 zoomRatioRange = photoSession.getZoomRatioRange(); 256 } catch (error) { 257 let err = error as BusinessError; 258 console.error('Failed to get the zoom ratio range. errorCode = ' + err.code); 259 } 260 if (zoomRatioRange.length <= 0) { 261 return; 262 } 263 // Set a zoom ratio. 264 try { 265 photoSession.setZoomRatio(zoomRatioRange[0]); 266 } catch (error) { 267 let err = error as BusinessError; 268 console.error('Failed to set the zoom ratio value. errorCode = ' + err.code); 269 } 270 let photoCaptureSetting: camera.PhotoCaptureSetting = { 271 quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // Set the photo quality to high. 272 rotation: camera.ImageRotation.ROTATION_0 // Set the rotation angle of the photo to 0. 273 } 274 // Use the current photo capture settings to take photos. 275 photoOutput.capture(photoCaptureSetting, (err: BusinessError) => { 276 if (err) { 277 console.error(`Failed to capture the photo ${err.message}`); 278 return; 279 } 280 console.info('Callback invoked to indicate the photo capture request success.'); 281 }); 282 283 console.info('onForeGround recovery end.'); 284 } 285 ``` 286