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