domingo, 29 de julio de 2012

Personalizar esquinas en la vistas

En algunos diseños podemos tener la necesidad de usar un background con su marco definido. Para generar la línia que define el marco podemos usar el siguiente código (los xml generados se tienen que crear en nuestro directorio /res/drawable):

Rectangle.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <corners android:radius="1dip" />
    <stroke
        android:width="1sp"
        android:color="#000000" />
    <solid android:color="#FFFFFF" />
    <padding
        android:bottom="3dip"
        android:left="3dip"
        android:right="3dip"
        android:top="3dip" />
</shape>        

Rounded.xml      
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <corners android:radius="10dip" />
    <stroke
        android:width="1sp"
        android:color="#000000" />
    <solid android:color="#FFFFFF" />
    <padding
        android:bottom="3dip"
        android:left="3dip"
        android:right="3dip"
        android:top="3dip" />
</shape>                  


El código anterior lo podemos añadir a nuestras vistas, como se hace en el ejemplo siguiente (notad que se añade en los TextView, pero eso es aplicable a todo lo que se una vista):


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:gravity="center"
    android:orientation="vertical" >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/corners_rectangle"
        android:padding="@dimen/padding_medium"
        android:text="Rectangle"
        tools:context=".CornerActivity" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dip"
        android:background="@drawable/corners_rounded"
        android:padding="@dimen/padding_medium"
        android:text="Rounded"
        tools:context=".CornerActivity" />
</LinearLayout>

La siguiente imagen nos muestra cómo queda nuestra vista:


It works!

Roger Sala,

domingo, 22 de julio de 2012

SlidingDrawer

En Android, podemos crear vistas/menú de opciones a partir de este objeto que se nos ofrece. La idea es usarlo para gestionar su aparición en pantalla des de alguna parte de la vista (izquierda - derecha, derecha - izquierda, arriba - abajo, abajo - arriba). Dentro de la vista del SlidingDrawable podemos añadir un layout personalizado 100%. A continuación el código para crear una base:

activity_my_sliding_drawable.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <SlidingDrawer
        android:id="@+id/slidingDrawer1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:content="@+id/content"
        android:handle="@+id/handle_button_1"
        android:topOffset="50dip" >

        <Button
            android:id="@+id/handle_button_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Bottom to Top" >
        </Button>

        <LinearLayout
            android:id="@+id/content"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="#FF444444"
            android:gravity="center"
            android:orientation="vertical" >

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Item 1" >
            </Button>

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Item 2" >
            </Button>

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Item 3" >
            </Button>

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Item 4" >
            </Button>

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Item 5" >
            </Button>
        </LinearLayout>
    </SlidingDrawer>
</LinearLayout>

MySlidingDrawable.java
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;

public class MySlidingDrawable extends Activity {

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

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_my_sliding_drawable, menu);
        return true;
    }
}

Aquí unas capturas de la aplicación:






It works!

Roger Sala,


Conexiones HTTPS

En Android para crear conexiones seguras tenemos que habilitarlo nosotros manualmente en el código. Para ello podemos usar el siguiente código:


HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

DefaultHttpClient client = new DefaultHttpClient();

SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory
.getSocketFactory();
socketFactory
.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(
client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr,
client.getParams());
// Set verifier
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
HttpGet httpget = new HttpGet(URL);
HttpResponse httpResponse = httpClient.execute(httpget);

It works!

Roger Sala,

sábado, 21 de julio de 2012

Cómo lanzar otras aplicaciones

En algun momento, puede ser necesario que nuestra aplicación requiera de otra. Ya sea porqué es una aplicación específica de la nuestra, porqué necesitamos de sus servicios...Para ello podemos invocarla a partir del "package name" con la que se encuentra subida al PlayStore. A continuación les dejo el fragmento de código que permite realizar dicha acción:


private static final String TARGET_APP = "packageName";
ApplicationInfo info = null;
try{
   //comprobamos que el usuario tenga la aplicación instalada
    info = getActivity().getPackageManager().
            getApplicationInfo(TARGET_APP, 0 );
} catch( PackageManager.NameNotFoundException e ){
}

