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


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


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!


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

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


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) {

    }
}

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.


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.

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>

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

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

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 ()


2

Spróbuj tego

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

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>

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

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

-1

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

FirebaseInstanceId.getInstance().getToken();

2
metoda getToken () jest przestarzała! Najlepsza odpowiedź pochodzi od @rzaaeeff.
Damiii

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

Ten kod służy do uzyskania identyfikatora Androida urządzenia, a nie tokenu firebase.
Syed Afeef
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.