capacitor: bug: Camera plugin restart app when take a photo

Bug Report

Capacitor Version

npx cap doctor output: Capacitor Doctor 💊

Latest Dependencies:

@capacitor/cli: 2.1.0

@capacitor/core: 2.1.0

@capacitor/android: 2.1.0

@capacitor/electron: 2.1.0

@capacitor/ios: 2.1.0

Installed Dependencies:

@capacitor/electron not installed

@capacitor/cli 2.1.0

@capacitor/android 2.1.0

@capacitor/ios 2.1.0

@capacitor/core 2.1.0

[success] Android looking great! 👌 Found 3 Capacitor plugins for ios: @codetrix-studio/capacitor-google-auth (2.1.1) @rdlabo/capacitor-facebook-login (2.0.2) cordova-plugin-nativegeocoder (3.4.1) [success] iOS looking great! 👌

Affected Platform(s)

  • Android
  • iOS
  • Electron
  • Web

Current Behavior

When calling the method const image = await Camera.getPhoto ({        quality: 70,        allowEditing: false,        resultType: CameraResultType.Uri,        promptLabelHeader: ‘Camera’,      promptLabelCancel: ‘Cancel’,      promptLabelPhoto: ‘Image Gallery’,      promptLabelPicture: ‘Take Photo’      });

The application to take photography is shown. When the photo is taken, the application restarts. Reviewing in Android Studio, the app process dies, and another instance of the app opens.

Expected Behavior

The application takes the photo and returns the url to the controller without restarting the app.

Sample Code or Sample Application Repo

const image = await Camera.getPhoto ({        quality: 70,        allowEditing: false,        resultType: CameraResultType.Uri,        promptLabelHeader: ‘Camera’,      promptLabelCancel: ‘Cancel’,      promptLabelPhoto: ‘Image Gallery’,      promptLabelPicture: ‘Take Photo’      });

Reproduction Steps

Other Technical Details

npm --version output: 6.13.7

node --version output: v10.15.1

pod --version output (iOS issues only):

Other Information

In this video you can see how when trying to take a photo from a xiaomi, the app process stops and restarts after taking the photo. Sometimes the method works correctly. YouTube link: https://youtu.be/GfvSIJ5SpwE

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 7
  • Comments: 36 (3 by maintainers)

Most upvoted comments

I’m not affiliated with the Capacitor team, but my personal opinion is it will never get addressed. Some phone manufacturers are doing aggressive memory management and they would terminate suspended apps very quickly to save memory. Since an Android intent is called in this case which practically launches the camera app it pushes your Capacitor app to the background and chances are it will be terminated by the OS sooner or later. I almost abandoned the Ionic platform because of this problem and looked into the way Flutter and React Native are handling this and found they suffer from the same issue. You can switch to native Android development but probably there is a good reason for you to use a hybrid framework so it is not an ideal solution. You can listen to the appRestoredResult event as some of the commenters mentioned above but honestly I’m taking photos in the middle of complex workflows so I did not like the idea. That’s when I came across the camera-preview plugin, actually I’m using the Cordova version but as far as I can see there is a Capacitor version too. The advantage of using that plugin is it is running on the main thread of your app so it won’t kill the app, however you need to provide a camera GUI which is a cumbersome task to do given absolutely positioned elements, different screen sizes, portrait/landscape orientation changes and devices with/without notches. Anyway, we put some time into developing a GUI, it is far from being perfect but at least we rarely get a camera crash report. Other downside is the camera preview plugin can only recognize front and back cameras and no option to cycle through a number of back cameras (close-up, telephoto, etc). If you can live with these limitations and willing to develop a custom camera GUI you can give the camera-preview plugin a go. Otherwise I suggest leveraging a state management solution and the appRestoredResult event.

We recently started using an Android Foreground service (docs) and the feedback from our customers is quite positive:

import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
import { ForegroundService } from '@capawesome-team/capacitor-android-foreground-service';

public async takePhoto() {
    await ForegroundService.startForegroundService({
      id: 1,
      title: 'Taking Photo',
      body: 'MyApp is running',
      smallIcon: 'ic_launcher',
    });
    const { path } = await Camera.getPhoto({
      source: CameraSource.Camera,
      resultType: CameraResultType.Uri,
    });
    await ForegroundService.stopForegroundService();
    return path;
}

We have not received any other complaints so far. Unfortunately, we were never able to reproduce it ourselves since we did not have the same devices (they have really old devices) with the same configurations. So we tried different things for quite a long time. Perhaps this helps someone.

Edit: The camera-preview plugin is a great solution, but we were not satisfied with the UX (probably we should have put more work into the UI).

Hello. Has anyone found a solution for this? I’m experiencing the same issue when taking a photo or picking a photo from the Library collection. The app restarting itself. I’ve tested on Emulators, Galaxy Tab A, Galaxy S10+

i solved this with foreground-service worked in capacitor v5 https://ionicframework.com/docs/v5/native/foreground-service

then add ForegroundService in providers at app.modules.ts

This appears to happen on older iOS devices as well, independent of Capacitor verisons: https://github.com/ionic-team/capacitor/issues/2897 … that issue has a sample project that intermittently repro’s the bug.

This isn’t actually a bug but the way Android is supposed to work; it only happens in conditions where memory is limited.

This is documented with a hint for the correct work around as mentioned here: #2931 (comment)

For some almost cut n paste ready snippets see my gist over here: https://gist.github.com/squio/1ff10bcca2aa1427a919e1c35cbc82fb - works for our app (in production).

It worked perfectly for me, thank you very much for the contribution.

@khindemit it will crash at some point even by locking, at least that is what we experienced on our app.

https://capacitor.ionicframework.com/docs/apis/camera There is information about this in the documentation

Additionally, because the Camera API launches a separate Activity to handle taking the photo, you should listen for appRestoredResult in the App plugin to handle any camera data that was sent in the case your app was terminated by the operating system while the Activity was running.

I tried the appRestoredResult event, but it is impossible to obtain the page where user is taken the picture. The app has several pages where user can take photos.

Yes, I hate this…

You need to serialize the app state by yourself. I made a method called OnBeforePhoto, I use it to serialize what I want to keep(Url, Modals, Methods, etc …) in localstorage. Then if the app returns something in the appRestoredResult I check the localstorage to get the previous state of the app.