Phonegap Plugin:How to convert Base64 String to a PNG image in Android

后端 未结 3 483
长发绾君心
长发绾君心 2020-11-29 01:35

Android does not allow native apps like Phonegap-based apps to write binary files. A common application is converting Base64 Strings to Images. So, how do you go about this

相关标签:
3条回答
  • 2020-11-29 01:52

    The solution; This plugin that converts a Base64 PNG String and generates an image to the sdCard. Let's go!

    1. The Base64 Decoder

    Get this blazing fast Base64 encode/decoder class called MiGBase64. Download it from SourceForge. Create a folder called 'util' within your project's src/ folder. Place the downloaded class there.

    2. The java

    Create a folder called 'org/apache/cordova' within your project's src/ folder. Create in it a Java file called "Base64ToPNG.java" with the following source code.

    package org.apache.cordova;
    
    /**
    * A phonegap plugin that converts a Base64 String to a PNG file.
    *
    * @author mcaesar
    * @lincese MIT.
    */
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    import org.apache.cordova.api.Plugin;
    import org.apache.cordova.api.PluginResult;
    import org.json.JSONArray;
    
    import android.os.Environment;
    import java.io.*;
    import org.json.JSONException;
    import org.json.JSONObject;
    import util.Base64;
    
    public class Base64ToPNG extends Plugin {
    
        @Override
        public PluginResult execute(String action, JSONArray args, String callbackId) {
    
            if (!action.equals("saveImage")) {
                return new PluginResult(PluginResult.Status.INVALID_ACTION);
            }
    
            try {
    
                String b64String = "";
                if (b64String.startsWith("data:image")) {
                    b64String = args.getString(0).substring(21);
                } else {
                    b64String = args.getString(0);
                }
                JSONObject params = args.getJSONObject(1);
    
                //Optional parameter
                String filename = params.has("filename")
                        ? params.getString("filename")
                        : "b64Image_" + System.currentTimeMillis() + ".png";
    
                String folder = params.has("folder")
                        ? params.getString("folder")
                        : Environment.getExternalStorageDirectory() + "/Pictures";
    
                Boolean overwrite = params.has("overwrite") 
                        ? params.getBoolean("overwrite") 
                        : false;
    
                return this.saveImage(b64String, filename, folder, overwrite, callbackId);
    
            } catch (JSONException e) {
    
                e.printStackTrace();
                return new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage());
    
            } catch (InterruptedException e) {
                e.printStackTrace();
                return new PluginResult(PluginResult.Status.ERROR, e.getMessage());
            }
    
        }
    
        private PluginResult saveImage(String b64String, String fileName, String dirName, Boolean overwrite, String callbackId) throws InterruptedException, JSONException {
    
            try {
    
                //Directory and File
                File dir = new File(dirName);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                File file = new File(dirName, fileName);
    
                //Avoid overwriting a file
                if (!overwrite && file.exists()) {
                    return new PluginResult(PluginResult.Status.OK, "File already exists!");
                }
    
                //Decode Base64 back to Binary format
                byte[] decodedBytes = Base64.decode(b64String.getBytes());
    
                //Save Binary file to phone
                file.createNewFile();
                FileOutputStream fOut = new FileOutputStream(file);
                fOut.write(decodedBytes);
                fOut.close();
    
    
                return new PluginResult(PluginResult.Status.OK, "Saved successfully!");
    
            } catch (FileNotFoundException e) {
                return new PluginResult(PluginResult.Status.ERROR, "File not Found!");
            } catch (IOException e) {
                return new PluginResult(PluginResult.Status.ERROR, e.getMessage());
            }
    
        }
    }
    

    3. The Javascript

    Write this JavaScript as Base64ToPNG.js to your project's www folder. DONT forget to include a reference to it in your html files.

    /**Works on all versions prior and including Cordova 1.6.1 
    * by mcaesar
    *  MIT license
    *  
    */
    
    (function() {
        /* This increases plugin compatibility */
        var cordovaRef = window.PhoneGap || window.Cordova || window.cordova; // old to new fallbacks
    
        /**
        * The Java to JavaScript Gateway 'magic' class 
        */
        function Base64ToPNG() { }
    
        /**
        * Save the base64 String as a PNG file to the user's Photo Library
        */
        Base64ToPNG.prototype.saveImage = function(b64String, params, win, fail) {
            cordovaRef.exec(win, fail, "Base64ToPNG", "saveImage", [b64String, params]);
        };
    
        cordovaRef.addConstructor(function() {
            if (!window.plugins) {
                window.plugins = {};
            }
            if (!window.plugins.base64ToPNG) {
                window.plugins.base64ToPNG = new Base64ToPNG();
            }
        });
    
    })(); 
    

    4. The plugins.xml file

    Add the following to res/xml/plugins.xml file

    <plugin name="Base64ToPNG" value="org.apache.cordova.Base64ToPNG"/>
    

    5. Finally, HTML examples and the parameters

    <button onclick="test();">No optional params required, Cowboy.</button> </br>
    <button onclick="test2();">Make PNG with some parameters</button>
    
    <script src="Base64ToPNG.js" type="text/javascript"></script>
    
    <script type="text/javascript">
    
    //May have a mime-type definition or not 
    var myBase64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="//a red dot
    
    
    function test(){
    
        //Illustrates how to use plugin with no optional parameters. Just the base64 Image.
        window.plugins.base64ToPNG.saveImage(myBase64, {}, 
           function(result) {
              alert(result);
           }, function(error) {
              alert(error);
           });
     }
    
     //No mimetype definition example
     var myOtherBase64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
    
     function test2(){
    
        //Shows how to use optional parameters
        window.plugins.base64ToPNG.saveImage(myBase64, {filename:"dot.png", overwrite: true}, 
           function(result) {
              alert(result);
           }, function(error) {
              alert(error);
        });
    
     }
     </script>
    

    Parameters

    1. filename: Name of the file to be generated. By default the same as the one in url.
    2. folder: Name of the directory to generate the file to. By default "sdcard/Pictures"
    3. overwrite: If the file already exists, replace it. By default false.

      I hope this answers some bothering questions. Happy coding!

    0 讨论(0)
  • 2020-11-29 02:04

    This solution only works when feeding it a CLEAN Base64 string. In other words, the "data:image/png;base64," part should be removed or the Base64 decoder fill fail, causing a nullpointer error when writing the file.

    Also I noticed that the image does not show up in the Gallery but it is stored correctly on the SD card. When I download it to my PC I can open it just fine. Not sure what that is about.

    Thanks for the work!

    0 讨论(0)
  • 2020-11-29 02:06

    Fo anybody wanting to use this with kineticjs, the following works a treat:

    function saveCanvas() {
        $('#save').bind( $bind, function(){
            stage.toDataURL({
            callback: function(dataUrl){
                window.plugins.base64ToPNG.saveImage(dataUrl.substr(22,dataUrl.length), {}, 
                    function(result) {
                        alert(result);
                    }, function(error) {
                        alert(error);
                    }
                );
            },
                mimeType: 'image/png',
                quality: 0.5
            });
        });
    }
    
    0 讨论(0)
提交回复
热议问题