incubator-callback-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Christopher Bailey (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (CB-14) CameraLauncher Plugin enhancement for loading big image files to avoid OutOfMemory exceptions
Date Mon, 30 Apr 2012 12:48:48 GMT

    [ https://issues.apache.org/jira/browse/CB-14?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13264905#comment-13264905
] 

Christopher Bailey commented on CB-14:
--------------------------------------

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:
{noformat}
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);
}
{noformat}

Finally in the webview, I add the following to pick up the modified callback:
{noformat}
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.");
	}
}
{noformat}

                
> CameraLauncher Plugin enhancement for loading big image files to avoid OutOfMemory exceptions
> ---------------------------------------------------------------------------------------------
>
>                 Key: CB-14
>                 URL: https://issues.apache.org/jira/browse/CB-14
>             Project: Apache Callback
>          Issue Type: Improvement
>          Components: Android
>    Affects Versions: 1.1.0
>         Environment: Android SDK: 2.x & above
> JDK: 1.6
> Eclipse: Helios
>            Reporter: Bright Zheng
>            Assignee: Joe Bowser
>            Priority: Critical
>              Labels: CameraLauncher, OutOfMemory, decodeStream
>             Fix For: 1.6.0
>
>
> 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.
> {code:title=safeDecodeStream method|borderStyle=solid}
>     /**
>      * 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);
> 	}  
> {code} 
> And then change all the codes which are invoking the Android decodeStream API directly
to this method.
> e.g.
> {code:title=usage example|borderStyle=solid}
> //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);
> {code} 

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Mime
View raw message