Firebase (FCM), як отримати токен


97

Я вперше використовую FCM.

Я завантажую зразок з firebase / quickstart-android і встановлюю FCM Quickstart. Але я не можу отримати жодного маркера з журналу, навіть натиснувши кнопку LOG TOKEN у додатку.

Потім я намагаюся надіслати повідомлення за допомогою консолі Firebase і налаштувати націлювання на назву мого пакета програми. Я отримав вхідні повідомлення.

Я хочу знати, чи можна використовувати FCM? GCM все нормально.

Рішення:

Оскільки я не розробник Android, а лише бекенд-розробник. Тож мені потрібно трохи часу, щоб її вирішити. На мій погляд, у прикладі програми є деякі помилки.

введіть тут опис зображення

Код:

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

Додайте це в MainActivity.java.

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

Після цього вище , ви отримаєте жетон у Logcat. Але, нарешті, я знаходжу зручний спосіб його отримати. Просто використовуйте режим налагодження, щоб встановити зразок програми, і ви зможете отримати маркер при першій його установці.

Але я не знаю, чому він не може надрукувати журнал, коли я його встановлюю. Можливо, пов’язане з мобільною системою.

І чому тоді я не можу отримати Повідомлення. FirebaseMessagingService.onMessageReceived не викликав sendNotification


якщо журнал потрапляє, він відображатиме маркер із ним у зразку програми
Шубханк,

Ні, сказав зразок програми. Він покаже маркер у logcat, лише якщо я натисну кнопку. Але в logcat я нічого не знаходжу. @ Shubhank
wyx

розкоментуйте ці рядки String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav

Відповіді:


127

ШВИДКИЙ І ДОБРИЙ ПРОТОТИП

Швидке рішення - зберегти його у sharedPrefs і додати цю логіку до onCreateметоду у вашій MainActivity або класі, який розширює додаток.

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

ЧИСТИЙ ШЛЯХ

Кращий варіант - створити службу і дотримуватися подібної логіки. Спочатку створіть нову Службу

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

А потім додайте його у файл AndroidManifest

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

Нарешті, ви можете використовувати статичний метод із вашої Служби MyFirebaseMessagingService.getToken(Context);

НАЙШИРШИЙ, АЛЕ ЗНИЖЕНИЙ

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

Це все ще працює, коли ви використовуєте стару бібліотеку Firebase, ніж версія 17.xx


6
Але другий підхід працює лише до тих пір, поки спільні уподобання не будуть очищені. Що робити, якщо дані програми очищені, і це значення рядка втрачено? Android не викликає "onNewtoken ()", оскільки нового маркера немає . Але як тоді ми запитуємо маркер? Всюди написано "просто використовувати onNewToken ()", але цей метод працює лише тоді, коли є новий маркер. Скажімо, цей метод вже запущений, але ми не потрудились зберегти маркер. Пізніше ми виконуємо перевірку і бачимо, що маркер не встановлений, що тоді? Як запустити FCM, щоб повторно повідомити маркер?
JeneralJames


1
Ви можете використовувати FirebaseInstanceId.getInstance().getInstanceId()замість FirebaseInstanceId.getInstance().getToken(), див. Цю відповідь
Вадим Котов

@JeneralJames, якщо користувач очищає дані додатка, onNewTokenйого завжди буде активовано, з документації тут firebase.google.com/docs/cloud-messaging/android/…
sarah

26

Команда, що стоїть за Firebase Android SDK, трохи змінила API. Я реалізував логіку "Token to Server" так:

У моєму екземплярі FirebaseMessagingService:

public class FirebaseCloudMessagingService extends FirebaseMessagingService {

    ...

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

    ...

}

Пам’ятайте, що маркер призначається для кожного пристрою, і його можна оновити Firebase незалежно від вашої логіки входу. Отже, якщо у вас є функція входу та виходу, вам доведеться розглянути додаткові випадки:

  1. Коли новий користувач входить в систему, вам потрібно прив’язати маркер до нового користувача (надіслати його на сервер). Оскільки маркер може бути оновлений під час сеансу старого користувача, а сервер не знає маркер нового користувача.
  2. Коли користувач виходить із системи, потрібно відв’язати маркер. Оскільки користувач більше не повинен отримувати сповіщення / повідомлення.

Використовуючи новий API, ви можете отримати маркер таким чином:

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

Удачі!


Спроба отримати значення поза OnSuccess дає значення null.
DragonFire

Функціонал входу / виходу не має нічого спільного з push-повідомленнями, це конкретний випадок використання для бізнесу. Наприклад, можливо, ви захочете націлити вихідних користувачів за допомогою деяких маркетингових / промо-сповіщень, щоб вони знову ввійшли в програму, і в цьому випадку вам знадобиться маркер FCM. Але відповідь правильна з точки зору отримання токена.
milosmns

@milosmns, ти маєш рацію щодо маркетингових / промо-повідомлень. Проте існує потреба вказувати статус маркера. Найпростішим рішенням було б зберегти незв’язані токени в якійсь таблиці історії, а потім використовувати ці минулі токени, щоб заохотити їх до повторного входу.
rzaaeeff,

