2

I have a phonegap plugin I altered. The Java part outputs a base64 string:

package org.apache.cordova;

import java.io.ByteArrayOutputStream;
import java.io.File;

import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;

import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.os.Environment;
import android.util.Base64;
import android.view.View;



public class Screenshot extends Plugin {

    @Override

    public PluginResult execute(String action, JSONArray args, String callbackId) {
        // starting on ICS, some WebView methods
        // can only be called on UI threads
        final Plugin that = this;
        final String id = callbackId;
        super.cordova.getActivity().runOnUiThread(new Runnable() {
            //@Override
            @TargetApi(8)
            public void run() {
                View view = webView.getRootView();

                view.setDrawingCacheEnabled(true);
                Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
                view.setDrawingCacheEnabled(false);

                File folder = new File(Environment.getExternalStorageDirectory(), "Pictures");
                if (!folder.exists()) {
                    folder.mkdirs();

                }

                File f = new File(folder, "screenshot_" + System.currentTimeMillis() + ".png");
                System.out.println(folder);
                System.out.println("screenshot_" + System.currentTimeMillis() + ".png");



                ByteArrayOutputStream baos = new ByteArrayOutputStream();  
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
                byte[] b = baos.toByteArray();
                String base64String = Base64.encodeToString(b, Base64.DEFAULT);
                String mytextstring = "data:image/png;base64,"+base64String;
                System.out.println(mytextstring);

                that.success(new PluginResult(PluginResult.Status.OK, mytextstring), id);
            }
        });

        PluginResult imageData = new PluginResult(PluginResult.Status.NO_RESULT);
        imageData.setKeepCallback(true);
        System.out.println("imageData=============>>>>>"+imageData);
        return imageData;
    }

}

I then pass this to some Javascript and then send the string to a server. I have checked the string that the .php file receives, and the base64 string is identical. However when I decode the base64 string it seems corrupt. For a better example copy the contents of this text file into a decoder.

http://dl.dropbox.com/u/91982671/base64.txt

Note: When the .php file tries to decode it data:image/png;base64, is infront, I have just removed it for the ease of you pasting it into a decoder.

Decoder found here:

http://www.motobit.com/util/base64-decoder-encoder.asp

All I can think is that for some reason I may not be outputting the base64 string correctly from the Java. Does anyone have any idea whats going on? Or what may cause this?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Bohdi
  • 1,295
  • 4
  • 28
  • 62
  • Have you tried decoding and saving it before you send it to javascript? Maybe you should try decoding it with Sun Java? Check out this link: http://stackoverflow.com/questions/469695/decode-base64-data-in-java – Anders Vedal Pettersen Sep 18 '12 at 16:43
  • 1
    Have you tried saving the png image before encoding it to see if it gets corrupted during or before the compression step? – gigadot Sep 18 '12 at 16:50
  • Have you tried the commons-codec Base64 encoder to see if you have the same results? While it sucks to have this external requirement, it does mean that you can support Android 2.1 devices as well. That's what Cordova currently uses for Base64 encoding. – Joe B Sep 18 '12 at 23:50

1 Answers1

1

I played about with this for a good few hours last night and took some of these suggestions into consideration.

Firstly I checked the image before I encoded it. It was fine.

However decoding it before it goes to the Javascript showed that it was corrupted, this meant it had to be something to do with the Java encoding process. To solve this, and I don't claim to 100% understand why it happens, but the the problem seems to lay with this code:

String mytextstring = "data:image/png;base64,"+base64String;

and the way I was adding "data:/image/png;base64," before I sent it to the Javascript and on to the PHP decoder. To resolve this I removed it from the Java code so it became:

String mytextstring = base64String;

And in my JavaScript function that sent it to the server I added it to the string there, this works and I received an uncorrupted image. Just in-case anyone wonders/cares the Javascript function where I add it instead is below:

function returnScreenshotImage(imageData) { 
    base64string = "data:image/png;base64,"+imageData;
    console.log("String: "+base64string);

    var url = 'http://www.websitename.co.uk/upload.php';
    var params = {image: imageData};

    document.basicfrm.oldscreenshotimg.value = document.basicfrm.screenshotimg.value;

    // send the data
    $.post(url, params, function(data) {
           document.basicfrm.screenshotimg.value = data;

           });    
}

As you can see the line:

base64string = "data:image/png;base64,"+imageData;

Adds the section previously added by the Java. This works now. Hope this helps people in the future. If anyone would care to comment ad explain why this is if they know feel free. :)

Bohdi
  • 1,295
  • 4
  • 28
  • 62