Notificaciones Push en la plataforma Android

266

Estoy buscando escribir una aplicación que reciba alertas enviadas desde un servidor. Encontré un par de métodos para hacer esto.

  1. SMS: intercepta los SMS entrantes e inicia una extracción desde el servidor
  2. Sondear el servidor periódicamente

Cada uno tiene sus propias limitaciones. SMS: no hay garantía en la hora de llegada. La encuesta puede agotar la batería.

¿Tiene una mejor sugerencia por favor? Muchas gracias.

Vinod
fuente
44
También puede ver la presentación de Google I / O 2010 sobre Push Notification developer.android.com/videos/index.html#v=PLM4LajwDVc
vokilam
Creo que puedes mirar esta publicación: stackoverflow.com/questions/17629942/… Con Worklight puedes recibir notificaciones a través de diferentes canales, incluido GCM.
Neeraj Krishna
1
La presentación de Google I / O 2010 está disponible en youtube.com/watch?v=PLM4LajwDVc
elcuco el
"La encuesta puede agotar la batería". Puede programar la encuesta con AlarmManager, para que la batería no se agote demasiado. Es una solución simple y gratuita (no es necesario pagar, como con GCM).
Deepscorn
tiene el mismo problema stackoverflow.com/questions/35812304/…
albert

Respuestas:

203

La respuesta oficial de Google es Android Cloud to Device Messaging Framework (en desuso) Google Cloud Messaging (en desuso) Firebase Cloud Messaging

Funcionará en Android> = 2.2 (en teléfonos que tienen Play Store).

BoD
fuente
está en beta en este momento, pero puedes registrarte con la esperanza de ser activado.
brack
3
En general, puede activarse muy rápidamente, y se está utilizando para cosas como GMail, por lo que se sabe que funciona en la producción. Desafortunadamente, falta su código de muestra para comunicarse con el aspecto del lado del servidor de C2DM. He escrito un tutorial para ese aspecto aquí blog.boxedice.com/2010/10/07/…
davidmytton
66
El problema es que necesita una cuenta de Google para sus usuarios: lo cual, creo, es una restricción.
kaffein
33
Tenga en cuenta que Android Cloud to Device Messaging Framework ha quedado en desuso. El nuevo marco se llama Google Cloud Messaging y se puede encontrar aquí: developer.android.com/guide/google/gcm/index.html
Ryan Berger
El 10 de abril de 2018, Google dejó de usar GCM. El servidor GCM y las API del cliente se eliminaron el 29 de mayo de 2019. Migre las aplicaciones GCM a Firebase Cloud Messaging (FCM), que hereda la infraestructura GCM confiable y escalable, además de muchas características nuevas. Consulte la guía de migración para obtener más información.
paiego
29

( Publicación cruzada de una respuesta que di a una pregunta similar: ¿es compatible Android con notificaciones push casi en tiempo real? )

Recientemente comencé a jugar con MQTT http://mqtt.org para Android como una forma de hacer este tipo de cosas (es decir, notificaciones push que no son SMS sino datos, entrega de mensajes casi inmediata, no sondeo, etc.)

Tengo una publicación de blog con información de fondo sobre esto en caso de que sea útil

http://dalelane.co.uk/blog/?p=938

(Nota: MQTT es una tecnología de IBM, y debo señalar que trabajo para IBM).

Dalelane
fuente
Hola Dale, leí tu publicación de blog sobre MQTT y definitivamente parece encajar en la factura de notificaciones casi instantáneas en móviles. Pero no he podido encontrar ninguna información sobre cómo lo hace realmente. ¿Mantiene un enchufe abierto en todo momento? ¿Cómo notifica al servidor si su dirección IP ha cambiado? Le agradecería si pudiera arrojar algo de luz sobre esto. Saludos Naren
Naren
2
Mantiene una conexión abierta. En una publicación de seguimiento ( dalelane.co.uk/blog/?p=1009 ) hablé más sobre las implicaciones de mantener una conexión abierta, ¿lo viste? Si la conexión se interrumpe, tanto el servidor como el cliente pueden ser notificados. Entonces es una decisión de la capa de aplicación decidir cómo responder (por ejemplo, volver a conectar). Hay más información en los documentos a los que se hace referencia en la publicación (por ejemplo, IA92: www-01.ibm.com/support/docview.wss?rs=171&uid=swg24006006 pdf en esa página, y Javadoc en el zip en esa página)
dalelane 05 de
18

