Android non consente alle app native come le app basate su PhoneGap di scrivere file binari. Un'applicazione comune sta convertendo le stringhe Base64 in immagini. Quindi, come procedi su questo problema?Plugin per Phoneegap: Come convertire String Base64 in un'immagine PNG su Android
risposta
La soluzione; Questo plugin converte una stringa PNG Base64 e genera un'immagine nella sdCard. Andiamo!
1. La Base64 Decoder
Ottenere questo velocissimo Base64 classe di codifica/decodifica chiamato MiGBase64. Scaricalo da SourceForge. Crea una cartella chiamata 'util' all'interno della cartella src/del tuo progetto. Inserisci qui la classe scaricata.
2. Il java
Creare una cartella denominata 'org/apache/Cordova' all'interno src/cartella del progetto. Creare in esso un file Java chiamato "Base64ToPNG.java" con il seguente codice sorgente.
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. Il Javascript
Scrivi questa JavaScript come Base64ToPNG.js nella cartella www del progetto. NON dimenticare di includere un riferimento ad esso nei tuoi file html.
/**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. Il file plugins.xml
Aggiungere il seguente alla res/xml/plugins.xml presentare
<plugin name="Base64ToPNG" value="org.apache.cordova.Base64ToPNG"/>
5. Infine, esempi HTML ei parametri
<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>
Parametri
- nome: nome del file da generare. Di default è lo stesso di quello in url.
- cartella: nome della directory in cui generare il file. Per impostazione predefinita "sdcard/Pictures"
sovrascrivi: Se il file esiste già, sostituirlo. Di default falso.
Spero che questo risponda a qualche domanda di disturbo. Buona programmazione!
Questa soluzione funziona solo quando si alimenta una stringa Base64 CLEAN. In altre parole, la parte "data: image/png; base64," deve essere rimossa o il riempimento del decodificatore Base64 fallisce, causando un errore di nullpointer durante la scrittura del file.
Inoltre ho notato che l'immagine non viene visualizzata nella Galleria ma è memorizzata correttamente sulla scheda SD. Quando lo scarico sul mio PC posso aprirlo bene. Non so di cosa si tratta.
Grazie per il lavoro!
Grazie per le correzioni. Modificato java per supportare "data: image/png; base64" completo. Per quanto riguarda l'immagine che non appare nella galleria, Android indicizza i file multimediali solo quando le unità di archiviazione cambiano stato, ad esempio da on a off. – mukama
@mcaesar Ho 3 domande sul plug-in: 1. Ho trovato che il parametro "cartella" dovrebbe essere: sdcard/nome_sedezione anziché "nome_sottore_directory". 2.Impostato un punto di interruzione nello strumento: byte [] decodificatoBytes = Base64.decode (b64String.getBytes()); in Base64ToPNG.java. E ho trovato che Base64.decode (~) restituisce un valore NULL. 3. Nella tua descrizione hai detto "Posiziona la classe scaricata lì", ma ottengo solo il file: Base64.java. C'è qualcosa che non va? Ho davvero bisogno del tuo plugin per convertire la mia tela in file .png, salvandola nel sistema locale. Per favore, dammi una guida. – Stallman
@mcaesar Hai accennato al fatto che correggi il file java per supportare l'intero "data: image/png; base64", ma temo che tu abbia dimenticato di caricare il file modificato. Grazie. – Stallman
Fo chiunque voglia usare questo con kineticjs, il seguente funziona a meraviglia:
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
});
});
}
grazie. Mi hai risparmiato ore a capire come avrebbe funzionato !! Ho apportato alcune piccole modifiche per supportare i file mp3 anziché PNG. Grazie ancora!!!! – ElHacker
@mcaesar Grazie mille, ho preparato tutto tranne una riga: byte [] decodedBytes = Base64.decode (b64String.getBytes()); mi dà il seguente errore: Il metodo decodifica (byte [], int) nel tipo Base64 non è applicabile per gli argomenti (byte []) Dato che non sono un professionista in Java potresti aiutarmi? Lo apprezzerei. – MarkSmits
Ciao @ Mark. Assicurati che la tua stringa base64 sia ben formattata. Vedi esempi che ho fornito. Grazie. – mukama