//si NO tiene la aplicación instalada le redirigimos a uno de los 2 markets para que se la descargue
if(info == null){
    try {
        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id="+ TARGET_APP)));
         } catch (android.content.ActivityNotFoundException anfe) {
            startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://play.google.com/store/apps/details?id="+ TARGET_APP)));
         }
}else{
   //si la tiene instalada la abrimos
    Intent LaunchIntent = getActivity().getPackageManager().getLaunchIntentForPackage(TARGET_APP);
   startActivity(LaunchIntent);
}

It works!

Roger Sala,

lunes, 16 de julio de 2012

ADB Timeout Connection

En algunas ocasiones cuando estamos provando nuestras aplicaciones nos pasa que en la consola de Eclipse vemos el siguiente error:
Failed to install *.apk on device *:
timeout Launch canceled!
Este se produce debido a que el tiempo de conexión que tiene configurado Eclipse en sus preferencias es de 5000ms por defecto. Algunos dispositivos por ciertos motivos pueden necesitar más tiempo. Para ello podemos modificar el timeout a partir de los siguientes pasos:
En Eclipse...Window -> Preferencias -> Android -> DDMS o bien Eclipse -> Preferencias -> Android -> DDMS y luego modificamos el timeou por defecto, por ejemplo, a 10000ms.
It works!
Roger Sala,

jueves, 12 de julio de 2012

Google Maps: Obtener clave

En Android para poder usar la API de Google Maps es necesario: Asignar a nuestro proyecto mediante la elección de API la que contiene Google Maps. Por ejemplo, si deseamos trabajar con API de nivel 15 tendríamos que escoger la API de nivel 15 Google Inc. A parte, tenemos que generar una clave privada de debug (al publicar la app se tiene que volver a generar a partir del certificado creado).

En este post vamos a ver como se crea una clave de Google Maps para debugar.

1.- Abrimos el terminal (línea de comandos). Y pegamos el comando siguiente:
keytool -list -alias androiddebugkey -keystore .android/debug.keystore
Este comando genera automáticamente una clave MD5, la cuál vamos a copiar para usarla en el paso 2.


NOTA: En caso de no saber la ruta de nuestra debug.keystore la podemos obtener a partir del eclipse: Eclipse --> preferences --> Android --> Build


2.- Accedemos a la siguiente dirección:

https://developers.google.com/android/maps-api-signup?hl=ca

A la parte inferior podemos pegar el código MD5 que hemos obtenido. Aceptamos la condiciones y ya tenemos la clave de debug generada.

Esta clave la podemos usar en todos nuestros proyectos. No hace falta generar una clave para cada uno de ellos.

IMPORTANTE: Antes de subir la aplicación al Playstore tenemos que generar (con los mismos pasos) una nueva clave con el certificado que hemos firmado la app.

It works!

Roger Sala,

martes, 10 de julio de 2012

EditText: Validar el formato del correo

Si en nuestra aplicación creamos un campo de entrada de correo electrónico mediante un editText no es suficiente con asignarle el atribute inputType="emailAdress" ya que eso solo despliega el teclado en modo correo.

Una vez el usuario ha entrado el texto tenemos que comprobar que el correo tiene el formato válido. Para ello podemos usar el siguiente código.

public static boolean checkValidEmail(String email) {
     String emailPattern = "[a-zA-Z0-9._-]+@[a-z]+\\.+[a-z]+";
     if (email.matches(emailPattern) && email.length() > 0){
           return true;
      }
      return false;
}

It works!


Roger Sala

Google Maps: Mostrar dirección del usuario

Dependiendo de la aplicación que estamos desarrollando nos puede interesar mostrar al usuario cuál es su dirección actual (calle, número, población...). Mediante la siguiente función podemos realizar dicha acción:


private String getAddress() {
     Geocoder geoCoder = new Geocoder(getBaseContext(), Locale.getDefault());
     List<Address> addresses;
     String location = "Cannot find user address";
     try {
          addresses = geoCoder.getFromLocation(userPosition.getLatitudeE6() / 1E6,
                                                                     userPosition.getLongitudeE6() / 1E6, 1);
          
          if (addresses.size() > 0) {
               location += addresses.get(0).getAddressLine(0) + ", " + addresses.get(0).getLocality();
      }
     return location;
     } catch (IOException e) {
            return location;
     }
}

Así de simple. La variable "userPostion" es la posición actual del usuario.

it works!

Roger Sala,



lunes, 9 de julio de 2012

Función para leer la entrada de datos

