lunes, 11 de junio de 2012

Evitando OOM procesando bitmaps

Cuando trabajamos con el procesamiento de imágenes en Android, uno de los principales problemas que nos encontramos es el ya (para mí) típico: "java.lang.OutOfMemoryError: bitmap size exceeds VM budget". Normalmente, este error suele pasar cuando estamos realizando la siguiente acción:
   Bitmap bitmap = BitmapFactory.decodeFile(fileName);
Una opción que en mis proyectos ha funcionado es implementar este método de la siguiente forma:
    private Bitmap decodeFile(File f){
        try {
            //Decode image size
            BitmapFactory.Options o=new BitmapFactory.Options();
            o.inSampleSize = 8;
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f),null,o);

            //The new size we want to scale to
            final int REQUIRED_SIZE=70;

            //Find the correct scale value. It should be the power of 2.
            int scale=1;
            while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale  /2>=REQUIRED_SIZE)
                scale*=2;

            //Decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } catch (FileNotFoundException e) {}
        return null;
    }


 Esta función, funciona en la mayoría de los casos y terminales. En caso que tengáis algun problema, se puede solucionar cambiando los valores de los parámetros:
 - o.inSampleSize;
 - REQUIRED_SIZE;


It works!


Roger Sala,

Facebook y Twitter en tus aplicaciones

Twitter y facebook son las 2 redes sociales que no pueden faltar en tu aplicación si quieres que la gente comparta información des de ella. A parte, de la publicidad que se genera de tu app.
En este post voy a mostrar la forma más sencilla de que tu app permita compartir mediante estas dos redes sociales. Conozco y he probado la APIs de Facebook, Twitter y varias librerías, pero la forma más fácil de hacerlo es abriendo la aplicación y añadirle el texto que quieres que se muestre. Puedes pensar, ¿y si no tengo la app instalada? Muy sencillo, se puede abrir un webview directamente a Facebook o Twitter.
No obstante, se que no se puede generalizar pero en este caso es practicamente absurdo no hacerlo, y es que, todo usuario Android que tiene cuenta a Facebook/Twitter tiene su aplicación instalada, entonces, este método pasa a ser el más fácil y rápido de añadir a tu app.

a continuación les dejo el código a añadir:

public void shareTwitter(Context context, String what)
{
       try {
            Intent sharingIntent = new Intent(Intent.ACTION_SEND);
            sharingIntent.setClassName("com.twitter.android",
                    "com.twitter.android.PostActivity");
            sharingIntent.putExtra(Intent.EXTRA_TEXT, what);
            context.startActivity(sharingIntent);
        } catch (Exception e) {
           //web
            Intent i = new Intent();
            i.putExtra(Intent.EXTRA_TEXT, "Mi primer tweet!");
            i.setAction(Intent.ACTION_VIEW);
            i.setData(Uri.parse("https://mobile.twitter.com/"));
            context.startActivityForResult(i, TWITTER);
       }
}



