Firebase (FCM) cómo obtener token


97

Es la primera vez que uso FCM.

Descargo una muestra de firebase / quickstart-android e instalo FCM Quickstart. Pero no puedo obtener ningún token del registro ni siquiera presionar el botón LOG TOKEN en la aplicación.

Luego intento enviar un mensaje con la consola de Firebase y configurarlo para apuntar al nombre del paquete de mi aplicación. Recibí mensajes entrantes.

Quiero saber si se puede usar FCM? GCM todo está bien.

Solución:

Porque no soy un desarrollador de Android, solo un desarrollador de backend. Entonces me toma algo de tiempo resolverlo. En mi opinión, hay algunos errores en la aplicación de muestra.

ingrese la descripción de la imagen aquí

Código:

RegistrationIntentService.java

public class RegistrationIntentService extends IntentService {

    private static final String TAG = "RegIntentService";


    public RegistrationIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        String token = FirebaseInstanceId.getInstance().getToken();
        Log.i(TAG, "FCM Registration Token: " + token);
    }
}

MyFirebaseInstanceIDService.java

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {

    private static final String TAG = "MyFirebaseIIDService";

    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the InstanceID token
     * is initially generated so this is where you would retrieve the token.
     */
    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
//        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
//        Log.d(TAG, "Refreshed token: " + refreshedToken);
//
//        // TODO: Implement this method to send any registration to your app's servers.
//        sendRegistrationToServer(refreshedToken);
//
        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
    }
    // [END refresh_token]

    /**
     * Persist token to third-party servers.
     * <p>
     * Modify this method to associate the user's FCM InstanceID token with any server-side account
     * maintained by your application.
     *
     * @param token The new token.
     */
    private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.
    }
}

Agregue esto en MainActivity.java.

 Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);

Después de hacer lo anterior, obtienes el Token en Logcat. Pero finalmente, encuentro una forma conveniente de conseguirlo. Simplemente use el modo de depuración para instalar la aplicación de muestra y podrá obtener el token la primera vez que lo instale.

Pero no sé por qué no puede imprimir el registro cuando lo instalo. Quizás esté relacionado con el sistema móvil.

Y luego por qué no puedo obtener la notificación. FirebaseMessagingService.onMessageReceived no llamó a sendNotification


si se golpea el registro, mostraría el token con él en la aplicación de muestra
Shubhank

No, la aplicación de muestra decía. Solo mostrará el token en logcat si presiono el botón. Pero no encuentro nada en logcat. @ Shubhank
wyx

descomentar estas líneas String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav

Respuestas:


129

MÁS RÁPIDO Y BUENO PARA PROTOTIPOS

La solución rápida es almacenarlo en sharedPrefs y agregar esta lógica al onCreatemétodo en su MainActivity o clase que está extendiendo Application.

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(this, instanceIdResult -> {
    String newToken = instanceIdResult.getToken();
    Log.e("newToken", newToken);
    getActivity().getPreferences(Context.MODE_PRIVATE).edit().putString("fb", newToken).apply();
});

Log.d("newToken", getActivity().getPreferences(Context.MODE_PRIVATE).getString("fb", "empty :("));

MANERA MÁS LIMPIA

Una mejor opción es crear un servicio y mantener una lógica similar. En primer lugar, cree un nuevo servicio

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public void onNewToken(String s) {
        super.onNewToken(s);
        Log.e("newToken", s);
        getSharedPreferences("_", MODE_PRIVATE).edit().putString("fb", s).apply();
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
    }

    public static String getToken(Context context) {
        return context.getSharedPreferences("_", MODE_PRIVATE).getString("fb", "empty");
    }
}

Y luego agréguelo al archivo AndroidManifest

<service
        android:name=".MyFirebaseMessagingService"
        android:stopWithTask="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
</service>

Finalmente, puede utilizar un método estático de su Servicio MyFirebaseMessagingService.getToken(Context);

EL MÁS RÁPIDO PERO DESPRECIADO

