Wednesday, December 2, 2015

Notificaciones en Android usando Parse.com

El proposito de este tutorial
El producto final va a ser una simple notificacion enviada desde la pagina web de Parse.com, y usaremos la plataforma de Parse para recibirla en Android. Cuando el usuario toque la notificacion en Android, la applicacion de Android se abrira automaticamente.
Todo esto se hara al configurar la plataforma de Parse.com y su SDK de Android.


Si prefieres ver este tutorial en video, subi un video mostrando esto pasa a paso en este link.


Que se necesita para este tutorial


Una cuenta en Parse.com. Una cuenta gratis sera suficiente para este ejercicio.
Un proyecto en Parse. Cualquier proyecto en Parse.com servira. (Si esto es muy complicado mandame un email y agrego los pasos para hacer el proyecto)
Android Studio
Un telefono Android, o el emulador

Comencemos!

Este tutorial esta hecho usando la guia de Parse.com para un proyecto ya existente de Android en vez de un proyecto nuevo. De esta forma este tutorial servira para ambos casos.

1. Obten la informacion de tu proyecto en Parse
Una vez que creas el proyecto en Parse, deberias ver algo similar a esto (Nov. 2015):


Primero que nada vamos a usar Gradle para instalar las librerias, por lo que no no va a ser necesario descargar el archivo .zip. No te preocupes de esto e ignora el primer paso mencionado en Parse.
Sin embargo, ya que vamos a usar Gradle para crear el proyector, es necesario agregar las dependencias que se muestran en el segundo paso. Haremos esto mas adelante.

La siguiente seccion es tambien muy importante ya que tiene nuestro ID y llave del proyecto de parse (Parse Application Id y Client Key).
Tu deberias tener tu propio par de ID y llave para usar especificamente con tu proyecto (Yo escondi los mios aca):

Por ahora deja abierta esta pagina web con la informacion de tu proyecto de Parse. Vamos a usar esta information en el proyecto de Android.

2. Crea un proyecto en Androi, o abre un proyecto existente
Si vas a crear un proyecto nuevo, cualquier proyecto va a servir para esta prueba. Es mejor si que tu proyecto soporte Android OS 4.1, o mas nuevo.

Para este tutorial yo cree un nuevo proyecto llamado "Test_ParsePush", y el nombre de el paquete de este proyecto es "com.eduardoflores.test_parsepush".
No importa cual es el nombre de tu paquete, pero si es necesario acordarse cual es ya que lo usaremos en el archivo de manifest.

3. Modifica tu archivo build.gradle (Module:app)
En este momento la estructura de tu proyecto en Android Studio deberia ser similar a esta:

Abre el archivo build.gradle que esta en tu modulo (si solo tienes 1 modulo, el modulo se llamara "app").
Al final de este archivo, en la seccion de "dependencies" vamos a agregar las dependencias de Parse que te dio Parse en su website al comienzo. Esto agregara el SDK de Parse a tu proyecto:
    compile 'com.parse.bolts:bolts-android:1.+'
    compile 'com.parse:parse-android:1.+'
Tus dependencias deberian ser ahora similares a estas (tu talvez tengas un poco mas o menos dependencias que venian con tu proyecto):
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.0.1'
    compile 'com.android.support:design:23.0.1'
    compile 'com.parse.bolts:bolts-android:1.+'
    compile 'com.parse:parse-android:1.+'
}

Ahora agrega el repositorio maven de donde vas a sacar las herramientas de Parse. (nota: esto es algo que no se menciona en los tutoriales de Parse):
buildscript {
    repositories {
        mavenCentral()
        maven { url 'https://maven.parse.com/repo' }
    }
    dependencies {
        classpath 'com.parse.tools:gradle:1.+'
    }
}
Y ahora finalmente agrega el plugin de Parse al comienzo de tu archivo build.gradle, asi:
apply plugin: 'com.parse'
Ahora tu archivo build.gradle completo deberia se deberia ver asi:
apply plugin: 'com.android.application'
apply plugin: 'com.parse'

buildscript {
    repositories {
        mavenCentral()
        maven { url 'https://maven.parse.com/repo' }
    }
    dependencies {
        classpath 'com.parse.tools:gradle:1.+'
    }
}

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "eduardoflores.com.test_parsepush"
        minSdkVersion 16
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.0.1'
    compile 'com.android.support:design:23.0.1'
    compile 'com.parse.bolts:bolts-android:1.+'
    compile 'com.parse:parse-android:1.+'
}
 
Estamos listos con el archivo build.gradle y lo puedes cerrar.

4. Modifica tu archivo Manifest
Abre el archivo de manifest en tu aplicacion, en Android.
- En el archivo manifest, antes de <application, necesitas agregar 2 cosas.
La primera cosa es esta:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
La segunda cosa require cambiar el nombre del paquete a el nombre del paquete de tu aplicacion de Android:
<permission android:protectionLevel="signature"
                android:name="TU_PAQUETE.permission.C2D_MESSAGE" />
<uses-permission android:name="TU_PAQUETE.permission.C2D_MESSAGE" />
Aca, es importante de que cambies el texto de "TU_PAQUETE" con el nombre del paquete de tu aplicacion de Android. En mi caso, como lo mencione en el paso numero 2, el nombre del paquete de mi aplicacion es "com.eduardoflores.test_parsepush"

