• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![Camera Background recovery processing](figures/camera-background-recovery.png)
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