Mi comprensión / experiencia con la notificación push de Android son:

  1. C2DM GCM : si su plataforma Android objetivo es 2.2+, entonces hágalo. Solo una trampa, los usuarios de dispositivos deben estar siempre conectados con una cuenta de Google para recibir los mensajes.

  2. MQTT : enfoque basado en Pub / Sub, necesita una conexión activa desde el dispositivo, puede agotar la batería si no se implementa con sensatez.

  3. Diácono : puede no ser bueno a largo plazo debido al apoyo limitado de la comunidad.

Editar : Agregado el 25 de noviembre de 2013

GCM - Google dice ...

Para dispositivos anteriores a 3.0, esto requiere que los usuarios configuren su cuenta de Google en sus dispositivos móviles. Una cuenta de Google no es un requisito en dispositivos con Android 4.0.4 o superior. *

Lalit
fuente
Si bien no se requiere una cuenta de Google para 4.0.4 o superior, parece requerir que tenga instalada la aplicación Google Play. Me pregunto cómo instalar eso sin tener una cuenta de Google.
Jan
1
@ Jan: la aplicación Google Play viene instalada con el dispositivo. El usuario no necesita instalar.
Dexter
@Dexter, no todos los dispositivos Android tienen Google Play instalado de manera predeterminada. La mayoría lo tiene instalado de manera predeterminada, especialmente los dispositivos que se compran a proveedores de teléfonos de renombre, pero los dispositivos que solo tienen el sistema operativo Android actualizado no siempre tienen Google Play. (Por ejemplo, muchos emuladores de Android, como los nuevos dispositivos Genymotion, no tienen Google Play de forma predeterminada.)
Spencer D
Entonces ... ¿Es MQTT la mejor opción para dispositivos Android que no tiene instalado Google Play?
Yeung
17

Marco de mensajería de Android Cloud a dispositivo

Importante: C2DM ha quedado en desuso oficialmente a partir del 26 de junio de 2012. Esto significa que C2DM ha dejado de aceptar nuevos usuarios y solicitudes de cuotas. No se agregarán nuevas funciones a C2DM. Sin embargo, las aplicaciones que usan C2DM continuarán funcionando. Se alienta a los desarrolladores existentes de C2DM a migrar a la nueva versión de C2DM, llamada Google Cloud Messaging para Android (GCM). Consulte el documento de migración de C2DM a GCM para obtener más información. Los desarrolladores deben usar GCM para nuevos desarrollos.

Compruebe amablemente el siguiente enlace:

http://developer.android.com/guide/google/gcm/index.html

chiranjib
fuente
17

Aquí he escrito algunos pasos para obtener RegID y notificaciones a partir de cero

  1. Crear / Registrar aplicación en Google Cloud
  2. Configurar Cloud SDK con desarrollo
  3. Configurar proyecto para GCM
  4. Obtener ID de registro del dispositivo
  5. Enviar notificaciones push
  6. Recibir notificaciones push

Puede encontrar el tutorial completo en el siguiente enlace URL

Primeros pasos con la notificación push de Android: último Google Cloud Messaging (GCM): tutorial completo paso a paso

ingrese la descripción de la imagen aquí

Recorte de código para obtener la ID de registro (Token de dispositivo para notificación push).

Configurar proyecto para GCM


Actualizar el archivo AndroidManifest

Para habilitar GCM en nuestro proyecto, necesitamos agregar algunos permisos en nuestro archivo de manifiesto Vaya a AndroidManifest.xml y agregue el código siguiente Agregar permiso

<uses-permission android:name="android.permission.INTERNET”/>
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<uses-permission android:name="android.permission.VIBRATE" />

<uses-permission android:name=“.permission.RECEIVE" />
<uses-permission android:name=“<your_package_name_here>.permission.C2D_MESSAGE" />
<permission android:name=“<your_package_name_here>.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

Agregar declaración de receptor de difusión de GCM

agregue la declaración del receptor de difusión de GCM en la etiqueta de su aplicación

<application
        <receiver
            android:name=".GcmBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" ]]>
            <intent-filter]]>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <category android:name="" />
            </intent-filter]]>

        </receiver]]>
     
<application/>

Agregar declaración de servicio de GCM

<application
     <service android:name=".GcmIntentService" />
<application/>

Obtener ID de registro (token de dispositivo para notificación push)

Ahora vaya a su Actividad de lanzamiento / bienvenida

