Enviando emails desde una aplicación Android  

Hoy vamos a enviar un correo electrónico desde nuestra aplicación. Ésto puede ser de mucha utilidad. Por ejemplo, para permitir que nuestros usuarios se pongan en contacto con nostros o nos puedan enviar un log de la aplicación para reportar fallos.

Hacerlo es muy sencillo, éste snippet de código lo explica a la perfección:

Intent email = new Intent(android.content.Intent.ACTION_SEND);
email.setType("plain/text");

email.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"email@email.com"});
email.putExtra(android.content.Intent.EXTRA_SUBJECT, "Asunto de mi correo");
email.putExtra(android.content.Intent.EXTRA_TEXT, "Texto de mi correo");

email.putExtra(Intent.EXTRA_STREAM,
	Uri.parse("file://"+Environment.getExternalStorageDirectory()+"/archivo.txt"));

startActivity(Intent.createChooser(email, "Enviar correo electrónico"));

Facil, ¿eh? ¡Happy coding!

hi 256 4 f4f3667dfb66514a859a216284211dd72f820799 Enviando emails desde una aplicación Android

Etiquetas: , , ,
Comentarios: No hay comentarios aún

Exploded deploy en JBoss 6 sobre Windows  

Cuando intento deployar un archivo EAR sobre un JBoss 6 bajo windows, recibo el siguiente error:

Failed to create Resource EJEMPLO.ear - cause: java.lang.Exception:Failed to distribute 'file:/XXXX/EJEMPLO.ear' to 'EJEMPLO.ear' - cause: java.lang.RuntimeException:java.io.FileNotFoundException: C:\XXXX\EJEMPLO.ear\META-INF\jboss-app.xml (El sistema no puede encontrar la ruta especificada)

Leemos aquí lo siguiente: “Every EAR application should specify a unique string name for the class loader”. Así que nos pondremos manos a la obra haciendo lo siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-app>
	<loader-repository>
		EJEMPLO:archive=EJEMPLO.ear
	</loader-repository>
</jboss-app>

El deploy a través de la Admin Console de JBoss sigue fallando. Así que tras otro rato de investigación (Google, qué haría sin ti…), siguiendo pistas de algunos de los foros de JBoss, probaremos a hacer lo siguiente:

  • Detener JBoss
  • Descomprimir el archivo ear en el directorio deploy de JBoss, añadiendo la extensión al directorio (es decir, descomprimiremos EJEMPLO.ear al directorio deploy/EJEMPLO.ear/).
  • Descomprimir dentro de ése directorio los archivos de los EBJ y el WAR en directorios con sus respectivas extensiones.
  • Volver a arrancar JBoss

Viendo los logs al iniciar JBoss, vemos que por fin todo se deploya correctamente. Y si modificamos algún recurso, éste se actualiza correctamente sin necesidad de un redeploy icon smile Exploded deploy en JBoss 6 sobre Windows

¡Espero que os sirva de ayuda! ¡Happy coding!

Solucionando problemas durante el desarrollo: Unable to open sync connection  

Tras un rato de desarrollo en ocasiones el ADB se vuelve un poco loco, y al subir un APK al móvil desde Eclipse recibimos éste error:

Unable to open sync connection!

La solución es sencilla:

  1. Quitar el cable USB
  2. Desactivar la depuración USB en el móvil y volverla a activar
  3. Conectar el cable USB de nuevo

Espero que os sirva de ayuda. ¡Happy coding icon smile Solucionando problemas durante el desarrollo: Unable to open sync connection !

Como hacer que una aplicación solicite permisos de superusuario  

Si tenemos el terminal rooteado podemos hacer muchas tareas interesantes desde nuestras aplicaciones. Pero antes de hacer nada, tenemos que solicitar al usuario los permisos de superusuario.

Haremos un método estático par ayudarnos en las tareas de ejecutar cosas como Root:

/**
 * Ejecuta un comando como Root
 */
public static boolean ejecutarComoRoot(String comando)
{
	Process p = null;

	try
	{
		// Ejecutamos como SU
		p = Runtime.getRuntime().exec("su -c "+comando);

		try
		{
			p.waitFor();

			// Comprobamos si somos root
			if (p.exitValue() != 255)
			{
				Log.i("Serone", "Comando '"+comando+"' ejecutado como root correctamente icon smile Como hacer que una aplicación solicite permisos de superusuario ");
				return true;
			}
			else
			{
				Log.e("Serone", "No somos root, no se puede ejecutar '"+comando+"'...");
			}
		}
		catch (InterruptedException e)
		{
			Log.e("Serone", "No somos root, no se puede ejecutar '"+comando+"'...", e);
		}
	}
	catch (IOException e)
	{
		Log.e("Serone", "No somos root, no se puede ejecutar '"+comando+"'...", e);
	}

	return false;
}

Luego, para solicitar root basta ejecutar cualquier comando, por ejemplo:

// Pedimos root (ejecutando un programa cualquiera como superusuario)
Utils.ejecutarComoRoot("ls");

Inspirado en el código de ésta web.

¡Happy coding!

Cómo hacer que una aplicación Android se pueda mover a la tarjeta SD  

Para permitir ésto basta con añadir android:installLocation=”auto” al manifest, como se puede ver en éste ejemplo:

<?xml version="1.0" encoding="utf-8"?>

<manifest
	xmlns:android="http://schemas.android.com/apk/res/android"
	package="com.serone.test"
	android:versionCode="1"
	android:versionName="1.0"
	android:installLocation="auto"> <!-- Esto nos permite que se instale en SD -->

	...

</manifest>

Tan fácil como eso icon smile Cómo hacer que una aplicación Android se pueda mover a la tarjeta SD ¡Happy coding!

