Firebase (FCM) como obter token

92

É a primeira vez que uso o FCM.

Baixei uma amostra de firebase / quickstart-android e instalo o FCM Quickstart. Mas não consigo obter nenhum token do registro, mesmo clicando no botão LOG TOKEN no aplicativo.

Em seguida, tento enviar uma mensagem com o console do Firebase e definir como destino o nome do pacote do meu aplicativo. Recebi mensagens.

Eu quero saber se o FCM pode ser usado? GCM está tudo bem.

Solução:

Porque eu não sou um desenvolvedor Android, apenas um desenvolvedor back-end. Então, demoro um pouco para resolver. Na minha opinião, existem alguns bugs no aplicativo de amostra.

insira a descrição da imagem aqui

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.
    }
}

Adicione isso no MainActivity.java.

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

Após fazer acima, você obtém o Token no Logcat. Mas, finalmente, encontro uma maneira conveniente de conseguir. Basta usar o modo de depuração para instalar o aplicativo de amostra e você pode obter o token quando instalá-lo pela primeira vez.

Mas não sei por que não consegue imprimir o log quando o instalo. Talvez esteja relacionado ao sistema móvel.

E então por que não consigo obter a notificação. FirebaseMessagingService.onMessageReceived não chamou sendNotification

wyx
fonte
se o log for atingido, ele mostrará o token com ele no aplicativo de amostra
Shubhank
Não, o aplicativo de amostra dizia .Só mostrará o token no logcat se eu clicar no botão. Mas não encontro nada no logcat. @ Shubhank
wyx
descomente estas linhas String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav

Respostas:

120

MAIS RÁPIDO E BOM PARA PROTÓTIPO

A solução rápida é armazená-lo em sharedPrefs e adicionar essa lógica ao onCreatemétodo em sua MainActivity ou classe que está estendendo 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 :("));

MANEIRA MAIS LIMPA

A melhor opção é criar um serviço e manter dentro de uma lógica semelhante. Em primeiro lugar, crie um novo serviço

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");
    }
}

Em seguida, adicione-o ao arquivo AndroidManifest

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

Por fim, você pode usar um método estático de seu serviço MyFirebaseMessagingService.getToken(Context);

O MAIS RÁPIDO MAS REMOVIDO

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

Ele ainda funciona quando você usa uma biblioteca do Firebase mais antiga que a versão 17.xx

Eliasz Kubala
fonte
6
Mas a segunda abordagem só funciona até que as preferências compartilhadas sejam apagadas. E se os dados do aplicativo forem apagados e o valor da string for perdido? O Android não chama "onNewtoken ()", pois não há um novo token. Mas então como solicitamos o token? Em todos os lugares está escrito "apenas use onNewToken ()", mas esse método só é executado quando há um novo token. Digamos que esse método já tenha sido executado, mas não nos preocupamos em armazenar o token. Mais tarde, fazemos uma verificação e vemos que o token não está definido, e então? Como faço para acionar o FCM para me dizer o token novamente?
JeneralJames de
1
Você pode usar em FirebaseInstanceId.getInstance().getInstanceId()vez de FirebaseInstanceId.getInstance().getToken(), veja esta resposta
Vadim Kotov
24

Informação importante.

se o serviço google play travou ou não está funcionando, então fcm return token = null

Se o serviço de reprodução estiver funcionando corretamente, o FirebaseInstanceId.getInstance().getToken()método retornatoken

Log.d("FCMToken", "token "+ FirebaseInstanceId.getInstance().getToken());
Yogesh Rathi
fonte
Sim, mas isso acontece com frequência
Hoang Duc Tuan
O token é armazenado em cache (provavelmente in-mem) após ter sido obtido uma vez. Portanto, isso significa que você precisa buscá-lo uma vez ou fazer com que o Firebase emita novamente outro token para você de alguma forma. Veja aqui como buscar manualmente stackoverflow.com/a/51630819/2102748
milosmns
20

A equipe por trás do Firebase Android SDK muda um pouco a API. Implementei a lógica "Token para servidor" assim:

Em minha instância de FirebaseMessagingService:

public class FirebaseCloudMessagingService extends FirebaseMessagingService {

    ...

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

    ...

}

Lembre-se de que o token é por dispositivo e pode ser atualizado pelo Firebase, independentemente da sua lógica de login. Portanto, se você tiver a funcionalidade Login e Logout, deverá considerar casos extras:

  1. Quando um novo usuário efetua login, você precisa vincular o token ao novo usuário (enviá-lo ao servidor). Porque o token pode ser atualizado durante a sessão do usuário antigo e o servidor não conhece o token do novo usuário.
  2. Quando o usuário efetua logout, você precisa desvincular o token. Porque o usuário não deve mais receber notificações / mensagens.

Usando a nova API, você pode obter token como este:

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

Boa sorte!