Agregar constantes y variables de clase

private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
public static final String EXTRA_MESSAGE = "message";
public static final String PROPERTY_REG_ID = "registration_id";
private static final String PROPERTY_APP_VERSION = "appVersion";
private final static String TAG = "LaunchActivity";
protected String SENDER_ID = "Your_sender_id";
private GoogleCloudMessaging gcm =null;
private String regid = null;
private Context context= null;

Actualizar los métodos OnCreate y OnResume

@Override
protected void onCreate(Bundle savedInstanceState)
{
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_launch);
     context = getApplicationContext();
         if (checkPlayServices()) 
     {
            gcm = GoogleCloudMessaging.getInstance(this);
            regid = getRegistrationId(context);

            if (regid.isEmpty())
            {
                registerInBackground();
            }
            else
            {
            Log.d(TAG, "No valid Google Play Services APK found.");
            }
      }
 }

@Override protected void onResume()
{
       super.onResume();       checkPlayServices();
}


# Implement GCM Required methods (Add below methods in LaunchActivity)

private boolean checkPlayServices() {
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (resultCode != ConnectionResult.SUCCESS) {
            if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
                GooglePlayServicesUtil.getErrorDialog(resultCode, this,
                        PLAY_SERVICES_RESOLUTION_REQUEST).show();
            } else {
                Log.d(TAG, "This device is not supported - Google Play Services.");
                finish();
            }
            return false;
        }
        return true;
 }

private String getRegistrationId(Context context) 
{
   final SharedPreferences prefs = getGCMPreferences(context);
   String registrationId = prefs.getString(PROPERTY_REG_ID, "");
   if (registrationId.isEmpty()) {
       Log.d(TAG, "Registration ID not found.");
       return "";
   }
   int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
   int currentVersion = getAppVersion(context);
   if (registeredVersion != currentVersion) {
        Log.d(TAG, "App version changed.");
        return "";
    }
    return registrationId;
}

private SharedPreferences getGCMPreferences(Context context) 
{
    return getSharedPreferences(LaunchActivity.class.getSimpleName(),
                Context.MODE_PRIVATE);
}

private static int getAppVersion(Context context) 
{
     try 
     {
         PackageInfo packageInfo = context.getPackageManager()
                    .getPackageInfo(context.getPackageName(), 0);
            return packageInfo.versionCode;
      } 
      catch (NameNotFoundException e) 
      {
            throw new RuntimeException("Could not get package name: " + e);
      }
}


private void registerInBackground() 
{     new AsyncTask() {
     Override
     protected Object doInBackground(Object... params) 
     {
          String msg = "";
          try 
          {
               if (gcm == null) 
               {
                        gcm = GoogleCloudMessaging.getInstance(context);
               }
               regid = gcm.register(SENDER_ID);               Log.d(TAG, "########################################");
               Log.d(TAG, "Current Device's Registration ID is: "+msg);     
          } 
          catch (IOException ex) 
          {
              msg = "Error :" + ex.getMessage();
          }
          return null;
     }     protected void onPostExecute(Object result) 
     { //to do here };
  }.execute(null, null, null);
}

Nota : guarde REGISTRATION_KEY, es importante para enviar un mensaje PN al GCM, también tenga en cuenta que será único para todos los dispositivos, al usar esto solo GCM enviará una notificación push.

Recibir notificaciones push

Agregar clase de receptor de difusión de GCM

Como ya hemos declarado "GcmBroadcastReceiver.java" en nuestro archivo de manifiesto, creemos este código de clase de receptor de actualización de clase de esta manera

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) 
    {        ComponentName comp = new ComponentName(context.getPackageName(),
                GcmIntentService.class.getName());        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
        Toast.makeText(context, wow!! received new push notification", Toast.LENGTH_LONG).show();
    }
}

Agregar clase de servicio GCM

Como ya hemos declarado "GcmBroadcastReceiver.java" en nuestro archivo de manifiesto, creemos este código de clase de receptor de actualización de clase de esta manera

