Apache Cordova
  1. Apache Cordova
  2. CB-14

CameraLauncher Plugin enhancement for loading big image files to avoid OutOfMemory exceptions

    Details

    • Type: Improvement Improvement
    • Status: Resolved
    • Priority: Critical Critical
    • Resolution: Not A Problem
    • Affects Version/s: 1.1.0
    • Fix Version/s: 1.6.0
    • Component/s: Android
    • Environment:

      Android SDK: 2.x & above
      JDK: 1.6
      Eclipse: Helios

      Description

      Currently the CameraLauncher plugin of Phonegap (or Apache Callback) is using Android default API for stream decoding.
      It will be very easy to get crash by throwing out the OutOfMemory exceptions while loading bigger image files.

      So I add a new method called safeDecodeStream for better stream decoding.

      safeDecodeStream method
      
          /**
           * A safer decodeStream method
           * rather than the one of {@link BitmapFactory}
           * which will be easy to get OutOfMemory Exception
           * while loading a big image file.
           * 
           * @param uri
           * @param width
           * @param height
           * @return
           * @throws FileNotFoundException
           */
          protected Bitmap safeDecodeStream(Uri uri, int width, int height)
          throws FileNotFoundException{
      		int scale = 1;
      		BitmapFactory.Options options = new BitmapFactory.Options();
      		android.content.ContentResolver resolver = this.ctx.getContentResolver();
      		
      		if(width>0 || height>0){
      			// Decode image size without loading all data into memory
      			options.inJustDecodeBounds = true;
      			BitmapFactory.decodeStream(
      					new BufferedInputStream(resolver.openInputStream(uri), 16*1024),
      					null,
      					options);
      			
      			int w = options.outWidth;
      			int h = options.outHeight;
      			while (true) {
      				if ((width>0 && w/2 < width)
      						|| (height>0 && h/2 < height)){
      					break;
      				}
      				w /= 2;
      				h /= 2;
      				scale *= 2;
      			}
      		}
      
      		// Decode with inSampleSize option
      		options.inJustDecodeBounds = false;
      		options.inSampleSize = scale;
      		return BitmapFactory.decodeStream(
      				new BufferedInputStream(resolver.openInputStream(uri), 16*1024), 
      				null, 
      				options);
      	}  
      

      And then change all the codes which are invoking the Android decodeStream API directly to this method.
      e.g.

      usage example
      
      //Updated by Bright for safer decodeStream
      //android.content.ContentResolver resolver = this.ctx.getContentResolver();
      //bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
      bitmap = safeDecodeStream(uri, this.targetWidth, this.targetHeight);
      
      

        Activity

        Hide
        Ben Plowman added a comment -

        Definitely agree that this is important. I have found lots of OOM errors in strange places on Android before I started scaling bitmaps like this.

        Show
        Ben Plowman added a comment - Definitely agree that this is important. I have found lots of OOM errors in strange places on Android before I started scaling bitmaps like this.
        Hide
        Pamela Fox added a comment -

        I added the suggested method to my Phonegap and it resolved the original OutOfMemory error, but I still experienced two other OutOfMemory errors:
        "bitmap size exceeds VM budget" (full trace: http://pastebin.com/raw.php?i=0SsTgbvF)
        And one during com.phonegap.api.PluginResult.toSuccessCallbackString (full trace: http://pastebin.com/raw.php?i=3cgyR5Dk)

        I seem to avoid these issues by requesting a low quality (20) and low width/height (400/400)..but I imagine that workaround won't work for all people using the Camera API, and I don't feel great on relying on that as a solution.

        Show
        Pamela Fox added a comment - I added the suggested method to my Phonegap and it resolved the original OutOfMemory error, but I still experienced two other OutOfMemory errors: "bitmap size exceeds VM budget" (full trace: http://pastebin.com/raw.php?i=0SsTgbvF ) And one during com.phonegap.api.PluginResult.toSuccessCallbackString (full trace: http://pastebin.com/raw.php?i=3cgyR5Dk ) I seem to avoid these issues by requesting a low quality (20) and low width/height (400/400)..but I imagine that workaround won't work for all people using the Camera API, and I don't feel great on relying on that as a solution.
        Hide
        Joe Bowser added a comment -

        Is this meant to be a patch? I see that it's been assigned to 2.0.0 for a fix.

        @Pamela Fox: Can you write a ticket indicating what device you ran into this on? I've run into this on very low-end Android devices.

        Show
        Joe Bowser added a comment - Is this meant to be a patch? I see that it's been assigned to 2.0.0 for a fix. @Pamela Fox: Can you write a ticket indicating what device you ran into this on? I've run into this on very low-end Android devices.
        Hide
        Pamela Fox added a comment -
        Show
        Pamela Fox added a comment - @Joe Bowser: OK, I've filed https://issues.apache.org/jira/browse/CB-220
        Hide
        Simon MacDonald added a comment -

        Bright, you code seems to help this issue. Can you sign the CLA:

        http://www.apache.org/licenses/#clas

        so we can add it to a future release?

        Show
        Simon MacDonald added a comment - Bright, you code seems to help this issue. Can you sign the CLA: http://www.apache.org/licenses/#clas so we can add it to a future release?
        Hide
        Joe Bowser added a comment -

        I tested the patch, and I managed to get the same thing as @PamelaFox. However, when I use FILE_URI I don't have this issue at all, however this code isn't used either. I suspect that this is an issue with passing a large amount of data across an intent and manipulating it, which in my experience has always led to disaster. We should probably discuss removing the DATA_URL option or re-thinking it in a later release.

        Show
        Joe Bowser added a comment - I tested the patch, and I managed to get the same thing as @PamelaFox. However, when I use FILE_URI I don't have this issue at all, however this code isn't used either. I suspect that this is an issue with passing a large amount of data across an intent and manipulating it, which in my experience has always led to disaster. We should probably discuss removing the DATA_URL option or re-thinking it in a later release.
        Hide
        Bright Zheng added a comment -

        @Simon, my pleasure. I have sent out the CLA by following the procedures. Thanks.

        Actually, I think you guys should review the related API usage on this project because I just patched what I used.
        The coverage is NOT 100%.

        Show
        Bright Zheng added a comment - @Simon, my pleasure. I have sent out the CLA by following the procedures. Thanks. Actually, I think you guys should review the related API usage on this project because I just patched what I used. The coverage is NOT 100%.
        Hide
        Lucas Emanuel Martins Farias added a comment -

        This problem occurs when your application is sent to background and the camera activity is in the foreground. We discovered that our application is being killed because camera takes too much memory and the garbage colector release memory killing background apps. This problem occurs with native Android apps too, so you have to build your own camera app. We resolved this problem creating our camera app described here: http://developer.android.com/guide/topics/media/camera.html#custom-camera
        So we created a Camera Activity that is called by a plugin and the problem don´t occured anymore. This way, you app is in foreground preventing the GC to kill it.

        Show
        Lucas Emanuel Martins Farias added a comment - This problem occurs when your application is sent to background and the camera activity is in the foreground. We discovered that our application is being killed because camera takes too much memory and the garbage colector release memory killing background apps. This problem occurs with native Android apps too, so you have to build your own camera app. We resolved this problem creating our camera app described here: http://developer.android.com/guide/topics/media/camera.html#custom-camera So we created a Camera Activity that is called by a plugin and the problem don´t occured anymore. This way, you app is in foreground preventing the GC to kill it.
        Hide
        Joe Bowser added a comment -

        @Lucas I think you're right on this one, and I'm going to have to investigate this further. We used to maintain our own Camera Activity and we dropped it because of the device fragmentation issues with Cameras and filters. The solution may be that we have a camera plugin that is implemented separately from the core that people can use if they run into this issue, and we might just have to mitigate the DATA_URL issue.

        Show
        Joe Bowser added a comment - @Lucas I think you're right on this one, and I'm going to have to investigate this further. We used to maintain our own Camera Activity and we dropped it because of the device fragmentation issues with Cameras and filters. The solution may be that we have a camera plugin that is implemented separately from the core that people can use if they run into this issue, and we might just have to mitigate the DATA_URL issue.
        Hide
        Joe Bowser added a comment -

        I recommend that people who NEED a Camera work on a Camera Plugin and concentrate on maintaining that, since that is currently beyond our scope.

        Show
        Joe Bowser added a comment - I recommend that people who NEED a Camera work on a Camera Plugin and concentrate on maintaining that, since that is currently beyond our scope.
        Hide
        Christopher Bailey added a comment -

        @Joe I too am facing the same issue. Asking people to implement their own camera solution for anyone needing to use the camera api is far from ideal. I think you could go some way to mitigating this issue if the cordova app saved it's application state (or rather that of it's plugins) using the onSaveInstanceState hook provided by Android:
        http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)
        Cordova could then check the bundle in the onCreate method to recreate the relevant plugins and allow the intent to be passed back to the application (obviously it would still be up to application developers to maintain their own app's state using the js destroy/resume events).

        Show
        Christopher Bailey added a comment - @Joe I too am facing the same issue. Asking people to implement their own camera solution for anyone needing to use the camera api is far from ideal. I think you could go some way to mitigating this issue if the cordova app saved it's application state (or rather that of it's plugins) using the onSaveInstanceState hook provided by Android: http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle ) Cordova could then check the bundle in the onCreate method to recreate the relevant plugins and allow the intent to be passed back to the application (obviously it would still be up to application developers to maintain their own app's state using the js destroy/resume events).
        Hide
        Joe Bowser added a comment -

        @Christopher OK, so if you are absolutely required to pass the image as a Base64 encoded stream from your camera API back to Cordova and you can't save your image any other way whatsoever (i.e. File URI), that's when I recommend creating your own Camera plugin. Using DATA_URI for this is not recommended for many reasons, most of which involves the large amount of data that you are going to be passing through intents. I don't believe that SaveInstanceState saves the state of the WebView, and that this is a red herring.

        Simple Solution: Don't use DATA_URI for any large images
        Complex Solution: If you MUST have Base64 data, write your own plugin because your requirements are unique.

        That being said, I really have to try hard to reproduce this error with a DATA_URL on the Nexus S.

        Show
        Joe Bowser added a comment - @Christopher OK, so if you are absolutely required to pass the image as a Base64 encoded stream from your camera API back to Cordova and you can't save your image any other way whatsoever (i.e. File URI), that's when I recommend creating your own Camera plugin. Using DATA_URI for this is not recommended for many reasons, most of which involves the large amount of data that you are going to be passing through intents. I don't believe that SaveInstanceState saves the state of the WebView, and that this is a red herring. Simple Solution: Don't use DATA_URI for any large images Complex Solution: If you MUST have Base64 data, write your own plugin because your requirements are unique. That being said, I really have to try hard to reproduce this error with a DATA_URL on the Nexus S.
        Hide
        Christopher Bailey added a comment -

        @Joe. Sorry I think my confusion was due to the incorrect assignment of issue CB-193 being merged into this ticket. Essentially when Cordova or any app fires up the camera (regardless of FILE_URI or DATA_URL) then the OS can decide summarily to kill of the app as it's running in the background. This is the issue mentioned in CB-193. You can try this yourself by firing up the camera and then using the task switcher/home key to change to one or more memory intensive apps (e.g. browser)

        This issue was particularly prevalent with the camera app on my Galaxy S so I have implemented a workaround by extending CameraLauncher and saving it's state in my Activity's onSaveInstanceState(). I feel that DroidGap.java should be doing this itself so that it can recover from such an event.

        Show
        Christopher Bailey added a comment - @Joe. Sorry I think my confusion was due to the incorrect assignment of issue CB-193 being merged into this ticket. Essentially when Cordova or any app fires up the camera (regardless of FILE_URI or DATA_URL) then the OS can decide summarily to kill of the app as it's running in the background. This is the issue mentioned in CB-193 . You can try this yourself by firing up the camera and then using the task switcher/home key to change to one or more memory intensive apps (e.g. browser) This issue was particularly prevalent with the camera app on my Galaxy S so I have implemented a workaround by extending CameraLauncher and saving it's state in my Activity's onSaveInstanceState(). I feel that DroidGap.java should be doing this itself so that it can recover from such an event.
        Hide
        Joe Bowser added a comment -

        @Christopher: If you have a patch, or at least a working code sample, by all means share it. Please open a new ticket and describe what the code does. If the patch is signficant enough, we may ask you to sign a CLA, but it'd save us a lot of time doing this instead of re-inventing the wheel.

        Show
        Joe Bowser added a comment - @Christopher: If you have a patch, or at least a working code sample, by all means share it. Please open a new ticket and describe what the code does. If the patch is signficant enough, we may ask you to sign a CLA, but it'd save us a lot of time doing this instead of re-inventing the wheel.
        Hide
        Christopher Bailey added a comment -

        It's not much code and I'm only interested in the situation where the app was destroyed after firing up the camera/album app. I'm sure it's easy to extend for other plugins.
        Firstly I override CameraLauncher.java just to make public the private vars. I call this CustomCameraPlugin

        Then in my activity I add the following:

        public void onCreate(Bundle savedInstanceState)
        {
        	super.onCreate(savedInstanceState);
        	if (savedInstanceState == null || savedInstanceState.isEmpty())
        	{
        		super.setIntegerProperty("splashscreen", R.drawable.startup);
        		super.loadUrl("file:///android_asset/www/index.html", 2000);
        	}
        	else
        	{
        		String sCallback = savedInstanceState.getString("callback");
        		if (sCallback != null)
        		{
        			try
        			{
        				if (sCallback.equals(CustomCameraPlugin.class.toString()))
        				{
        					CustomCameraPlugin c = new CustomCameraPlugin();
        					c.callbackId = savedInstanceState.getString("callbackId");
        					c.setContext(this);
        					c.setView(this.appView);
        					String uri = savedInstanceState.getString("imageUri");
        					if (uri != null)
        					{
        						c.imageUri = Uri.fromFile(new File(uri));
        					}
        					c.mediaType = savedInstanceState.getInt("mediaType");
        					c.targetHeight = savedInstanceState.getInt("targetHeight");
        					c.targetWidth = savedInstanceState.getInt("targetWidth");
        					setActivityResultCallback(c);
        				}
        			}
        			catch (Exception e)
        			{
        				e.printStackTrace();
        			}
        		}
        		// add a hash to the url to indicate we need to add the custom callback
        		super.loadUrl("file:///android_asset/www/index.html#new");
        	}
        }
        
        @Override
        public void onSaveInstanceState(Bundle savedInstanceState)
        {
        	IPlugin callback = (IPlugin) this.activityResultCallback;
        	if (callback != null)
        	{
        		String className = callback.getClass().toString();
        		savedInstanceState.putString("callback", className);
        
        		if (className.equals(CustomCameraPlugin.class.toString()))
        		{
        			CustomCameraPlugin c = (CustomCameraPlugin) callback;);
        
        			savedInstanceState.putString("callbackId", "Camera");
        			if (c.imageUri != null)
        				savedInstanceState.putString("imageUri", c.imageUri.getPath());
        			savedInstanceState.putInt("mediaType", c.mediaType);
        			savedInstanceState.putInt("targetHeight", c.targetHeight);
        			savedInstanceState.putInt("targetWidth", c.targetWidth);
        		}
        	}
        	super.onSaveInstanceState(savedInstanceState);
        }
        

        Finally in the webview, I add the following to pick up the modified callback:

        if (window.location.hash) {
        	log("Location hash exists ... setting callback");
        	if (typeof cordova !== "undefined") {
        		cordova.callbacks["Camera"] = {
        			success : savePicUri,
        			fail : unableToTakePhoto
        		};
        	} else {
        		log("  ... callback setting failed. Cordova undefined.");
        	}
        }
        
        Show
        Christopher Bailey added a comment - It's not much code and I'm only interested in the situation where the app was destroyed after firing up the camera/album app. I'm sure it's easy to extend for other plugins. Firstly I override CameraLauncher.java just to make public the private vars. I call this CustomCameraPlugin Then in my activity I add the following: public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState == null || savedInstanceState.isEmpty()) { super.setIntegerProperty("splashscreen", R.drawable.startup); super.loadUrl("file:///android_asset/www/index.html", 2000); } else { String sCallback = savedInstanceState.getString("callback"); if (sCallback != null) { try { if (sCallback.equals(CustomCameraPlugin.class.toString())) { CustomCameraPlugin c = new CustomCameraPlugin(); c.callbackId = savedInstanceState.getString("callbackId"); c.setContext(this); c.setView(this.appView); String uri = savedInstanceState.getString("imageUri"); if (uri != null) { c.imageUri = Uri.fromFile(new File(uri)); } c.mediaType = savedInstanceState.getInt("mediaType"); c.targetHeight = savedInstanceState.getInt("targetHeight"); c.targetWidth = savedInstanceState.getInt("targetWidth"); setActivityResultCallback(c); } } catch (Exception e) { e.printStackTrace(); } } // add a hash to the url to indicate we need to add the custom callback super.loadUrl("file:///android_asset/www/index.html#new"); } } @Override public void onSaveInstanceState(Bundle savedInstanceState) { IPlugin callback = (IPlugin) this.activityResultCallback; if (callback != null) { String className = callback.getClass().toString(); savedInstanceState.putString("callback", className); if (className.equals(CustomCameraPlugin.class.toString())) { CustomCameraPlugin c = (CustomCameraPlugin) callback;); savedInstanceState.putString("callbackId", "Camera"); if (c.imageUri != null) savedInstanceState.putString("imageUri", c.imageUri.getPath()); savedInstanceState.putInt("mediaType", c.mediaType); savedInstanceState.putInt("targetHeight", c.targetHeight); savedInstanceState.putInt("targetWidth", c.targetWidth); } } super.onSaveInstanceState(savedInstanceState); } Finally in the webview, I add the following to pick up the modified callback: if (window.location.hash) { log("Location hash exists ... setting callback"); if (typeof cordova !== "undefined") { cordova.callbacks["Camera"] = { success : savePicUri, fail : unableToTakePhoto }; } else { log(" ... callback setting failed. Cordova undefined."); } }
        Hide
        George Hamilton added a comment -

        Hi

        I notice this issue status is 'Resolved' and resolution 'Not A Problem'. With my Asus Transformer using phonegap 1.7.0, the camera is crashing the application when the picture size is set to 8M. I am using FILE_URI. Here is my code:

        navigator.camera.getPicture(
            function(fileURI){
                console.log(fileURI);
            },
            function(message){
                console.log(message);
            },
            {
                quality: 50,
                destinationType: Camera.DestinationType.FILE_URI,
                sourceType : Camera.PictureSourceType.CAMERA
            }
        );
        

        and the exception:

        D/dalvikvm(23824): GC_FOR_ALLOC freed 275K, 81% free 7792K/39239K, paused 33ms
        I/dalvikvm-heap(23824): Forcing collection of SoftReferences for 31961104-byte allocation
        D/dalvikvm(23824): GC_BEFORE_OOM freed 28K, 81% free 7764K/39239K, paused 22ms
        E/dalvikvm-heap(23824): Out of memory on a 31961104-byte allocation.
        I/dalvikvm(23824): "main" prio=5 tid=1 RUNNABLE
        I/dalvikvm(23824):   | group="main" sCount=0 dsCount=0 obj=0x40a39460 self=0x3f2828
        I/dalvikvm(23824):   | sysTid=23824 nice=0 sched=0/0 cgrp=default handle=1074562184
        I/dalvikvm(23824):   | schedstat=( 18895478000 6928031000 33348 ) utm=1662 stm=227 core=0
        I/dalvikvm(23824):   at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
        I/dalvikvm(23824):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
        I/dalvikvm(23824):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:549)
        I/dalvikvm(23824):   at android.provider.MediaStore$Images$Media.getBitmap(MediaStore.java:716)
        I/dalvikvm(23824):   at org.apache.cordova.CameraLauncher.onActivityResult(CameraLauncher.java:296)
        I/dalvikvm(23824):   at org.apache.cordova.DroidGap.onActivityResult(DroidGap.java:1145)
        I/dalvikvm(23824):   at android.app.Activity.dispatchActivityResult(Activity.java:4649)
        I/dalvikvm(23824):   at android.app.ActivityThread.deliverResults(ActivityThread.java:2976)
        I/dalvikvm(23824):   at android.app.ActivityThread.handleSendResult(ActivityThread.java:3023)
        I/dalvikvm(23824):   at android.app.ActivityThread.access$1100(ActivityThread.java:123)
        I/dalvikvm(23824):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1177)
        I/dalvikvm(23824):   at android.os.Handler.dispatchMessage(Handler.java:99)
        I/dalvikvm(23824):   at android.os.Looper.loop(Looper.java:137)
        I/dalvikvm(23824):   at android.app.ActivityThread.main(ActivityThread.java:4424)
        I/dalvikvm(23824):   at java.lang.reflect.Method.invokeNative(Native Method)
        I/dalvikvm(23824):   at java.lang.reflect.Method.invoke(Method.java:511)
        I/dalvikvm(23824):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
        I/dalvikvm(23824):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
        I/dalvikvm(23824):   at dalvik.system.NativeStart.main(Native Method)
        I/dalvikvm(23824): 
        D/skia    (23824): --- decoder->decode returned false
        D/AndroidRuntime(23824): Shutting down VM
        W/dalvikvm(23824): threadid=1: thread exiting with uncaught exception (group=0x40a381f8)
        E/AndroidRuntime(23824): FATAL EXCEPTION: main
        E/AndroidRuntime(23824): java.lang.OutOfMemoryError
        E/AndroidRuntime(23824): 	at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
        E/AndroidRuntime(23824): 	at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
        E/AndroidRuntime(23824): 	at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:549)
        E/AndroidRuntime(23824): 	at android.provider.MediaStore$Images$Media.getBitmap(MediaStore.java:716)
        E/AndroidRuntime(23824): 	at org.apache.cordova.CameraLauncher.onActivityResult(CameraLauncher.java:296)
        E/AndroidRuntime(23824): 	at org.apache.cordova.DroidGap.onActivityResult(DroidGap.java:1145)
        E/AndroidRuntime(23824): 	at android.app.Activity.dispatchActivityResult(Activity.java:4649)
        E/AndroidRuntime(23824): 	at android.app.ActivityThread.deliverResults(ActivityThread.java:2976)
        E/AndroidRuntime(23824): 	at android.app.ActivityThread.handleSendResult(ActivityThread.java:3023)
        E/AndroidRuntime(23824): 	at android.app.ActivityThread.access$1100(ActivityThread.java:123)
        E/AndroidRuntime(23824): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1177)
        E/AndroidRuntime(23824): 	at android.os.Handler.dispatchMessage(Handler.java:99)
        E/AndroidRuntime(23824): 	at android.os.Looper.loop(Looper.java:137)
        E/AndroidRuntime(23824): 	at android.app.ActivityThread.main(ActivityThread.java:4424)
        E/AndroidRuntime(23824): 	at java.lang.reflect.Method.invokeNative(Native Method)
        E/AndroidRuntime(23824): 	at java.lang.reflect.Method.invoke(Method.java:511)
        E/AndroidRuntime(23824): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
        E/AndroidRuntime(23824): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
        E/AndroidRuntime(23824): 	at dalvik.system.NativeStart.main(Native Method)
        W/ActivityManager(  200):   Force finishing activity uk.ac.edina.mobile/.AndroidMapper
        W/ActivityManager(  200): Activity pause timeout for ActivityRecord{415e7bf8 uk.ac.edina.mobile/.AndroidMapper}
        D/WindowManager(  200): adjustConfigurationLw, config:{1.0 0mcc0mnc (no locale) layoutdir=0 sw800dp w1280dp h752dp xlrg land ?uimode ?night finger -keyb/v/h -nav/v} mLidOpen:-1 mHasDockFeature:true mHasHallSensorFeature:true config.hardKeyboardHidden:2
        
        Show
        George Hamilton added a comment - Hi I notice this issue status is 'Resolved' and resolution 'Not A Problem'. With my Asus Transformer using phonegap 1.7.0, the camera is crashing the application when the picture size is set to 8M. I am using FILE_URI. Here is my code: navigator.camera.getPicture( function(fileURI){ console.log(fileURI); }, function(message){ console.log(message); }, { quality: 50, destinationType: Camera.DestinationType.FILE_URI, sourceType : Camera.PictureSourceType.CAMERA } ); and the exception: D/dalvikvm(23824): GC_FOR_ALLOC freed 275K, 81% free 7792K/39239K, paused 33ms I/dalvikvm-heap(23824): Forcing collection of SoftReferences for 31961104-byte allocation D/dalvikvm(23824): GC_BEFORE_OOM freed 28K, 81% free 7764K/39239K, paused 22ms E/dalvikvm-heap(23824): Out of memory on a 31961104-byte allocation. I/dalvikvm(23824): "main" prio=5 tid=1 RUNNABLE I/dalvikvm(23824): | group="main" sCount=0 dsCount=0 obj=0x40a39460 self=0x3f2828 I/dalvikvm(23824): | sysTid=23824 nice=0 sched=0/0 cgrp=default handle=1074562184 I/dalvikvm(23824): | schedstat=( 18895478000 6928031000 33348 ) utm=1662 stm=227 core=0 I/dalvikvm(23824): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) I/dalvikvm(23824): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493) I/dalvikvm(23824): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:549) I/dalvikvm(23824): at android.provider.MediaStore$Images$Media.getBitmap(MediaStore.java:716) I/dalvikvm(23824): at org.apache.cordova.CameraLauncher.onActivityResult(CameraLauncher.java:296) I/dalvikvm(23824): at org.apache.cordova.DroidGap.onActivityResult(DroidGap.java:1145) I/dalvikvm(23824): at android.app.Activity.dispatchActivityResult(Activity.java:4649) I/dalvikvm(23824): at android.app.ActivityThread.deliverResults(ActivityThread.java:2976) I/dalvikvm(23824): at android.app.ActivityThread.handleSendResult(ActivityThread.java:3023) I/dalvikvm(23824): at android.app.ActivityThread.access$1100(ActivityThread.java:123) I/dalvikvm(23824): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1177) I/dalvikvm(23824): at android.os.Handler.dispatchMessage(Handler.java:99) I/dalvikvm(23824): at android.os.Looper.loop(Looper.java:137) I/dalvikvm(23824): at android.app.ActivityThread.main(ActivityThread.java:4424) I/dalvikvm(23824): at java.lang.reflect.Method.invokeNative(Native Method) I/dalvikvm(23824): at java.lang.reflect.Method.invoke(Method.java:511) I/dalvikvm(23824): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) I/dalvikvm(23824): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) I/dalvikvm(23824): at dalvik.system.NativeStart.main(Native Method) I/dalvikvm(23824): D/skia (23824): --- decoder->decode returned false D/AndroidRuntime(23824): Shutting down VM W/dalvikvm(23824): threadid=1: thread exiting with uncaught exception (group=0x40a381f8) E/AndroidRuntime(23824): FATAL EXCEPTION: main E/AndroidRuntime(23824): java.lang.OutOfMemoryError E/AndroidRuntime(23824): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) E/AndroidRuntime(23824): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493) E/AndroidRuntime(23824): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:549) E/AndroidRuntime(23824): at android.provider.MediaStore$Images$Media.getBitmap(MediaStore.java:716) E/AndroidRuntime(23824): at org.apache.cordova.CameraLauncher.onActivityResult(CameraLauncher.java:296) E/AndroidRuntime(23824): at org.apache.cordova.DroidGap.onActivityResult(DroidGap.java:1145) E/AndroidRuntime(23824): at android.app.Activity.dispatchActivityResult(Activity.java:4649) E/AndroidRuntime(23824): at android.app.ActivityThread.deliverResults(ActivityThread.java:2976) E/AndroidRuntime(23824): at android.app.ActivityThread.handleSendResult(ActivityThread.java:3023) E/AndroidRuntime(23824): at android.app.ActivityThread.access$1100(ActivityThread.java:123) E/AndroidRuntime(23824): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1177) E/AndroidRuntime(23824): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime(23824): at android.os.Looper.loop(Looper.java:137) E/AndroidRuntime(23824): at android.app.ActivityThread.main(ActivityThread.java:4424) E/AndroidRuntime(23824): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime(23824): at java.lang.reflect.Method.invoke(Method.java:511) E/AndroidRuntime(23824): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) E/AndroidRuntime(23824): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) E/AndroidRuntime(23824): at dalvik.system.NativeStart.main(Native Method) W/ActivityManager( 200): Force finishing activity uk.ac.edina.mobile/.AndroidMapper W/ActivityManager( 200): Activity pause timeout for ActivityRecord{415e7bf8 uk.ac.edina.mobile/.AndroidMapper} D/WindowManager( 200): adjustConfigurationLw, config:{1.0 0mcc0mnc (no locale) layoutdir=0 sw800dp w1280dp h752dp xlrg land ?uimode ?night finger -keyb/v/h -nav/v} mLidOpen:-1 mHasDockFeature:true mHasHallSensorFeature:true config.hardKeyboardHidden:2
        Hide
        Bright Zheng added a comment -

        Hi George,

        Maybe the definition of status & resolution is not accurate since the issue is still there.

        They just want to put this as scope of plugin which the users/developers have to cope with.

        My suggestion to you is to follow my steps as above mentioned and you can go more far.

        Good luck!
        Bright

        Show
        Bright Zheng added a comment - Hi George, Maybe the definition of status & resolution is not accurate since the issue is still there. They just want to put this as scope of plugin which the users/developers have to cope with. My suggestion to you is to follow my steps as above mentioned and you can go more far. Good luck! Bright
        Hide
        Joe Bowser added a comment -

        @George: See CB-415 for your bug

        Show
        Joe Bowser added a comment - @George: See CB-415 for your bug
        Hide
        Will Koper added a comment -

        I tried to implement Christopher's solution, but since the callback server hasn't started when I call setActivityResultForCallback, the pluginSuccess call gets lost in the ether. Same goes if I try to instantiate the callbackServer in my onCreate function because the cb server restarts itself.

        Is it worth requesting that the devs implement a way to save and restore plugins from the savedInstanceState bundle?

        Show
        Will Koper added a comment - I tried to implement Christopher's solution, but since the callback server hasn't started when I call setActivityResultForCallback, the pluginSuccess call gets lost in the ether. Same goes if I try to instantiate the callbackServer in my onCreate function because the cb server restarts itself. Is it worth requesting that the devs implement a way to save and restore plugins from the savedInstanceState bundle?
        Hide
        Narendra Kurapati added a comment -

        Still, we have this issue in newer versions. The above function is giving errors. Please let us know if there any fixes.

        Show
        Narendra Kurapati added a comment - Still, we have this issue in newer versions. The above function is giving errors. Please let us know if there any fixes.

          People

          • Assignee:
            Joe Bowser
            Reporter:
            Bright Zheng
          • Votes:
            2 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development