Solución:
Bueno. Así que logré hacer algunas pruebas y concluí lo siguiente:
-
deleteToken()
es la contraparte degetToken(String, String)
, pero no paragetToken()
.
Solo funciona si la ID de remitente que está pasando es una ID de remitente diferente (no la misma ID que se puede ver en su google-services.json). Por ejemplo, si desea permitir que un servidor diferente envíe a su aplicación, llame getToken("THEIR_SENDER_ID", "FCM")
para darles autorización para enviar a su aplicación. Esto devolverá un token de registro diferente que corresponde solo a ese remitente específico.
En el futuro, si decide eliminar su autorización para enviarlo a su aplicación, deberá utilizar deleteToken("THEIR_SENDER_ID", "FCM")
. Esto invalidará el token correspondiente, y cuando el Remitente intente enviar un mensaje, como el comportamiento previsto, recibirá un NotRegistered
error.
- Para eliminar el token de su propio remitente, el manejo correcto es usar
deleteInstanceId()
.
Mención especial esta respuesta de @Prince, específicamente el ejemplo de código para ayudarme con esto.
Como ya hace @ MichałK en su publicación, después de llamar al deleteInstanceId()
, getToken()
debe llamarse para enviar una solicitud de un nuevo token. Sin embargo, no tiene que llamarlo la segunda vez. Siempre y cuando onTokenRefresh()
onNewToken()
está implementado, debería activarse automáticamente proporcionándole el nuevo token.
Para abreviar, deleteInstanceId()
> getToken()
> comprobar onTokenRefresh()
onNewToken()
.
Nota: Llamando deleteInstanceId()
no solo eliminará el token de su propia aplicación. Eliminará todas las suscripciones a temas y todos los demás tokens asociados con la instancia de la aplicación.
¿Estás seguro de que estás llamando? deleteToken()
¿adecuadamente? El valor para la audiencia debe ser (también visto en mi respuesta que vinculó) es “establecido en el ID de remitente del servidor de aplicaciones”. Estas pasando el getId()
valor que no es el mismo que el ID del remitente (contiene el valor del ID de la instancia de la aplicación). Además, ¿cómo envía el mensaje (servidor de aplicaciones o consola de notificaciones)?
getToken()
y getToken(String, String)
devuelve diferentes tokens. Vea mi respuesta aquí.
Yo tambien probé
FirebaseInstanceId.getInstance().deleteInstanceId()
, pero luego la próxima vez que llameFirebaseInstanceId.getInstance.getToken
Recibo nulo (funciona en el segundo intento).
Probablemente sea porque la primera vez que llamas al getToken()
, todavía se está generando. Es solo el comportamiento previsto.
Supongo que despues
deleteInstanceId
Podría llamar de inmediatogetToken()
de nuevo, pero parece un truco.
Realmente no. Así es como obtendrá el nuevo token generado (siempre que ya esté generado). Entonces creo que está bien.
Hice una breve investigación sobre cuál sería la solución más elegante para recuperar el control total (suscribirse y cancelar la suscripción a FCM) como antes. Habilite y deshabilite el FCM después de que el usuario inicie o cierre sesión.
Paso 1. – Evitar la inicialización automática
Firebase ahora maneja el InstanceID
y todo lo demás que necesite generar un token de registro. Primero que nada necesitas prevenir inicialización automática. Según la documentación de configuración oficial, debe agregar estos metadatos valores a tu AndroidManifest.xml
:
<?xml version="1.0" encoding="utf-8"?>
<application>
<!-- FCM: Disable auto-init -->
<meta-data android:name="firebase_messaging_auto_init_enabled"
android:value="false" />
<meta-data android:name="firebase_analytics_collection_enabled"
android:value="false" />
<!-- FCM: Receive token and messages -->
<service android:name=".FCMService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
</application>
Ahora desactivó el proceso automático de solicitud de token. Al mismo tiempo, tiene la opción de habilitarlo nuevamente en tiempo de ejecución por código.
Paso 2. – Implementar enableFCM()
y disableFCM()
funciones
Si habilita la inicialización automática nuevamente, recibió un nuevo token de inmediato, por lo que esta es una manera perfecta de implementar el enableFCM()
método. Toda la información de suscripción asignada a InstanceID, por lo que cuando la elimine, inicie la cancelación de la suscripción de todos los temas. De esta manera podrá implementar disableFCM()
método, simplemente desactive el inicio automático antes de eliminarlo.
public class FCMHandler {
public void enableFCM(){
// Enable FCM via enable Auto-init service which generate new token and receive in FCMService
FirebaseMessaging.getInstance().setAutoInitEnabled(true);
}
public void disableFCM(){
// Disable auto init
FirebaseMessaging.getInstance().setAutoInitEnabled(false);
new Thread(() -> {
try {
// Remove InstanceID initiate to unsubscribe all topic
// TODO: May be a better way to use FirebaseMessaging.getInstance().unsubscribeFromTopic()
FirebaseInstanceId.getInstance().deleteInstanceId();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
Paso 3. – FCMService
implementación: recepción de tokens y mensajes
En el último paso, debe recibir el nuevo token y enviarlo directamente a su servidor. Por otro lado, recibirá su mensaje de datos y simplemente lo hará lo que quiera.
public class FCMService extends FirebaseMessagingService {
@Override
public void onNewToken(String token) {
super.onNewToken(token);
// TODO: send your new token to the server
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String from = remoteMessage.getFrom();
Map data = remoteMessage.getData();
if (data != null) {
// TODO: handle your message and data
sendMessageNotification(message, messageId);
}
}
private void sendMessageNotification(String msg, long messageId) {
// TODO: show notification using NotificationCompat
}
}
Creo que esta solución es clara, sencilla y transparente. Probé en un entorno de producción y funciona. Espero que haya sido de ayuda.
Estaba trabajando en el mismo problema, cuando terminé mi logout()
de mi aplicación. Pero el problema fue que después de cerrar la sesión, todavía recibía notificaciones automáticas de Firebase. lo intenté eliminar el token de Firebase. Pero después de eliminar el token en mi logout()
método, es null
cuando lo consulto en mi login()
método. Después de trabajar 2 días finalmente obtuve una solución.
-
En tus
logout()
método, elimine el token de Firebase en segundo plano porque no puede eliminar el token de Firebase del hilo principalnew AsyncTask<Void,Void,Void>() { @Override protected Void doInBackground(Void... params) { try { FirebaseInstanceId.getInstance().deleteInstanceId(); } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void result) { // Call your Activity where you want to land after log out } }.execute();
-
En tus
login()
, vuelva a generar el token de Firebase.new AsyncTask<Void,Void,Void>() { @Override protected Void doInBackground(Void... params) { String token = FirebaseInstanceId.getInstance().getToken(); // Used to get firebase token until its null so it will save you from null pointer exeption while(token == null) { token = FirebaseInstanceId.getInstance().getToken(); } return null; } @Override protected void onPostExecute(Void result) { } }.execute();