Log.d("Firebase", "token "+ FirebaseInstanceId.getInstance().getToken());

Todavía funciona cuando usa una biblioteca de base de fuego más antigua que la versión 17.xx


6
Pero el segundo enfoque solo funciona hasta que se borran las preferencias compartidas. ¿Qué pasa si se borran los datos de la aplicación y se pierde ese valor de cadena? Android no llama a "onNewtoken ()" ya que no hay ningún token nuevo . Pero entonces, ¿cómo solicitamos el token? En todas partes dice "solo use onNewToken ()" pero ese método solo se ejecuta cuando hay un nuevo token. Digamos que ese método ya se ha ejecutado, pero no nos molestamos en almacenar el token. Posteriormente realizamos una comprobación y vemos que el token no está configurado, ¿entonces qué? ¿Cómo hago que FCM me diga el token nuevamente?
JeneralJames


1
Puede usar en FirebaseInstanceId.getInstance().getInstanceId()lugar de FirebaseInstanceId.getInstance().getToken(), vea esta respuesta
Vadim Kotov

@JeneralJames si un usuario borra los datos de la aplicación, onNewTokensiempre se activará, de la documentación aquí firebase.google.com/docs/cloud-messaging/android/…
sarah

26

El equipo detrás de Firebase Android SDK cambió un poco la API. Implementé la lógica "Token to Server" como esta:

En mi instancia de FirebaseMessagingService:

public class FirebaseCloudMessagingService extends FirebaseMessagingService {

    ...

    @Override
    public void onNewToken(String token) {
        // sending token to server here
    }

    ...

}

Tenga en cuenta que el token es por dispositivo y Firebase puede actualizarlo independientemente de su lógica de inicio de sesión. Por lo tanto, si tiene la función de inicio de sesión y cierre de sesión, debe considerar casos adicionales:

  1. Cuando un nuevo usuario inicia sesión, debe vincular el token al nuevo usuario (enviarlo al servidor). Debido a que el token puede actualizarse durante la sesión del usuario anterior y el servidor no conoce el token del nuevo usuario.
  2. Cuando el usuario cierra la sesión, debe desvincular el token. Porque el usuario ya no debería recibir notificaciones / mensajes.

Usando la nueva API, puede obtener un token como este:

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
        @Override
        public void onSuccess(InstanceIdResult instanceIdResult) {
            String token = instanceIdResult.getToken();
            // send it to server
        }
    });

¡Buena suerte!


Intentar obtener el valor fuera de OnSuccess es nulo.
DragonFire

La funcionalidad de inicio de sesión / cierre de sesión no tiene nada que ver con los mensajes Push, este es un caso de uso comercial específico. Por ejemplo, es posible que desee dirigirse a los usuarios desconectados con algunas notificaciones de marketing / promoción para que vuelvan a iniciar sesión en la aplicación, en cuyo caso necesitará el token de FCM. Pero la respuesta es correcta en términos de obtener el token.
milosmns

@milosmns, tiene razón en términos de notificaciones de marketing / promociones. Aún así, existe la necesidad de una indicación del estado del token. La solución simple sería almacenar los tokens no vinculados en algún tipo de tabla de historial y luego usar esos tokens anteriores para alentar al
usuario

Hm, no estoy seguro de cuánto tiempo puede reutilizar el mismo token y cuándo exactamente se invalida. Vale la pena investigar esto, ya que supongo que deberá borrar esta tabla de historial / caché / persistencia una vez que los tokens se vuelvan inválidos.
milosmns

@milosmns, en Firebaseland, los tokens no caducan sino que se renuevan. Cuando activa cualquier actividad relacionada con el token con la API de FCM, se valida el token proporcionado. Si el token no es válido, recibirá el error: MissingRegistration o error: InvalidRegistration. Puede encontrar más códigos de error aquí: firebase.google.com/docs/cloud-messaging/…
rzaaeeff

24

Información importante.

Si el servicio de Google Play se bloquea o no se ejecuta, entonces fcm return token = null