¡Feliz año 2012 desde HijoDeBlog!  

package com.hijodeblog;

import java.util.*;

/**
 * ¡Feliz año 2012 desde HijoDeBlog!
 */
public class Felicitacion
{
 /**
 * Constructor de la felicitación
 */
 void Felicitacion()
 {
 System.out.println("¡Feliz año 2012 desde HijoDeBlog!");
 }
}
Etiquetas: , ,
Comentarios: No hay comentarios aún

Ejecutando tareas paralelas: Pools de hebras  

Paralelizar tareas puede ser una forma rápida y sencilla de optimizar un proceso que se compone de múltiples subprocesos pequeños. Y una forma sencilla de implementar ésta paralelización es el uso de los Pools de hebras.

El método para crear un Pool de hebras es el siguiente (comentaré todo en los comentarios del código:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Main
{
	public static void main(String args[])
	{
		// Creamos un pool de hebras, en éste caso con 10 hebras, podremos
		// configurarlo con el número de hebras que necesitemos
		ExecutorService exec = Executors.newFixedThreadPool(10);

		// Ejecutaremos 100 tareas de ejemplo, que se irán ejecutando poco a poco
		for (int i = 0; i < 100; i++)
		{
			// Creamos cada tarea. Puede ser cualquier clase que implemente el interfaz Runnable
			exec.execute(new Runnable()
			{
				public void run()
				{
					 System.out.println("Ejecutando la hebra " + Thread.currentThread() + "...");
				}
			});
		}

		// Finalizamos el pool de hebras
		exec.shutdown();

		try
		{
			// Eperamos 50 segundos a que todo finalize
			boolean b = exec.awaitTermination(50, TimeUnit.SECONDS);
			System.out.println("Estado tras la espera... " + (b ? "¡Finalizado!" : "No finalizado..."));
		}
		catch (InterruptedException e)
		{
		   e.printStackTrace();
		}
	}
}

Sencillo, ¿a que si? Probadlos, no podréis vivir sin ellos a partir de ahora icon wink Ejecutando tareas paralelas: Pools de hebras

Cómo eliminar tareas residuales del TimerServide de JBoss  

Imaginad que en nuestor poryecto hemos estado usando el TimerService y se han quedado tareas residuales que ya no usamos. Ahora, de forma contínua, recibimos el error siguiente en la consola de JBoss:

[org.jboss.ejb3.timerservice.mk2.task.TimerTask] Error invoking timeout for timer

Para eliminarlo tendremos que ejecutar una vez el código siguiente:

try
{
	InitialContext ic = new InitialContext();
	SessionContext contextoSesion = (SessionContext) ic.lookup("java:comp/EJBContext");

	TimerService timerService = contextoSesion.getTimerService();

	for(Timer timer : timerService.getTimers())
	{
		timer.cancel();
	}
}
catch (Exception ex)
{
	System.out.println(ex.getMessage());
}

Tras ello habrá que eliminar todo el contenido del directorio ${JBOSS_HOME}/standalone/data/time-service-data y reiniciar JBoss par aplicar los cambios.

Espero que os sea de utilidad. ¡Saludos!

Solucionando errores con JBoss: The libs.CopyLibs.classpath property is not set up  

Éste error es más bien debido al uso de NetBeans para desarrollar nuestra aplicación para JBoss. En el archivo “nbproject\build-impl.xml” encontraremos el fragmento siguiente:

<target name="-init-taskdefs">
	<fail unless="libs.CopyLibs.classpath">
		The libs.CopyLibs.classpath property is not set up.
		This property must point to
		org-netbeans-modules-java-j2seproject-copylibstask.jar file which is part
		of NetBeans IDE installation and is usually located at
		&lt;netbeans_installation&gt;/java&lt;version&gt;/ant/extra folder.
		Either open the project in the IDE and make sure CopyLibs library
		exists or setup the property manually. For example like this:
		ant -Dlibs.CopyLibs.classpath=a/path/to/org-netbeans-modules-java-j2seproject-copylibstask.jar
	</fail>
    <taskdef classpath="${libs.CopyLibs.classpath}" resource="org/netbeans/modules/java/j2seproject/copylibstask/antlib.xml"/>
</target>

Para solucionarlo habrá que ir a Tools » Options » Miscallenous » Ant y añadir a la sección Properties la línea siguiente:

ibs.CopyLibs.classpath=DirectorioDeNetbeans/java/ant/extra/org-netbeans-modules-java-j2seproject-copylibstask.jar

Luego, reconstruyendo el proyecto, el error debería estar fuera.

¡Happy coding!

Cómo borrar el DataStore local de Google AppEngine  

Cuando estás desarrollando una aplicación bajo Google AppEngine con el emulador local, en ocasiones necesitas vaciar el almacén de datos JDO de la aplicación. Para hacerlo basta con seguir los siguientes pasos:

  • Borrar el archivo “./WEB-INF/appengine-generated/local_db.bin” (la BD local donde se guardan los datos durante el desarrollo)
  • Limpiar el proyecto y volver a generar para crear de nuevo el DataStore vacío

Así de sencillo icon smile Cómo borrar el DataStore local de Google AppEngine La pista la obtuve de aquí.

¡Happy coding!


Disclaimer: Las imágenes mostradas en ésta página web se utilizan sólamente con propósitos ilustrativos, y son propiedad de sus respectivos autores (cuando es aplicable).
Hijo de Blog es un producto del Dr. SeROne

Los contenidos se ofrecen bajo una licencia de Creative Commons
Attribution-NonCommercial-NoDerivs 3.0 Unported

salvo que se indique lo contrario

Licencia de Creative Commons