public class GcmIntentService extends IntentService
{     public static final int NOTIFICATION_ID = 1;     private NotificationManager mNotificationManager;     private final static String TAG = "GcmIntentService";     public GcmIntentService() {
     super("GcmIntentService");     
     }     @Override
     protected void onHandleIntent(Intent intent) {
          Bundle extras = intent.getExtras();
          Log.d(TAG, "Notification Data Json :" + extras.getString("message"));

          GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
          String messageType = gcm.getMessageType(intent);          if (!extras.isEmpty()) {          if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
               .equals(messageType)) {
               sendNotification("Send error: " + extras.toString());
          } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
          .equals(messageType)) {
          sendNotification("Deleted messages on server: "
          + extras.toString());          // If it's a regular GCM message, do some work.
          } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
          .equals(messageType)) {
          // This loop represents the service doing some work.
          for (int i = 0; i < 5; i++) {
               Log.d(TAG," Working... " + (i + 1) + "/5 @ "
               + SystemClock.elapsedRealtime());               try {
                    Thread.sleep(5000);
               } catch (InterruptedException e) {
               }
             }
             Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());
             sendNotification(extras.getString("message"));
           }
        }        // Release the wake lock provided by the WakefulBroadcastReceiver.
        GcmBroadcastReceiver.completeWakefulIntent(intent);
     }     // Put the message into a notification and post it.
     // This is just one simple example of what you might choose to do with
     // a GCM message.
     private void sendNotification(String msg) {          mNotificationManager = (NotificationManager) this
          .getSystemService(Context.NOTIFICATION_SERVICE);
          PendingIntent contentIntent = PendingIntent.getActivity(this, 0,          new Intent(this, LaunchActivity.class), 0);

          NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(          this)
          .setSmallIcon(R.drawable.icon)
          .setContentTitle("Ocutag Snap")
          .setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
          .setContentText(msg)
          .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE);

          mBuilder.setContentIntent(contentIntent);          mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
     }
}
swiftBoy
fuente
@Rohit verificaste el enlace que tiene un tutorial completo. También por favor hágame saber lo que falta. Actualizaré la respuesta.
swiftBoy
11

Hay un nuevo esfuerzo de código abierto para desarrollar una biblioteca Java para notificaciones push en Android basada en el servidor web Meteor. Puede consultarlo en el Blog del Proyecto Deacon , donde encontrará enlaces a Meteor y al repositorio GitHub del proyecto. Necesitamos desarrolladores, así que ¡corra la voz!

mtbkrdave
fuente
9

Puede usar Xtify ( http://developer.xtify.com ): tienen un servicio web de notificaciones push que funciona con su SDK. es gratis y hasta ahora me ha funcionado muy bien.

Peter
fuente
3
Recibí una respuesta de su vicepresidente diciendo que no hay planes de cobrar por el servicio push. Es un SDK bastante sorprendente.
Crowe T. Robot
8

o....

3) Mantenga una conexión con el servidor, envíe mensajes de mantenimiento cada pocos minutos y el servidor puede enviar mensajes instantáneamente. Así es como funciona Gmail, Google Talk, etc.

Isaac Waller
fuente
55
Creo que esto, lamentablemente, producirá una gran cantidad de batería descargada. SI toma esta ruta, asegúrese de limitar la cantidad de tiempo que hace esto.
haseman
No, en realidad no lo hará, porque las conexiones TCP / IP inactivas casi no consumen energía en el módem celular.
Isaac Waller
En realidad, tomará mucho tiempo, así que tienes razón. Enviar mensajes de mantenimiento con intervalos largos también ayuda mucho.
Isaac Waller
¿Qué son los "intervalos largos" a este respecto? Sé que Gmail Push funciona así, pero no sé qué intervalos de tiempo de espera usan.
tobsen
Encontré esta imagen sobre el rendimiento de la batería Pull vs Push: labs.ericsson.com/files/battery.jpg La tomé de la API de Ericsson Push aquí: labs.ericsson.com/apis/mobile-java-push/documentation
Menda
6

Recomiendo usar GCM - Google Cloud Messaging para Android Es gratis, y para usos simples debería ser muy fácil.

Sin embargo, requiere mantener un tercer servidor lateral para enviar las notificaciones en su nombre. Si desea evitar que haya algunas soluciones industriales muy buenas para el servicio de notificaciones push de Android:

  • Dirigible urbano : hasta 1 millón de notificaciones gratuitas por mes, luego se le cobrará por cada 1000 notificaciones
  • PushApps : gratis por 1 millón de notificaciones por mes y notificaciones ilimitadas por 19.99 por mes
  • PushWoosh - gratis para dispositivos 1M, los planes premium son de 39 EURO

Diclaimer : trabajo en PushApps y también uso su producto en mis aplicaciones desde hace más de un año.

