[ 
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

        

Reply via email to