Хм, я не впевнений насправді, як довго ви можете повторно використовувати той самий маркер і коли саме він стає недійсним. Це варто дослідити, оскільки, мабуть, вам потрібно буде очистити цю таблицю історії / кешу / збереження, як тільки маркери стануть недійсними.
milosmns

@milosmns, у Firebaseland токени не закінчуються, а навпаки, оновлюються. Коли ви запускаєте будь-яку діяльність, пов’язану з маркером, за допомогою FCM API, наданий маркер перевіряється. Якщо маркер недійсний, ви отримаєте повідомлення про помилку: MissingRegistration або помилка: InvalidRegistration. Ви можете знайти більше кодів помилок тут: firebase.google.com/docs/cloud-messaging/…
rzaaeeff

24

Важлива інформація.

якщо служба Google Play зависла або не працює, то fcm return token = null

Якщо служба відтворення працює належним чином, FirebaseInstanceId.getInstance().getToken()метод повертаєтьсяtoken

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

Так, але це трапляється дуже часто
Хоанг Дук Туан

Токен кешується (швидше за все, в пам'яті) після того, як його було отримано один раз. Отже, це означає, що вам потрібно отримати його один раз або отримати Firebase, щоб якось перевидати вам інший маркер. Дивіться тут , як витягти вручну stackoverflow.com/a/51630819/2102748
milosmns

13

Згідно з док

Перенесіть клієнтську програму GCM на FCM

onTokenRefresh()

Викликається, лише якщо оновлено маркер InstanceID

Тож він буде дзвонити лише в перший раз, коли ви встановите програму на свій пристрій.

Тому я пропоную, будь-ласка, видалити програму вручну та спробувати запустити її знову

безумовно, ви отримаєте TOKEN


2
не переінсталюйте, видаліть його вручну, потім запустіть проект,
Гаурав,

розкоментуйте ці рядки String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav

1
@Gaurav, Як я можу отримати маркер після другого входу? onTokenRefreshне викликати кожен логін. як я можу отримати маркер на моєму екрані входу?
delavega66

3
@ de_la_vega_66, Ви повинні зберігати свій маркер при першому вході в систему
Gaurav,

Ваша служба, яка розширює FirebaseInstanceIdService і має метод зворотного виклику onTokenRefresh (), ПОВИННА бути зареєстрована у файлі маніфесту: <service android: name = "com.mypackage.name.MyInstanceIdService" android: exported = "true"> <intent-filter> <action android: name = "com.google.firebase.INSTANCE_ID_EVENT" /> </intent-filter> </service>
Кирило Кармазін

9

Спробуйте це. Чому ти використовуєш RegistrationIntentService?

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

    private void registerToken(String token) {

    }
}

8

Цей рядок повинен отримати вам токен FCM Firebase.

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

Виконайте Log.d, щоб роздрукувати його на моніторі Android.


Повертається нулем
Кішан Соланкі

7

Замість цього:

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

Зробити це:

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

І ще одне:

Вам потрібно викликати sendRegistrationToServer()метод, який оновить маркер на сервері, якщо ви надсилаєте push-повідомлення з сервера.

ОНОВЛЕННЯ:

Новий маркер Firebase генерується ( onTokenRefresh()викликається), коли:

  • Додаток видаляє ідентифікатор екземпляра
  • Додаток відновлено на новому пристрої
  • Користувач видаляє / перевстановлює програму
  • Користувач очищає дані програми.

Мені довелося видалити ідентифікатор екземпляра FirebaseInstanceId.getInstance (). DeleteInstanceId (), але я отримав ПОМИЛКУ ПОСЛУГИ,
Hardik9850

2
Вам потрібно запустити FirebaseInstanceId.getInstance().deleteInstanceId()іншу тему
rockar06,

5

Одночасно не забудьте включити це у свій файл маніфесту, щоб отримати ідентифікатор маркера

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

5

Метод getToken()застарілий. Можна використовуватиgetInstanceId() замість цього.

Якщо ви хочете обробляти результати під час запиту instanceId(token), перевірте цей код.

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

В firebase-messaging:17.1.0і новіше FirebaseInstanceIdService застаріла, ви можете отримати onNewTokenна FirebaseMessagingServiceкласі , як описано на https://stackoverflow.com/a/51475096/1351469

Але якщо ви хочете просто отримати маркер у будь-який час, то тепер ви можете зробити це так:

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

Чи можна це повернути, тому одну і ту ж функцію можна використовувати в багатьох місцях, або нам доводиться копіювати та вставляти через асинхронну природу firebase
DragonFire

3

Якщо ви використовуєте якусь функцію автентифікації firebase, ви можете взяти маркер за допомогою цього:

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

Працюйте добре, якщо користувач зареєстрований. getCurrentUser ()


2

спробуйте це

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

1

для тих, хто приземляється тут, дотепер FirebaseInstanceIdServiceзастарілий, використовуйте замість цього:

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

і оголосити в 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();

            }
        });

-1

Ви можете використовувати наступне у Firebase (FCM), щоб отримати маркер:

FirebaseInstanceId.getInstance().getToken();

2
метод getToken () застарілий! Зараз найкраща відповідь від @rzaaeeff.
Damiii

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

Цей код - отримати ідентифікатор Android пристрою, а не маркер Firebase.
Syed Afeef
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.