Orr
fuente
6

A partir del 18/05/2016 Firebase es la plataforma unificada de Google para desarrolladores móviles que incluye notificaciones push.

Freek Nortier
fuente
4

Me temo que has encontrado ambos métodos posibles. Google, al menos inicialmente, iba a implementar una API GChat que podría usar para una implementación push / pull. Lamentablemente, esa biblioteca fue cortada por Android 1.0.

haseman
fuente
1
Prometieron recuperarlo una vez que se resuelvan los problemas de seguridad ... si eso sucede.
Jeremy Logan
3

No sé si esto sigue siendo útil. Logré algo como esto con una biblioteca de Java en http://www.pushlets.com/

Si lo hace en un servicio, no evitará que Android lo cierre y mate el hilo del oyente.

n3utrino
fuente
2

C2DM: los usuarios de su aplicación deben tener la cuenta de gmail.

MQTT: cuando su conexión llegó a 1024, dejará de funcionar porque usó "seleccionar modelo" de Linux.

Hay un servicio gratuito de inserción y una API para Android, puedes probarlo: http://push-notification.org

Jacky
fuente
2

Método gratuito y fácil:

Si su base de usuarios objetivo no es grande (menos de 1000) y desea comenzar con un servicio gratuito, Airbop es el mejor y más conveniente.

Sitio web de Airbop Utiliza el servicio Google Cloud Messaging a través de su API y ofrece un buen rendimiento. Lo he usado para dos de mis proyectos y fue fácil implementarlo.

Los servicios como Urbanship son excelentes, pero proporcionan una pila completa de implementación y no solo las notificaciones automáticas.

Si solo el servicio push es su objetivo, Airbop funcionará bien.

No he usado Pushwoosh , pero también es una gran opción. Permite empujar hasta 1,000,000 de dispositivos gratis

adimoh
fuente
1

Sugeriría usar ambos SMS y HTTP. Si el usuario no ha iniciado sesión, envíe un SMS a su teléfono para notificarle que hay un mensaje esperando.

Así es como funciona este servicio de Ericsson Labs: https://labs.ericsson.com/apis/mobile-java-push/

Si implementa esto usted mismo, la parte difícil es eliminar el SMS entrante sin que el usuario lo vea. O tal vez está bien si lo ven en su caso.

Parece que esto funciona: Eliminar SMS usando BroadCastReceiver - Android

Sí, escribir código como este puede ser peligroso y potencialmente puede arruinar la vida de alguien porque su aplicación eliminó un SMS que no debería.

Sarel Botha
fuente
1
jajaja: "Sí, escribir código como este puede ser peligroso y potencialmente puede arruinar la vida de alguien porque su aplicación eliminó un SMS que no debería". Votar por eso. jajaja
Kumar Ravi
El enlace a Mobile Java Push está inactivo y el servicio en sí parece estar en desuso.
naXa
1

Puede usar Google Cloud Messaging o GCM , es gratis y fácil de usar. También puede usar servidores push de terceros como PushWoosh, que le brinda más flexibilidad

Mohsen Afshin
fuente
1

Hay muchos servidores de terceros como Urban Airship , Xtify, Mainline , ... lo que permite enviar no solo en Android, sino también en iOs, Windows Phone ...

Panchine Lac
fuente
1

Firebase Cloud Messaging (FCM) es la nueva versión de GCM. FCM es una solución de mensajería multiplataforma que le permite enviar mensajes de forma segura y gratuita. Hereda la infraestructura central de GCM para entregar mensajes de manera confiable en Android, iOS, Web (javascript), Unity y C ++.

A partir del 10 de abril de 2018, Google ha desaprobado GCM. El servidor GCM y las API del cliente están en desuso y se eliminarán el 11 de abril de 2019. Google recomienda migrar las aplicaciones GCM a Firebase Cloud Messaging (FCM), que hereda la infraestructura GCM confiable y escalable.

Recurso

Fahed Hermoza
fuente
0

Puedes usar Pusher

Es un servicio alojado que hace que sea muy fácil agregar datos y funcionalidades en tiempo real a aplicaciones web y móviles.
Pusher ofrece bibliotecas para integrarse en todos los principales tiempos de ejecución y marcos.

PHP, Ruby, Python, Java, .NET, Go and Nodeen el servidor
JavaScript, Objective-C (iOS) and Java (Android)en el cliente.

Arash Hatami
fuente