- Ahora en el mismo archivo de manifest, entre las ultimas etiquetas </activity> y </application>, necesitas poner la informacion de GCM para recibir tu mensaje:
<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParsePushBroadcastReceiver"
          android:exported="false">
    <intent-filter>
        <action android:name="com.parse.push.intent.RECEIVE" />
        <action android:name="com.parse.push.intent.DELETE" />
        <action android:name="com.parse.push.intent.OPEN" />
    </intent-filter>
</receiver>
<receiver android:name="com.parse.GcmBroadcastReceiver"
          android:permission="com.google.android.c2dm.permission.SEND">
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <category android:name="TU_PAQUETE" />
    </intent-filter>
</receiver>
Date cuenta de que tambien debes poner el nombre del paquete de tu aplicacion en la ultima categoria de nombre.
Y asi, con el nombre del paquete de la aplicacion reemplazado, todo tu archivo manifest deberia ser similar a esto:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="eduardoflores.com.test_parsepush" >

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <permission android:protectionLevel="signature"
                android:name="eduardoflores.com.test_parsepush.permission.C2D_MESSAGE" />
    <uses-permission android:name="eduardoflores.com.test_parsepush.permission.C2D_MESSAGE" />

    <application
        android:name=".StarterClass"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <service android:name="com.parse.PushService" />
        <receiver android:name="com.parse.ParsePushBroadcastReceiver"
                  android:exported="false">
            <intent-filter>
                <action android:name="com.parse.push.intent.RECEIVE" />
                <action android:name="com.parse.push.intent.DELETE" />
                <action android:name="com.parse.push.intent.OPEN" />
            </intent-filter>
        </receiver>
        <receiver android:name="com.parse.GcmBroadcastReceiver"
                  android:permission="com.google.android.c2dm.permission.SEND">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
                <category android:name="eduardoflores.com.test_parsepush" />
            </intent-filter>
        </receiver>
    </application>
</manifest>
Y ahora estas tambien listo con el archivo de manifest (lo de name=.StarterClass lo voy a explicar despues).

5. Escribe el codigo de Java en tu aplicacion Android
En tu actividad inicial debes inicializar el SDK de Parse con las llaves de Parse y el ID, y luego le dices a Parse que guarde eso en otro proceso.

Lo siguiente es muy importante: TU APLICACION NO VA A FUNCIONAR SI INICIALIZAS PARSE MAS DE UNA VEZ DENTRO DE TU APLICACION.

Que significa esto? Si tu inicializas Parse en el metodo de tu MainActivity, la aplicacion va a funcionar y vas a poder recibir notificaciones, pero solo si la aplicacion esta corriendo.
Una vez que la notificacion llegue tu aplicacion va a comenzar, el metodo onCreate() va a ser llamado nuevamente y Parse va a ser inicializado de nuevo. Esto hara que la aplicacion se termine con un mensaje de "Unable to create service com.parse.PushService: java.lang.NullPointerException" (no es posible crear un servicio de com.parse.PushService)
Para evitar esto vamos a crear una actividad simple que lo unico que va a ser es comenzar la aplicacion, junto con inicializar la libreria de Parse.


Crea una clase simple

Crea un nuevo archivo de java llamado "StarterClass.java" y haz que esta clase extienda Activity.

En la clase StarterClass, crea un metodo onCreate(), y adentro de este metodo, despues del super() metodo, agrega esto:
Parse.initialize(this, APPLICATION_ID, CLIENT_KEY);
ParseInstallation.getCurrentInstallation().saveInBackground();

Asi con eso, tu clase basica completa va a ser asi:
package eduardoflores.com.test_parsepush;

import com.parse.Parse;
import com.parse.ParseInstallation;

import android.app.Application;

/**
 * @author Eduardo Flores
 */
public class StarterClass extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        // Inicializa Parse
        Parse.initialize(this, "application_id_from_parse", "client_key_from_parse");
        ParseInstallation.getCurrentInstallation().saveInBackground();
    }
}
 
Esta clase StarterClass que creamos es lo que definimos en el archivo manifest bajo el nombre de name=".StarterClass" para la aplicacion. Asi esta clase es invocada solo una vez, haciendo que Parse tambien se inicialize una sola vez.

Y con eso, todo lo que necesitas ahora es mandar notificaciones desde Parse.com!
Corre tu aplicacion de Android y manda un mensaje desde Parse.com, y todo deberia funcionar como esto:


 

Y finalmente, puedes bajar todo el codigo de este tutorial desde aca.


Eduardo Flores.

6 comments:

  1. podrías hacer un video explicandolo paso a paso?

    ReplyDelete
    Replies
    1. Dame un par de dias para pensar como grabarlo y editarlo, y lo subo a youtube.

      Delete
  2. ok, subi el video y puse el link al comienzo del tutorial. Dime si tienes algun problema.

    ReplyDelete
  3. Este codigo me funciono de maravillas.

    Pero actualmente me esta tirando el siguiente error:
    "Error:Cause: peer not authenticated"

    Creo que hace referencia este código

    dependencies {
    classpath 'com.parse.tools:gradle:1.+'
    }

    Te paso lo mismo? Sera por la migración del servicio de Parse?

    Gracias!

    ReplyDelete
    Replies
    1. Fabrizio, la verdad es que no he probado esto de nuevo, y te sugeriria que no pierdas tu tiempo con esto. Parse se va a cerrar en un par de meses, por lo que todas las aplicaciones hechas en Parse van a desaparecer.

      Prueba Firebase.

      Delete