Open fititrick opened 4 years ago
How much memory does your device have? Are there any crash logs in logcat?
No crash log in the logcat.
It is a XIAOMI REDMI NOTE 8T with 3 GB of ram
I have noticed phones with low memory ~2GB experience this exact behaviour, so possibly a OutOfMemory exception? You can debug the application and step through lines in returnResult() method. It's unusal for exception to not show up in logs, maybe don't use your app process as filter in logcat; let it display system wide logs and try to crash the application.
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.
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 have noticed phones with low memory ~2GB experience this exact behaviour, so possibly a OutOfMemory exception? You can debug the application and step through lines in returnResult() method. It's unusal for exception to not show up in logs, maybe don't use your app process as filter in logcat; let it display system wide logs and try to crash the application.
I have copied the logcat for you. Just the process when i clicked to the capture button, until the app process is dead.
Error logcat:
2020-05-27 15:18:53.935 606-29140/? E/CamComm1.0-MD: Mismatched tag type when updating entry enable (-2146762752) of type byte; got type int32 data instead
2020-05-27 15:18:53.935 606-29140/? E/CamComm1.0-MD: Mismatched tag type when updating entry is_main (-2146762751) of type byte; got type int32 data instead
2020-05-27 15:18:54.164 606-9481/? E/mm-camera:
Verbose logcat:
2020-05-27 15:18:52.634 9668-9668/? D/SigquitBasedANRDetector: Registered
2020-05-27 15:18:52.653 9668-9668/? D/SigquitBasedANRDetector: Initialized
2020-05-27 15:18:52.662 7401-7815/? I/VendorTagDescriptor: lookupTag: Tag name 'MiAlgoAsdVersion' does not exist.
2020-05-27 15:18:52.662 7401-7815/? W/VendorTagHelper: caution: failed to try get value from camera characteristics:
--------- beginning of system
2020-05-27 15:18:53.864 1677-2673/? W/MiuiGesturePointerEventListener: onActionDown end: mGestureStatus = 0
2020-05-27 15:18:53.865 7401-7401/? D/ViberatorContext: performSnapClick: ignore...
2020-05-27 15:18:53.867 7401-7401/? D/CAM_CameraSnapView: snap click action_down
2020-05-27 15:18:53.867 7401-7401/? D/CAM_FragmentBottomActio: onSnapPrepare
2020-05-27 15:18:53.871 9668-9773/? D/WM-PackageManagerHelper: androidx.work.impl.background.systemjob.SystemJobService enabled
2020-05-27 15:18:53.871 9668-9773/? D/WM-Schedulers: Created SystemJobScheduler and enabled SystemJobService
2020-05-27 15:18:53.874 7401-7815/? I/VendorTagDescriptor: lookupTag: Tag name 'MiAlgoAsdVersion' does not exist.
2020-05-27 15:18:53.874 7401-7815/? W/VendorTagHelper: caution: failed to try get value from camera characteristics:
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.
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.
This apprestoredResult only should be used on low-end devices, which don't have large memory.
but, it is happening on the device with 3gb RAM also. is it not a bug in a capacitor?
This apprestoredResult only should be used on low-end devices, which don't have large memory.
but, it is happening on the device with 3gb RAM also. is it not a bug in a capacitor?
It is an android behavior, and manufacturers can modify this behavior. In our app it happens a lot with the Moto G7(4GB of RAM) but it doesn't happen in the Galaxy J5 PRO(2GB of RAM)
I can confirm this has happened to me Xiaomi 8a & Huawei P9 Lite, android 6
will this be addressed? All my components which uses camera are broken right now, my clients can't use camera functionality because of this. I'm not using base64 or anything
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.
@battika I'm assuming your app has support for taking pictures, but doesn't allow users to pick existing ones from storage. That flow faces the same issue and I don't think there's an alternate solution like you've implemented with camera-preview plugin.
I think this should be highlighted more prominently in the documentation along with suggestions on how to actually manage it.
@a-uz you are correct, I only allow users to take pictures as my app requires real-time pictures. Using the gallery option is most likely having the same issue however there are other plugins for image picking too. I will actually start experimenting with the appRestoredResult event and NGXS state management once I start converting the my Ionic 2 app to the latest version. Hope I can come up with a solution good enough for the client. However on one occasion users need to take 4 different pictures on a single page and I'm not sure how my app will look UX-wise if it restarts 4 times on a single page :) Anyway, I shall see...
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've hit this one too during app development. While I have state management set up, I still end up losing the photo that was taken when the app restarted and I've tried putting listeners on the 'appRestoredResult' and it's not giving me any data back according to the logs.
Going to try the Preview approach since I don't need library support for photos.
I am facing similar issue https://github.com/ionic-team/capacitor/issues/4130
@joaolnpr Have you resolved this issue ?
This issues will never gets fixed, it has been around for years and it is one of the main drawbacks of the hybrid approach. Once the app goes into the background,
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.
@battika 100% true, on Cordova this bug has been around for years but it cannot be fixed. Once the activity goes in the background, it is goodnight. I am curious to know why Flutter for example faces the same issue. Is it calling the camera as an intent? I was under the impression it was talking to the camera API directly. I could only find app restarts related to the image picker plugin on Flutter https://github.com/flutter/flutter/issues/59395. Interesting the camera-preview approach. I will give it a try.
For anyone still wondering with this. Before transitioning to camera you can start a foreground service, that way is less likely android will reclaim resources from your app. Once the photo has been taken, you can dismiss it. It might be a bit dirty but I don't think of anything else at the moment.
@dalepo like this? https://ionicframework.com/docs/native/foreground-service
@dalepo like this? https://ionicframework.com/docs/native/foreground-service
Yes
A quick heads up: as of Capacitor 3.2.3 the following solution works for me (for both Camera and Gallery sources):
https://gist.github.com/squio/1ff10bcca2aa1427a919e1c35cbc82fb
Capacitor versions before 3.2.3 had a bug (now fixed) which prevented the restored result from working
Using a foreground service is causing crashes on some devices, see
https://github.com/DavidBriglio/cordova-plugin-foreground-service/issues/19
https://github.com/DavidBriglio/cordova-plugin-foreground-service/issues/20
@dalepo
Hey guys, we have the same issues with a Xiaomi Redmi device. The app is developed in Unity and runs the native camera app. After locking the app on the device using this guide, the problem is not more there: https://www.xiaomist.com/2020/12/prevent-your-xiaomi-applications-from.html
So, the app does not restart when the User takes a picture. Remaining question: is it possible to mark the app as "locked" on Android programmatically. Or maybe somehow ask the user to set it, like requesting a permission.
@khindemit it will crash at some point even by locking, at least that is what we experienced on our app.
Still facing the issue. Any news, guys?
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: https://github.com/ionic-team/capacitor/issues/2931#issuecomment-632280083
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).
@squio Memory does not have anything to do with this issue, it is the way background tasks are dealt with in some roms. A more aggressive approach like on Xiaomi (but also the latest Samsung, Huawei etc..) kills the app when it goes to the background. It is not limited to photo taking, any background task can be killed at random if it is not a system app or a popular app the manufacturer decided to whitelist. More info https://dontkillmyapp.com/
One (almost) working solution is launching a foreground task when taking a picture, so it is less likely the app gets killed.
Endless thread here https://github.com/apache/cordova-plugin-camera/issues/345
Yes, I hate this...
Hello my ionic 6 and capacitor 4 app crash when take picture from camera. it happend only sometime like after 10 click photo app will crash, not all phone
how to handle this
my code import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
async openCamera(imageno: any) { const takePicture = async () => { const image = await Camera.getPhoto({ quality: 50, allowEditing: false, resultType: CameraResultType.Uri, }); this.readImg(image, imageno) }; takePicture(); }
async readImg(photo: any, imageno: any) { let random = Date.now() + Math.floor(Math.random() * 90000) + 10000 + '.jpg' const response = await fetch(photo.webPath); const blob = await response.blob(); console.log(blob); const formData = new FormData(); formData.append('photo', blob, random); this.uploadImg(formData,) }
can you share your code
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).
solution with cordova and capacitor "@awesome-cordova-plugins/foreground-service": "^6.3.0"
const getType = async (type) => { if (type === "camera") { ForegroundService.start("Cámara","Se está ejecutando la cámara","myicon"); setUpload(false); await Camera.getPhoto({ quality: 50, source: CameraSource.Camera, resultType: CameraResultType.Uri, }) .then((image) => { ForegroundService.stop(); saveImage(image); }) .catch(() => { ForegroundService.stop(); }); } else { ForegroundService.start("Fotos","Se está ejecutando la galería de fotos","myicon"); setUpload(false); await Camera.pickImages({ quality: 50, source: CameraSource.Photos, resultType: CameraResultType.Uri, }) .then((image) => { ForegroundService.stop(); saveImage(image?.photos[0]); }) .catch(() => { ForegroundService.stop(); }); } };
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 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.
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, did you find a solution to turn off the notification received by the user when the foreground service is started ? Or at least, cut the annoying sound of the notification.
Thx in advance :)
@robingenz thanks for that suggestion on a workaround.
Is this still your recommended method?
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)
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.7node --version
output: v10.15.1pod --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