rzaaeeff
fonte
Tentar obter o valor fora de OnSuccess está dando null.
DragonFire
A funcionalidade de login / logout não tem nada a ver com mensagens push, este é um caso de uso de negócios específico. Por exemplo, você pode desejar direcionar usuários desconectados com algumas notificações de marketing / promoção para que eles se conectem novamente ao aplicativo; nesse caso, você precisará do token FCM. Mas a resposta está correta em termos de obtenção do token.
milosmns 01 de
@milosmns, você está certo em termos de notificações de marketing / promoção. Ainda assim, é necessário indicar o status do token. A solução simples seria armazenar os tokens não acoplados em algum tipo de tabela de histórico e, em seguida, usar esses tokens anteriores para encorajar o uso de login novamente.
rzaaeeff
Hm, não tenho certeza de quanto tempo você pode reutilizar o mesmo token e quando exatamente ele é invalidado. Vale a pena investigar isso, pois acho que você precisa limpar essa tabela de histórico / cache / persistência quando os tokens se tornarem inválidos.
Milosmns
@milosmns, em Firebaseland, os tokens não expiram, mas são renovados. Quando você aciona qualquer atividade relacionada ao token com a API FCM, o token fornecido é validado. Se o token for inválido, você receberá o erro: MissingRegistration ou erro: InvalidRegistration. Você pode encontrar mais códigos de erro aqui: firebase.google.com/docs/cloud-messaging/...
rzaaeeff
13

De acordo com o doc

Migrar um aplicativo cliente GCM para o FCM

onTokenRefresh()

Chamado apenas se o token InstanceID for atualizado

Portanto, ele chamará apenas na primeira vez quando você instalar um aplicativo em seu dispositivo.

Portanto, sugiro que desinstale seu aplicativo manualmente e tente executá-lo novamente

definitivamente você receberá TOKEN

Gaurav
fonte
2
não reinstalar, desinstale -o manualmente e execute o projeto,
Gaurav
descomente estas linhas String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav
1
@Gaurav, Como posso obter o token após o segundo login? onTokenRefreshnão chamando cada login. como posso obter o token na minha tela de login?
delavega66
3
@ de_la_vega_66, Você deve armazenar seu token no primeiro login
Gaurav
Seu serviço que estende FirebaseInstanceIdService e tem o método de retorno de chamada onTokenRefresh () DEVE ser registrado no arquivo Manifest: <service android: name = "com.mypackage.name.MyInstanceIdService" android: export = "true"> <intent-filter> <action android: name = "com.google.firebase.INSTANCE_ID_EVENT" /> </intent-filter> </service>
Kirill Karmazin
9

Experimente isso. Por que você está usando RegistrationIntentService?

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

    private void registerToken(String token) {

    }
}
FireUser
fonte
8

Essa linha deve fornecer a você o token Firebase FCM.

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

Faça Log.d para imprimi-lo no monitor do Android.

Alphonsus Chen
fonte
Ele retorna nulo
Kishan Solanki
7

Em vez disso:

    // [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]

Faça isso:

    // [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]

E mais uma coisa:

Você precisa chamar o sendRegistrationToServer()método que atualizará o token no servidor, se estiver enviando notificações push do servidor.

ATUALIZAR:

Um novo token do Firebase é gerado ( onTokenRefresh()é chamado) quando:

  • O aplicativo exclui o ID da instância
  • O aplicativo é restaurado em um novo dispositivo
  • O usuário desinstala / reinstala o aplicativo
  • O usuário limpa os dados do aplicativo.
ativos desde 93
fonte
Tive que excluir o ID da instância FirebaseInstanceId.getInstance (). DeleteInstanceId (), mas recebi um ERRO DE SERVIÇO,
Hardik9850
2
Você precisa executar FirebaseInstanceId.getInstance().deleteInstanceId()em outro Thread
rockar06
5

Ao mesmo tempo, não se esqueça de incluir isso em seu arquivo de manifesto para receber a id do token

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

Em firebase-messaging:17.1.0e mais recentes o FirebaseInstanceIdService está obsoleto, você pode obter o onNewTokenna FirebaseMessagingServiceclasse conforme explicado em https://stackoverflow.com/a/51475096/1351469

Mas se você quiser apenas obter o token a qualquer momento, agora você pode fazer assim:

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( this.getActivity(),  new OnSuccessListener<InstanceIdResult>() {
  @Override
  public void onSuccess(InstanceIdResult instanceIdResult) {
    String newToken = instanceIdResult.getToken();
    Log.e("newToken",newToken);
  }
});
jcesarmobile
fonte
Isso pode ser retornado, para que a mesma função possa ser usada em muitos lugares ou temos que copiar e colar devido à natureza assíncrona do firebase
DragonFire
4

O método getToken()está obsoleto. Você pode usar em seu getInstanceId()lugar.

Se você deseja manipular os resultados ao 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()));
sNash
fonte
3

Se estiver usando alguma função de autenticação do firebase, você pode pegar o token usando este:

//------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 bem se o usuário estiver logado. getCurrentUser ()

Diego venâncio
fonte
2

tente isso

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

para aqueles que pousam aqui, até agora FirebaseInstanceIdServiceestá obsoleto, use:

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);
    }
}

e declarar no AndroidManifest

<application... >

<service android:name=".fcm.MyFirebaseMessagingService">
    <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>
</application>
user1908375
fonte
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();

            }
        });
pruthwiraj.kadam
fonte
-1

Você pode usar o seguinte no Firebase (FCM) para obter o token:

FirebaseInstanceId.getInstance().getToken();
Ahmed Sayed
fonte
2
O método getToken () está obsoleto! A melhor resposta, agora, é de @rzaaeeff.
Damiii
-9
Settings.Secure.getString(getContentResolver(),
                     Settings.Secure.ANDROID_ID);
Saurabh G.
fonte
Esse código é para obter o ID do Android do dispositivo, não o token firebase.
Syed Afeef