public static void shareFacebook(Context context, String what) 
{
       try {
            Intent intentF = new Intent(Intent.ACTION_VIEW);
            intentF.setType("text/plain")
                .setAction("android.intent.action.SEND")
                .setFlags(0x3000000)
                .setClassName("com.facebook.katana","com.facebook.katana.ShareLinkActivity")
                                 .putExtra(Intent.EXTRA_TEXT, what);

               context.startActivity(intentF);
       } catch (ActivityNotFoundException ex) {
         // web
           context.startActivity(new Intent(Intent.ACTION_VIEW, Uri
           .parse("http://m.facebook.com/sharer.php?u=" + what)));
}


It works!

Roger Sala,

domingo, 10 de junio de 2012

Testing de la aplicación

Parte del éxito de una aplicación pasa por asegurarse que la aplicación es fiable y robusta. Para publicar nuestra aplicación en Google Play tenemos que estar al 100% seguros que no tiene errores, que no se fuerza el cierre de la aplicación y que está testeada por el máximo de dispositivos Android posibles. Este último punto es el más complicado. ¿Porqué? Actualmente hay más de 800 dispositivos distintos que tienen el sistema operativo Android instalado. A pesar que Android ha intentado crear unos estándares con la resolución de pantalla siempre hay dispositivos que se resisten a estos. ¡Cuántos más hayamos podido probar mejor!

No obstante, cuando no podemos probar todo lo que queríamos la aplicación tenemos que recurrir a otras alternativas. Una de ellas es incorporar la librería BugSense. Esta librería es muy fácil e útil de usar. La gran ventaja es que es totalmente transparente al usuario, con lo cuál los "crashes" de nuestra app se nos informan vía email sin necesidad de la colaboración del usuario. Con ello podemos recibir y solucionar todos los problemas que la aplicación puede generar y que des de nuestros recursos no hemos podido tratar. A parte, entre otras cosas genera estadísticas, agrupa los errores, los podemos clasificar en resueltos/no resueltos.

Su uso está explicado en la web, no obstante la idea principal es:

1.- Crear su propia cuenta de BugSense.
2.- Descargarse el archivo .jar
3.- Incorporarlo al proyecto. (carpeta /libs + configure Build Path + Add to build Path).
4.- Crear nuestra aplicación en la web de BugSense.
5.- Recomendación: Tan pronto como se ejecute la app añadir la linea de código siguiente:
       BugSenseHandler.setup(this, "ID de la app en BugSense");

6.- Intentar crear un crash de la app y ver que se recibe el correo.
7.- Preparada para publicar con la tranquilidad que todos los "crashes" podrán ser tratados.

It works!

Roger Sala,

Google Analytics

Google Analytics para desarrolladores es un servicio gratuito que nos proporciona Google que podemos usar para gestionar/tener estadísticas/controlar los accesos a nuestra aplicación.

Para añadirlo en nuestra aplicación podemos seguir los siguientes pasos:

1.- Creamos una cuenta de Analytics a partir de nuestra cuenta de gmail. 

2.- Una vez creada la cuenta, podemos añadir el nombre de nuestra aplicación. Una vez añadida obtenemos un UID que nos vamos a guardar para añadirlo en nuestra aplicación.

3.- Volviendo a Eclipse... Añadimos el archivo GoogleAnalytics.jar a la carpeta /libs de nuestro proyecto. Click derecho + Configure Build Path + Add to Build Path.

4.- Añadimos los permisos necesarios en el AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

5.- Una vez añadido ya podemos usar el Tracker (método de Google Analytics). A continuación un ejemplo fácil de como hacerlo.

public class Example extends Activity{

       GoogleAnalyticsTracker mTracker = GoogleAnalyticsTracker.getInstance();

      @Override
      public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
         mtracker.startNewSession(/*UID de Google Analytics*/, this);
         mtracker.trackPageView("nombre que aparecerá en las estadísticas");
      }

    @Override
    protected void onPause() {
        mTracker.dispatch();
        super.onPause();
    }
   
    @Override
    public void onDestroy() {
        super.onDestroy();
        mTracker.stopSession();
    }

}


Si accedemos ahora a nuestra cuenta de GoogleAnalytics ya podemos ver nuestra página indexada en las estadísticas!

It works!

Roger Sala,


Enviar correo

Muchas veces des de nuestra aplicación queremos facilitar al usuario la posibilidad de mandar un correo des de nuestra aplicación. Por ejemplo, añadir la opción de contactar y/o sugerirnos mejoras/críticas en nuestra aplicación. Para llevarlo a cabo basta con añadir el siguiente fragmento de código.

Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND); 
emailIntent.setType("message/rfc822");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{getResources().getString(R.string.contactMail) }); 
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, getString(R.string.mailSubject)); 
startActivity(Intent.createChooser(emailIntent, getString(R.string.mailSend)));

Esto es todo!

It works!

Roger Sala,

sábado, 2 de junio de 2012

Navigator GPS

Desde nuestra aplicación podemos abrir otras aplicaciones como por ejemplo el correo, facebook, twitter, etc. En este caso vamos a ver como abrir la aplicación Navigator de nuestro dispositivo y mostrar la indicaciones para llegar hasta un punto concreto.

Para ello añadimos el siguiente código ya sea en un OnClickListener de ListView, ImageButton, Button, etc.

startActivity(new Intent(Intent.ACTION_VIEW, Uri
                        .parse("google.navigation:q=" + siteLatitude + ","
                                + siteLongitude)));

Espero que os sirva y a disfrutar!


It works!

Roger Sala 

Custom Splash

Android por defecto no añade a sus proyectos una vista de Splash dónde se inicie la aplicación. No obstante, mediante Thread tenemos la posibilidad de implementar nuestra propia vista de Splash. Para ello podemos crear Activity siguiente:

public class Splash extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash);

        try {
            Thread splashThread = new Thread() {
                @Override
                public void run() {
                    try {
                        int waited = 0;
                        while (waited < 800) {
                            sleep(80);
                            waited += 100;
                        }
                        // perquè aixi quan premin back no apareixi aquesta
                        // vista
                        finish();
                        Intent intent = new Intent(Splash.this,
                                ClassToGo.class);
                        startActivity(intent);
                    } catch (InterruptedException e) {
                    }
                }
            };
            splashThread.start();
        } catch (Exception e) {
        }

    }
}

A continuación añadimos en la carpeta de res/layout/splash.xml:

 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@android:color/white">

    <ImageView
        android:id="@+id/splash"
        android:layout_alignParentTop="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:src="@drawable/ic_launcher" />

</RelativeLayout>

Y ya tenemos nuestra propia vista splash. Obviamente, se puede variar el formato y aprovechar el Splash para cargar la información de los webservices. Esta funcionalidad ya depende de cada uno!


It works!


Roger Sala