Si el servicio de reproducción funciona correctamente, el FirebaseInstanceId.getInstance().getToken()método vuelvetoken

Log.d("FCMToken", "token "+ FirebaseInstanceId.getInstance().getToken());

Sí, pero esto sucede muy a menudo
Hoang Duc Tuan

El token se almacena en caché (probablemente en memoria) después de que se haya obtenido una vez. Entonces, esto significa que debe buscarlo una vez o hacer que Firebase vuelva a emitir otro token de alguna manera. Vea aquí cómo buscar manualmente stackoverflow.com/a/51630819/2102748
milosmns

13

Según doc

Migrar una aplicación cliente de GCM a FCM

onTokenRefresh()

solo se llama si se actualiza el token InstanceID

Por lo tanto, solo llamará la primera vez que instale una aplicación en su dispositivo.

Así que le sugiero que desinstale su aplicación manualmente e intente ejecutarla nuevamente.

definitivamente obtendrás TOKEN


2
no reinstalar, desinstalarlo manualmente y luego ejecutar el proyecto,
Gaurav

descomentar estas líneas String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav

1
@Gaurav, ¿cómo puedo obtener un token después de un segundo inicio de sesión? onTokenRefreshno llamando a cada inicio de sesión. ¿Cómo puedo obtener un token en mi pantalla de inicio de sesión?
delavega66

3
@ de_la_vega_66, debes almacenar tu token en el primer inicio de sesión
Gaurav

Su Servicio que extiende FirebaseInstanceIdService y tiene el método de devolución de llamada onTokenRefresh () DEBE estar registrado en el archivo Manifest: <service android: name = "com.mypackage.name.MyInstanceIdService" android: exported = "true"> <intent-filter> <action android: name = "com.google.firebase.INSTANCE_ID_EVENT" /> </intent-filter> </service>
Kirill Karmazin

9

Prueba esto. ¿Por qué estás usando RegistrationIntentService?

public class FirebaseInstanceIDService extends FirebaseInstanceIdService {    
    @Override
    public void onTokenRefresh() {    
        String token = FirebaseInstanceId.getInstance().getToken();    
        registerToken(token);
    }

    private void registerToken(String token) {

    }
}

8

Esta línea debería proporcionarle el token FCM de firebase.

String token = FirebaseInstanceId.getInstance().getToken();
Log.d("MYTAG", "This is your Firebase token" + token);

Haga Log.d para imprimirlo en el monitor de Android.


Devuelve nulo
Kishan Solanki

7

En lugar de esto:

    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
//        Get updated InstanceID token.
//        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
//        Log.d(TAG, "Refreshed token: " + refreshedToken);
//
//        TODO: Implement this method to send any registration to your app's servers.
//        sendRegistrationToServer(refreshedToken);
//
        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
    }
    // [END refresh_token]

Hacer esto:

    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
//        Log.d(TAG, "Refreshed token: " + refreshedToken);

        // Implement this method to send token to your app's server
       sendRegistrationToServer(refreshedToken);

    }
    // [END refresh_token]

Y una cosa más:

Debe llamar al sendRegistrationToServer()método que actualizará el token en el servidor, si está enviando notificaciones push desde el servidor.

ACTUALIZAR:

Se genera ( onTokenRefresh()se llama) un nuevo token de Firebase cuando:

  • La aplicación elimina el ID de instancia
  • La aplicación se restaura en un nuevo dispositivo
  • El usuario desinstala / reinstala la aplicación
  • El usuario borra los datos de la aplicación.

Tuve que eliminar Instance ID FirebaseInstanceId.getInstance (). DeleteInstanceId () pero obtuve un ERROR DE SERVICIO,
Hardik9850

2
Necesitas correr FirebaseInstanceId.getInstance().deleteInstanceId()en otro hilo
rockar06

6

Al mismo tiempo, no olvide incluir esto en su archivo de manifiesto para recibir la identificación del token

<service
    android:name=".MyFirebaseInstanceIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service>

5