En ciertas ocasiones queremos ver la entrada que nos manda el servidor antes de tratarla. Para ello podemos usar la siguiente función:

 private void readStream(InputStream in) {
      BufferedReader reader = null;
      try {
          reader = new BufferedReader(new InputStreamReader(in));
          String line = "";
          while ((line = reader.readLine()) != null) {
                 //System.out.println(line);
                 Log.d("readStream", line);
          }
       } catch (IOException e) {
            e.printStackTrace();
       } finally {
            if (reader != null) {
                 try {
                   reader.close();
                 } catch (IOException e) {
                   e.printStackTrace();
                 }
            }
       }
 }

Simple pero...it works!

Roger Sala,

domingo, 8 de julio de 2012

Estilos ProgressBar

En muchas situaciones el proceso de obtener/cargar datos puede durar varios segundos. En estas situaciones puede ser necesario bloquear la vista del usuario o bien trabajar con un hilo paralelo. Lo importante es indicar al usuario que la aplicación no esta bloqueada sino que esta en un proceso. Para ello podemos utilizar las ProgressBar. En este post vamos a tratar este tema. Básicamente, mostraremos como añadir ProgressBar mediante xml y los distintos estilos que hay.

 1) Para crear una progressBar donde se vea la evolución del proceso añadimos lo siguiente en nuestro xml:


<ProgressBar
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:progress="100" />


2) Para crear una progressBar indeterminado y tamaño pequeño añadimos lo siguiente en nuestro xml:

   <ProgressBar
        style="?android:attr/progressBarStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
 

3) Para crear una progressBar indeterminado y tamaño normal añadimos lo siguiente en nuestro xml:

    <ProgressBar
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />



4) Para crear una progressBar indeterminado y tamaño grande añadimos lo siguiente en nuestro xml:


    <ProgressBar
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>


It works!

Roger Sala,

domingo, 1 de julio de 2012

Notificaciones y Notificicaciones Builder

En nuestras aplicaciones nos puede interesar comunicar cierta información y asegurarnos que el usuario sepa que se ha producido ese evento. Para ello podemos usar el sistema de  notificaciones que Android nos ofrece. Existen dos tipos de notificación: des de un servidor externo (C2DM) o bien des de la propia aplicación. En este post, vamos a hablar de como una aplicación misma puede generar sus propias notificaciones. Veremos que se usa la librería de compatibilidad v4. Este hecho se produce debido a que la clase "Notification" de Android está "deprecated".  A continuación el código:

Antes de empezar
Añadimos la librería de compatibilidad v4.
1.- Crear la carpeta /libs en el proyecto.
2.- Copiar el .jar (de la compatibilidad v4).
3.- Click derecho + add to build path

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.gydapp.appNotification"
    android:installLocation="preferExternal"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".NotificationsActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

NotificationsActivity
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.view.View;
import android.widget.Button;

public class NotificationsActivity extends Activity {

    private final int NOTIFICATION_ID = 1;

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

        // setup notification button
        Button notificationButton = (Button) findViewById(R.id.button);
        notificationButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                createNotification();
            }
        });
    }

    private void createNotification() {

        // setup notifications system
        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        Intent notificationIntent = new Intent(this,
                NotificationsActivity.class);
      
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
      
        // Using library compat
        NotificationCompat.Builder builder = new NotificationCompat.Builder(
                this);
        builder.setContentIntent(pendingIntent)
                .setWhen(System.currentTimeMillis())
                .setTicker("Notification ticker")
                .setSmallIcon(R.drawable.ic_launcher)
                .setContentTitle("Notification title")
                .setContentText("Notification text")
                .setAutoCancel(true);
      
        notificationManager.notify(NOTIFICATION_ID, builder.getNotification());
      
           //Notification class the same that Builder
//         Notification notification = new Notification(R.drawable.ic_launcher,
//                "Notification ticker", System.currentTimeMillis());
//
//       
//         notification.flags |= Notification.FLAG_AUTO_CANCEL;
//       
//        notification.setLatestEventInfo(this, "Notification title",
//                "Notification text", pendingIntent);
//        
//        notificationManager.notify(NOTIFICATION_ID, notification);
   
    }
}

main.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:orientation="vertical" >
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Generate Notification" >
    </Button>
</RelativeLayout>

A continuación la imagen de la ejecución:



It works!

Roger Sala,