Jak uzyskać token w Firebase (FCM)

97

Po raz pierwszy używam FCM.

Pobieram próbkę z firebase / quickstart-android i instaluję FCM Quickstart. Ale nie mogę pobrać żadnego tokena z dziennika, nawet naciskając przycisk LOG TOKEN w aplikacji.

Następnie próbuję wysłać wiadomość za pomocą konsoli Firebase i ustawiam docelową nazwę mojego pakietu aplikacji. Otrzymałem wiadomości.

Chcę wiedzieć, czy można używać FCM? GCM wszystko jest w porządku.

Rozwiązanie:

Ponieważ nie jestem programistą Androida, tylko programistą zaplecza. Więc rozwiązanie tego zajmuje mi trochę czasu. Moim zdaniem w przykładowej aplikacji jest kilka błędów.

wprowadź opis obrazu tutaj

Kod:

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

Dodaj to w pliku MainActivity.java.

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

Po wykonaniu powyższych , otrzymasz Token w Logcat. Ale w końcu znajduję wygodny sposób, aby to zdobyć. Po prostu użyj trybu debugowania, aby zainstalować przykładową aplikację, a token możesz uzyskać podczas pierwszej instalacji.

Ale nie wiem, dlaczego nie może wydrukować dziennika po zainstalowaniu. Może mieć związek z systemem mobilnym.

A potem dlaczego nie mogę otrzymać powiadomienia. FirebaseMessagingService.onMessageReceived nie wywołał sendNotification

wyx
źródło
jeśli dziennik zostanie trafiony, pokaże token z nim w przykładowej aplikacji
Shubhank
Nie, powiedziała przykładowa aplikacja, która wyświetli token w logcatie tylko wtedy, gdy naciśnę przycisk. Ale nic nie znajduję w logcat. @ Shubhank
wyx
odkomentuj te wiersze String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav

Odpowiedzi:

128

NAJSZYBSZY I DOBRY DO PROTOTYPU