El método getToken()está obsoleto. Puedes usargetInstanceId() en lugar.

Si desea manejar los resultados al solicitar instanceId(token), verifique este código.

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(instanceIdResult -> {
        if (instanceIdResult != null) {
            String token = instanceIdResult.getToken();
            if (!TextUtils.isEmpty(token)) {
                Log.d(TAG, "retrieve token successful : " + token);
            }
        } else{
            Log.w(TAG, "instanceIdResult should not be null..");
        }
    }).addOnFailureListener(e -> {
        //do something with e
    }).addOnCanceledListener(() -> {
        //request has canceled
    }).addOnCompleteListener(task -> Log.v(TAG, "task result : " + task.getResult().getToken()));

4

En firebase-messaging:17.1.0y en versiones más recientes, FirebaseInstanceIdService está obsoleto, puede obtener el onNewTokenon the FirebaseMessagingServiceclass como se explica en https://stackoverflow.com/a/51475096/1351469

Pero si solo desea obtener el token en cualquier momento, ahora puede hacerlo así:

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( this.getActivity(),  new OnSuccessListener<InstanceIdResult>() {
  @Override
  public void onSuccess(InstanceIdResult instanceIdResult) {
    String newToken = instanceIdResult.getToken();
    Log.e("newToken",newToken);
  }
});

¿Se puede devolver esto, por lo que la misma función se puede usar en muchos lugares o tenemos que copiar y pegar debido a la naturaleza asincrónica de firebase?
DragonFire

3

Si está usando alguna función de autenticación de firebase, puede tomar el token usando esto:

//------GET USER TOKEN-------
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getToken(true)
        .addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
            public void onComplete(@NonNull Task<GetTokenResult> task) {
                if (task.isSuccessful()) {
                    String idToken = task.getResult().getToken();
                      // ...
                }
            }
        });

Funciona bien si el usuario está registrado. getCurrentUser ()


2

prueba esto

FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener(OnSuccessListener<InstanceIdResult> { instanceIdResult ->
             fcm_token = instanceIdResult.token}

1

para aquellos que aterrizan aquí, hasta ahora FirebaseInstanceIdServiceestá en desuso, use en su lugar:

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    @Override
    public void onNewToken(String token) {
        Log.d("MY_TOKEN", "Refreshed token: " + token);

        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        // Instance ID token to your app server.
        // sendRegistrationToServer(token);
    }
}

y declarar en AndroidManifest

<application... >

<service android:name=".fcm.MyFirebaseMessagingService">
    <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>
</application>

1
FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
            @Override
            public void onComplete(@NonNull Task<InstanceIdResult> task) {
                if (!task.isSuccessful()) {
                    Log.w(TAG, "getInstanceId failed", task.getException());
                    return;
                }

                // Get new Instance ID token
                String **token** = task.getResult().getToken();

            }
        });

0

El FirebaseInstanceId.getInstance().getInstanceId()está en desuso . Según el documento de base de fuego , puede recuperar el token de registro actual con el siguiente código:

FirebaseMessaging.getInstance().getToken()
    .addOnCompleteListener(new OnCompleteListener<String>() {
        @Override
        public void onComplete(@NonNull Task<String> task) {
          if (!task.isSuccessful()) {
            Log.w(TAG, "Fetching FCM registration token failed", task.getException());
            return;
          }

          // Get new FCM registration token
          String token = task.getResult();

          // Log and toast
          String msg = getString(R.string.msg_token_fmt, token);
          Log.d(TAG, msg);
          Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
        }
    });

-1

Puede usar lo siguiente en Firebase (FCM) para obtener el token:

FirebaseInstanceId.getInstance().getToken();

2
¡El método getToken () está obsoleto! La mejor respuesta, ahora, es de @rzaaeeff.
Damiii

-9
Settings.Secure.getString(getContentResolver(),
                     Settings.Secure.ANDROID_ID);

Ese código es para obtener la ID de Android del dispositivo, no el token de base de fuego.
Syed Afeef
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.