33

I'm using PhoneGap's navigator.camera.getPicture function to retrieve a photo from the device's camera on Android.

function onSuccess(imageData) {
    alert("Success!");
}

function onFail(message) {
    alert('Failed because: ' + message);
}

$(function() {
    $("button").tap(function() {
        navigator.camera.getPicture(onSuccess, onFail, { quality: 50 }); 
    });
});

When I click the button, it does start the camera, but when I click OK on the camera app after taking a photo, it restarts the application.

I tried to:

  • use different source types.
  • use different destination types.
  • reduce quality.

Any ideas?

EDIT: I also started an issue at github.

Alon Gubkin
  • 56,458
  • 54
  • 195
  • 288

9 Answers9

36

This problem isn't actually about Phonegap. It's a common issue on native android apps too.

It occurs because when the camera is triggered, the android activity goes background (onStop state), waiting for the camera to take the picture. Then the GC comes and kills the activity to free memory before the conclusion of camera action, and when the camera is done your activity has already died. That is why the app is restarted.

It's on Android Lifecycle docs (http://developer.android.com/reference/android/app/Activity.html ):

If an activity is completely obscured by another activity, it is stopped. It still retains all state and member information, however, it is no longer visible to the user so its window is hidden and it will often be killed by the system when memory is needed elsewhere.