Szybkim rozwiązaniem jest zapisanie go w sharedPrefs i dodanie tej logiki do onCreatemetody w MainActivity lub klasie rozszerzającej 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 :("));

CZYSTSZY SPOSÓB

Lepszą opcją jest stworzenie usługi i trzymanie się podobnej logiki. Najpierw utwórz nową usługę

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

A następnie dodaj go do pliku AndroidManifest

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

Wreszcie możesz użyć metody statycznej z usługi MyFirebaseMessagingService.getToken(Context);

NAJSZYBSZY, ALE WYCOFANY

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

Nadal działa, gdy używasz starszej biblioteki Firebase niż wersja 17.xx

Eliasz Kubala
źródło
6
Ale drugie podejście działa tylko do momentu wyczyszczenia wspólnych preferencji. Co się stanie, jeśli dane aplikacji zostaną wyczyszczone, a wartość ciągu zostanie utracona? Android nie wywołuje „onNewtoken ()”, ponieważ nie ma nowego tokenu. Ale jak poprosimy o token? Wszędzie jest napisane „po prostu użyj onNewToken ()”, ale ta metoda działa tylko wtedy, gdy istnieje nowy token. Powiedzmy, że ta metoda już została uruchomiona, ale nie zawracaliśmy sobie głowy przechowywaniem tokena. Później sprawdzamy i widzimy, że token nie jest ustawiony, co wtedy? Jak uruchomić FCM, aby ponownie przekazał mi token?
JeneralJames
1
Możesz użyć FirebaseInstanceId.getInstance().getInstanceId()zamiast FirebaseInstanceId.getInstance().getToken(), zobacz tę odpowiedź
Vadim Kotov
@JeneralJames, jeśli użytkownik wyczyści dane aplikacji, onNewTokenzawsze zostanie wyzwolony, z dokumentacji tutaj firebase.google.com/docs/cloud-messaging/android/ ...
sarah
26

Zespół odpowiedzialny za Firebase Android SDK nieco zmienił API. Zaimplementowałem logikę „Token to Server” w następujący sposób:

W moim wystąpieniu FirebaseMessagingService:

public class FirebaseCloudMessagingService extends FirebaseMessagingService {

    ...

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

    ...

}

Pamiętaj, że token dotyczy każdego urządzenia i Firebase może go zaktualizować niezależnie od logiki logowania. Tak więc, jeśli masz funkcje logowania i wylogowania, musisz wziąć pod uwagę dodatkowe przypadki:

  1. Gdy loguje się nowy użytkownik, należy powiązać token z nowym użytkownikiem (wysłać go na serwer). Ponieważ token może być aktualizowany podczas sesji, stary użytkownik i serwer nie znają tokena nowego użytkownika.
  2. Gdy użytkownik się wyloguje, należy odłączyć token. Ponieważ użytkownik nie powinien już otrzymywać powiadomień / wiadomości.

Korzystając z nowego API, możesz uzyskać token w ten sposób:

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

Powodzenia!

rzaaeeff
źródło
Próba uzyskania wartości poza OnSuccess daje null.
DragonFire
Funkcja logowania / wylogowania nie ma nic wspólnego z wiadomościami Push, jest to specyficzny biznesowy przypadek użycia. Na przykład możesz chcieć skierować do wylogowanych użytkowników niektóre powiadomienia marketingowe / promocyjne, aby skłonić ich do ponownego zalogowania się do aplikacji, w takim przypadku będziesz potrzebować tokena FCM. Ale odpowiedź jest prawidłowa, jeśli chodzi o zdobycie tokena.
milosmns
@milosmns, masz rację, jeśli chodzi o powiadomienia marketingowe / promocyjne. Nadal istnieje potrzeba wskazania statusu tokena. Prostym rozwiązaniem byłoby przechowywanie niezwiązanych tokenów w jakiejś tabeli historii, a następnie użycie tych poprzednich tokenów, aby zachęcić do
ponownego
Hm, nie jestem pewien, jak długo można ponownie używać tego samego tokena i kiedy dokładnie zostanie on unieważniony. Warto to zbadać, ponieważ sądzę, że po utracie ważności tokenów należałoby wyczyścić tę tabelę historii / pamięci podręcznej / trwałości.
milosmns
@milosmns, w Firebaseland, tokeny nie wygasają, ale są odnawiane. Kiedy uruchamiasz jakąkolwiek aktywność związaną z tokenem za pomocą FCM API, podany token jest weryfikowany. Jeśli token jest nieprawidłowy, pojawi się błąd: MissingRegistration lub błąd: InvalidRegistration. Więcej kodów błędów można znaleźć tutaj: firebase.google.com/docs/cloud-messaging/…
rzaaeeff
24

Ważna informacja.

jeśli usługa Google Play zawiesiła się lub nie działa, token zwrotu fcm = null

Jeśli usługa Play działa poprawnie, FirebaseInstanceId.getInstance().getToken()metoda zwracatoken

Log.d("FCMToken", "token "+ FirebaseInstanceId.getInstance().getToken());
Yogesh Rathi
źródło
Tak, ale zdarza się to bardzo często
Hoang Duc Tuan
Token jest zapisywany w pamięci podręcznej (najprawdopodobniej w pamięci) po jednorazowym pobraniu. Oznacza to, że musisz go pobrać raz lub sprawić, by Firebase w jakiś sposób ponownie wystawił dla Ciebie kolejny token. Zobacz tutaj, jak ręcznie pobrać stackoverflow.com/a/51630819/2102748
milosmns
13

Według doc

Przenieś aplikację kliencką GCM do FCM

onTokenRefresh()

Wywoływane tylko wtedy, gdy token InstanceID jest aktualizowany

Więc zadzwoni tylko za pierwszym razem, gdy zainstalujesz aplikację na swoim urządzeniu.

Dlatego sugeruję ręczne odinstalowanie aplikacji i ponowne uruchomienie

na pewno otrzymasz TOKEN

Gaurav
źródło
2
nie instalować ponownie, odinstaluj go ręcznie, a następnie uruchom projekt,
Gaurav,
odkomentuj te wiersze String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav
1
@Gaurav, Jak mogę otrzymać token po drugim logowaniu? onTokenRefreshnie wywołując każdego logowania. jak mogę otrzymać token na ekranie logowania?
delavega66
3
@ de_la_vega_66, Musisz zapisać swój token przy pierwszym logowaniu
Gaurav
Twoja usługa, która rozszerza FirebaseInstanceIdService i ma metodę wywołania zwrotnego onTokenRefresh (), MUSI być zarejestrowana w pliku manifestu: <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

Spróbuj tego. Dlaczego używasz RegistrationIntentService?

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

    private void registerToken(String token) {

    }
}
FireUser
źródło
8

