29 de junio de 2018
App Inventor, Base64
Como crear una extensión para convertir imágenes en Base64 y viceversa | App Inventor
Vamos a crear una extensión de app inventor para convertir la información de una imagen a base64 para poder manipularla como texto y también poder convertir una cadena en Base64 a una imagen.
¿En que caso seria util la extensión?
- Para cuando tengamos la necesidad de almacenar una imagen dentro de una
TinyDB
. - Poder mandar una imagen dentro de un JSON a algún servidor.
- También hay veces que tenemos una imagen en base64 y queremos colocarla en la herramienta
Image
. Como sabemos la herramienta Image no puede leer Base64.
Empecemos a construir la extensión
Primero que todo va ser necesario clonar el repositorio de App Inventor:
$ cd ~/
$ git clone https://github.com/mit-cml/appinventor-sources.git
Una vez clonado el repositorio, vamos a crear la ruta de nuestro paquete y el archivo java. El nombre del paquete no es muy relevante pero yo siempre uso el nombre de mi dominio claramente en forma de paquete.
$ cd ~/appinventor-sources/appinventor/components/src
$ mkdir -p com/mvochoa/base64
$ cd com/mvochoa/base64
$ touch Base64.java
Creamos la clase y agregamos la información de la extensión al archivo java Base64.java
.
package com.mvochoa.base64;
import com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.common.ComponentCategory;
@DesignerComponent(version = 1,
description = "Codificador y Decodificar de imágenes en base64",
category = ComponentCategory.EXTENSION,
nonVisible = true,
iconName = "images/extension.png")
public class Base64 {
}
También hay que especificar que es un objecto externo al igual que los permisos necesario para la extensión, va ser necesario poder escribir y leer de la memoria externa del dispositivo. Ademas hay que extender de la clase AndroidNonvisibleComponent ya que nuestra extensión no va ser un componente visible.
package com.mvochoa.base64;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.annotations.UsesPermissions;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
@SimpleObject(external = true)
@UsesPermissions(permissionNames = "android.permission.WRITE_EXTERNAL_STORAGE, android.permission.READ_EXTERNAL_STORAGE")
public class Base64 extends AndroidNonvisibleComponent {
}
Creamos el constructor de la clase y obtenemos el Context que vamos a ocupar para poder obtener las rutas donde se almacena el Cache.
package com.mvochoa.base64;
import android.content.Context;
import com.google.appinventor.components.runtime.ComponentContainer;
public class Base64 extends AndroidNonvisibleComponent {
Context context;
public Base64(ComponentContainer container) {
super(container.$form());
context = (Context)container.$context();
}
}
La primera función que vamos hacer es la de convertir una imagen a base64.
package com.mvochoa.base64;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.runtime.util.ErrorMessages;
import java.io.ByteArrayOutputStream;
public class Base64 extends AndroidNonvisibleComponent {
@SimpleFunction(description = "Retorna una cadena en base64 de la imagen.")
public String ImageToBase64(String path) {
String base64 = "";
try {
Bitmap bm = BitmapFactory.decodeFile(path);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] byteArrayImage = baos.toByteArray();
base64 = android.util.Base64.encodeToString(byteArrayImage, android.util.Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
form.dispatchErrorOccurredEvent(this, "ioBase64",
ErrorMessages.ERROR_CANVAS_BITMAP_ERROR, e.getMessage());
}
return base64;
}
}
La función crea un Bitmap para poder obtener el arreglo de bytes de la imagen y obtenemos la cadena en Base64 con la información de la imagen usando la función android.util.Base64.encodeToString y se retorna la cadena obtenida.
La siguiente función es para convertir una cadena de texto en Base64 a una imagen y vamos a retornar la ruta de la imagen creada para eso ocupábamos los permisos, esto se hace para que la herramienta Image
pueda leer la imagen.
package com.mvochoa.base64;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Base64 extends AndroidNonvisibleComponent {
@SimpleFunction(description = "Retorna la ruta de la imagen.")
public String Base64ToImage(String base64) {
String name = (System.currentTimeMillis() / 1000L) + "";
try {
File img = File.createTempFile(name, null, context.getExternalCacheDir());
name = img.getAbsolutePath();
FileOutputStream fos = new FileOutputStream(img);
fos.write(android.util.Base64.decode(base64, android.util.Base64.DEFAULT));
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
form.dispatchErrorOccurredEvent(this, "ioBase64",
ErrorMessages.ERROR_CANNOT_SAVE_IMAGE, e.getMessage());
}
return name;
}
}
Para el nombre de la imagen es de un numero de la fecha actual pero en formato Unix es para evitar duplicados y creamos un archivo temporal dentro de la carpeta de Cache, ya solo se escribe dentro del archivo la cadena en Base64 decodificada y listo tenemos nuestra imagen.
Como extra vamos agregar dos funciones adicionales para convertir un cadena de texto a Base64 y viceversa:
package com.mvochoa.base64;
public class Base64 extends AndroidNonvisibleComponent {
@SimpleFunction(description = "Retorna la cadena codificada en base64.")
public String TextToBase64(String text) {
String base64 = "";
try {
base64 = android.util.Base64.encodeToString(text.getBytes(), android.util.Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
form.dispatchErrorOccurredEvent(this, "ioBase64", ErrorMessages.ERROR_CANVAS_BITMAP_ERROR, e.getMessage());
}
return base64;
}
@SimpleFunction(description = "Retorna la cadena en Base64 decodificada.")
public String Base64ToText(String base64) {
String text = "";
try {
text = new String(android.util.Base64.decode(base64, android.util.Base64.DEFAULT));
} catch (Exception e) {
e.printStackTrace();
form.dispatchErrorOccurredEvent(this, "ioBase64", ErrorMessages.ERROR_CANVAS_BITMAP_ERROR, e.getMessage());
}
return text;
}
}
Compilemos la extensión
Listo. Bueno ahora solo queda compilar la extensión para poderla usarla en app inventor. Ejecutamos los siguientes comandos:
$ cd ~/appinventor-sources/appinventor
$ ant clean
$ ant extensions
Listo con eso tenemos nuestro archivo .aix
en la ruta ~/appinventor-sources/appinventor/components/build/extensions/com.mvochoa.base64.aix
El archivo com.mvochoa.base64.aix
es el que tenemos que importar en app inventor.
¿Como se usa la extensión?
Entramos a http://ai2.appinventor.mit.edu/ y creamos un nuevo proyecto.
Una vez abierto el proyecto importáremos la extensión que es el archivo com.mvochoa.base64.aix
.
Ahora creamos un interfaz para probar la extensión con los siguientes componentes:
- Image
- Name: Image_Piker
- Height: 30%
- Width: Fill Parent
- VerticalArrangement
- Name: VerticalArrangement1
- Height: 40%
- Width: Fill Parent
- Componentes:
- ImagePiker
- Name: BtnImagePiker
- Width: Fill Parent
- Text: Seleccionar Imagen
- Label
- Name: Label1
- Width: Fill Parent
- Text: Imagen en base64
- FontBold: true
- TextBox
- Name: TxbBase64
- Width: Fill Parent
- Height: Fill Parent
- MultiLine: true
- Text:
- Label
- Name: Label2
- Width: Fill Parent
- Text: Base64 convertida a imagen
- FontBold: true
- ImagePiker
- Image
- Name: Image_Base64
- Height: 30%
- Base64 | La extensión que acabamos de hacer.
Ahora en la parte de los bloques, vamos a usar el evento AfterPicking del componente BtnImagePiker para que se ejecute después de que se seleccione una imagen.
Coloquemos la imagen seleccionada en el atributo Picture del Image_Piker.
Usamos el método de ImageToBase64 de la extensión y en el atributo Path colocamos la ruta de la imagen seleccionada y la cadena devuelta la colocamos en atributo Text del componente TxbBase64.
Por ultimo usamos el método Base64ToImage de la extensión para convertir la cadena de Base64 a Imagen y colocarla en el atributo Picture de Image_Base64.
Probamos la Aplicación
Ya solo queda probar la aplicación este fue el resultado como puedes ver en le TextBox se escribe todo la información de la imagen en Base64 y esa misma se vuelve a leer y se muestra en Image.
Bueno eso seria todo te comparto los enlaces de los archivos:
- Código fuente: Base64.java
- Extensión: com.mvochoa.base64.aix
- Proyecto de la app: UsoExtBase64.aia
- Apk de la app: UsoExtBase64.apk
Espero que te haya sido de ayuda. No olvides si ha sido util para ti seria de mucha ayuda si compartes este material con tus amigos.