The same occurs by acessing the media gallery or other resources that causes your activity to go background. Phonegap (now Cordova) team is already working to improve this ( https://issues.apache.org/jira/browse/CB-14 ).

We had this problem in our company and the solution was to natively develop a Phonegap plugin to use our customized camera, then our activity never go to onStop state. Follow the android API instructions on http://developer.android.com/guide/topics/media/camera.html#custom-camera and try it too.

See ya!


Edit 1:

We submited a Google Code project named Foreground Camera Plugin that fixes the problem of Android Camera restarting Phonegap applications. There is some orientation on how to use it too. Please see: http://code.google.com/p/foreground-camera-plugin/


Edit 2:

Since this problem happens with gallery too, we submited another Google Code project named Foreground Gallery Plugin that works with Cordova and fixes this issue. Please see: http://code.google.com/p/foreground-gallery-plugin/

  • 3
    So what was the reason to use PhoneGap in the first place if now I can't take pictures with it? Doesn't make sense. – Zorayr May 23 '12 at 08:41
  • @vinicius haven't you considered open sourcing your plugin? – keune Jul 11 '12 at 09:04
  • 1
    Hi @keune I will talk to my team first and if its ok to open source the plugin, I'll try to upload a "hello world" project with working plugin and past the link here. But thanks for the idea. – Vinícius Fonseca Jul 11 '12 at 15:29
  • 2
    Hi Vicinius, have u got any plans to update this to later versions of PhoneGap? – Dan Smart Aug 28 '13 at 10:35
  • Good plugin but is deprecated in the actual phonegap versión, plugin works with cordova 2.1 now cordova is in version 3.1. In cordova 3.1 the problem need will fix with the plugin – Víctor Dueñas Robles Nov 08 '13 at 13:19
  • Is this issue resolved in the new version of android or cordova? I was facing this issue on a MOTO X until i turned off Developer Debugging Options in settings. Ideally it shud have worked regardless of the settings. But now i'm wondering if it will work on all android devices. Any thoughts? – Yashvit Oct 01 '14 at 08:15
  • Hi I tried the sample, but actually the onstop() was called still, I wonder whats the difference between a android camera app and a customized Activity which calls the camera functionality? – Qing Dec 24 '14 at 08:46
  • Can anyone help with the steps using this plugin for ionic2 cordova application. – Ankit Maheshwari Sep 22 '17 at 06:15
  • foreground-camera-plugin has 4 years already. Any updates on this? – Dani Feb 13 '18 at 13:15
29

Note that if you are testing this applications directly on your Android phone, there's an option inside "Developer options" called "Don't keep activities". When this option is checked it eliminates the activity when you leave it. Specifically in the case of the camera (and other applications lunched from your activity) it will restart your activity.

Uncheck this and see if that helps.

Mannyfatboy
  • 389
  • 7
  • 14
  • 1
    Pop over to http://stackoverflow.com/questions/14615190/cordova-samsung-galaxy-siii-camera-crashes-app and get yourself a green tick. – ocodo Mar 20 '13 at 02:07
  • This worked for me and is a fine work around for developing. But how do I make it so my users don't have to do this step? – wilblack Aug 11 '15 at 08:51
  • @wilblack the assumption is that "Developer options" are not used by the regular user but only from the actual developers, so I guess that answers your question... – radioaktiv Aug 25 '16 at 09:01
  • You should do some testing with Don't keep activities on to make sure that your application is properly maintaining in low memory state. – Sasha Nov 10 '16 at 11:49
  • This is not a solution! This is you hiding for the problem so you can say: works on my machine. This option is here to test this case. Android can always close your app when it is in the background if it needs to. This is a reason why hybrid development with cordova sucks. You still need to know the platform quirks so better make good quality native apps. – Roel Nov 17 '16 at 09:12
  • that's ok for testing but it's not a real solution I'm afraid – Dani Feb 13 '18 at 13:18
4

I have a Samsung Galaxy Note II. I had the same problem. I changed this in the AndroidManifest.xml and now it works on Samsung and HTC Thunderbolt

<uses-feature android:name="android.hardware.camera" android:required="false"/>

<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="10"/>

<activity  android:configChanges="orientation|keyboardHidden" />
user372225
  • 851
  • 2
  • 9
  • 23
2

Users won't want to restart their phone to free up memory, or check a box in Settings. The user-friendly way I found to return to my app's activity after leaving the camera, was to add the line:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

in CameraLauncher.java of the camera cordova plugin right before this.cordova.startActivityForResult() attempts to pass back the camera result. This makes sure that the old activity is retrieved, rather than being garbage-collected and a new instance being launched. From the android Intent API:

int FLAG_ACTIVITY_CLEAR_TOP

"If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent."

Community
  • 1
  • 1
kwills
  • 116
  • 10
2

When Android relaunches the app after the picture has been taken, a resume event is sent to the app. The event contains the taken photo data. So, a possible workaround involves catching the event:

document.addEventListener('resume', function(evt) {
  if(evt.action === 'resume' && evt.pendingResult) {
    var r = evt.pendingResult;
    if(r.pluginServiceName === 'Camera' && r.pluginStatus === 'OK') {
      // r.result contains file:/// url or a base64 image.
    }
  }
}, false);

Of course, you also have to restore the state of the application. For that, save your state information to eg. localStorage before opening the camera.

tuomassalo
  • 8,717
  • 6
  • 48
  • 50
1

For me it helped to use cordova background plugin: https://www.npmjs.com/package/cordova-plugin-background-mode

Include into config.xml:

<gap:plugin name="cordova-plugin-background-mode" source="npm"/>

Then trigger click event to start camera plugin and send app to background:

$(document).on("click","#btn_bild_aufnehmen",function(){        
    cordova.plugins.backgroundMode.setDefaults({ text:'desc',title:'appname'});
    cordova.plugins.backgroundMode.enable();
    //do your camera stuff
});

Do not forget to disable background mode in case of success by camera plugin:

cordova.plugins.backgroundMode.disable();

To be sure also disable it onResume and enable it onPause:

function onResume(){
   window.plugin.backgroundMode.disable();
}
function onPause(){
   window.plugin.backgroundMode.enable();
}
zuluk
  • 1,557
  • 8
  • 29
  • 49
  • I couldn't get this working. I can see it in the android notifications panel in the background "Doing heavy tasks." but after taking a photo the activity is still restarted. Any ideas? I wrapped the camera and barcode calls like in your example. – Ryan Apr 21 '17 at 08:41
  • Sorry, but it is not possible for me to make a good suggestion what the problem is. It seems that the background mode starts fine. So maybe you do not disable background mode first in success function of the camera plugin? Or it goes into error callback? – zuluk Apr 21 '17 at 09:24
0

I am having a similar problem where even the full example provided at Camera Documentation crashes the application on an Android device (Samsung, Galaxy S). Here is a output of the log that I get:

enter image description here

Zorayr
  • 23,770
  • 8
  • 136
  • 129
0

I also had the same problem. I cleared all the data from the phone to increase the phone internal memory size. Then stopped all the running applications and restarted my app. This time when the capture event was called my app did not crash.

Basically this problem exists for phones with less internal memory. This will work fine in higher end phones.

Note: Also add these extra parameters to the image captured:

 navigator.camera.getPicture(onPhotoDataSuccess, onFail, {
                   quality: 20,
                   destinationType:Camera.DestinationType.DATA_URL,
                   targetWidth: 200,
                   targetHeight: 200,
                   saveToPhotoAlbum : true
 });
0

This is actually happening when your device activities are being killed by Garbage collector , when some of your app event is trigered, your default activity goes at background hence it is being killed.

To fix this you need to go to Developer Options There you will see the option Don't Keep Activities , just uncheck that. restart your app and try camera now. it will work smoothly.

  • 2
    This does not fix the issue - that setting is so that you can replicate the use-case when the OS kills the app due to low memory usage consistently. If the device a user is running your app on has low memory it will kill the app (do what this setting is doing). – Lee Brindley Aug 16 '16 at 10:50