Ta linia powinna dostarczyć token Firebase FCM.

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

Wykonaj Log.d, aby wydrukować go na monitorze systemu Android.

Alphonsus Chen
źródło
Zwraca wartość null
Kishan Solanki
7

Zamiast tego:

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

Zrób to:

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

I jeszcze jedno:

Musisz wywołać sendRegistrationToServer()metodę, która zaktualizuje token na serwerze, jeśli wysyłasz powiadomienia push z serwera.

AKTUALIZACJA:

Nowy token Firebase jest generowany ( onTokenRefresh()wywoływany), gdy:

  • Aplikacja usuwa identyfikator instancji
  • Aplikacja zostanie przywrócona na nowym urządzeniu
  • Użytkownik odinstalowuje / ponownie instaluje aplikację
  • Użytkownik czyści dane aplikacji.
aktywny od93
źródło
Musiałem usunąć identyfikator instancji FirebaseInstanceId.getInstance (). DeleteInstanceId (), ale otrzymałem BŁĄD SERWISOWY,
Hardik9850
2
Musisz biec FirebaseInstanceId.getInstance().deleteInstanceId()w innym wątku
rockar06
6

Jednocześnie nie zapomnij uwzględnić tego w swoim pliku manifestu, aby otrzymać identyfikator tokena

<service
    android:name=".MyFirebaseInstanceIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service>
Kharak
źródło
5

Metoda getToken()jest przestarzała. Możesz użyć getInstanceId()zamiast tego.

Jeśli chcesz obsłużyć wyniki podczas żądania instanceId(token), sprawdź ten kod.

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
źródło
4

W firebase-messaging:17.1.0i nowsza FirebaseInstanceIdService jest przestarzała, można dostać onNewTokensię na FirebaseMessagingServiceklasy, jak wyjaśniono na https://stackoverflow.com/a/51475096/1351469

Ale jeśli chcesz po prostu zdobyć token w dowolnym momencie, teraz możesz to zrobić w ten sposób:

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( this.getActivity(),  new OnSuccessListener<InstanceIdResult>() {
  @Override
  public void onSuccess(InstanceIdResult instanceIdResult) {
    String newToken = instanceIdResult.getToken();
    Log.e("newToken",newToken);
  }
});
jcesarmobile
źródło
Czy można to zwrócić, aby ta sama funkcja mogła być używana w wielu miejscach, czy też musimy kopiować i wklejać ze względu na asynchroniczną naturę firebase
DragonFire
3

Jeśli używasz jakiejś funkcji uwierzytelniania w Firebase, możesz pobrać token, używając tego:

//------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();
                      // ...
                }
            }
        });

Działa dobrze, jeśli użytkownik jest zalogowany. getCurrentUser ()

Diego Venâncio
źródło
2

Spróbuj tego

FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener(OnSuccessListener<InstanceIdResult> { instanceIdResult ->
             fcm_token = instanceIdResult.token}
Mohammad Rbabah
źródło
1

dla tych, którzy tu wylądują, do tej pory FirebaseInstanceIdServicejest przestarzała, użyj zamiast tego:

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

i zadeklaruj w AndroidManifest

<application... >

<service android:name=".fcm.MyFirebaseMessagingService">
    <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>
</application>
user1908375
źródło
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
źródło
0

FirebaseInstanceId.getInstance().getInstanceId()Jest przestarzała . Na podstawie dokumentu firebase możesz pobrać aktualny token rejestracji za pomocą następującego kodu:

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();
        }
    });
khesam109
źródło
-1

Aby uzyskać token, możesz skorzystać z następujących usług w Firebase (FCM):

FirebaseInstanceId.getInstance().getToken();
Ahmed Sayed
źródło
2
metoda getToken () jest przestarzała! Najlepsza odpowiedź pochodzi od @rzaaeeff.
Damiii
-9
Settings.Secure.getString(getContentResolver(),
                     Settings.Secure.ANDROID_ID);
Saurabh G.
źródło
Ten kod służy do uzyskania identyfikatora Androida urządzenia, a nie tokenu firebase.
Syed Afeef