Firebase (FCM) как получить токен


98

Я впервые использую FCM.

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

Затем я пытаюсь отправить сообщение с помощью консоли Firebase и настраиваю таргетинг на имя моего пакета приложения. Я получаю входящие сообщения.

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

Решение:

Потому что я не разработчик Android, а просто backend-разработчик. Так что мне нужно время, чтобы решить эту проблему. На мой взгляд, в тестовом приложении есть несколько ошибок.

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

Код:

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, только если я нажму кнопку. Но я ничего не нахожу в журнале. @ Shubhank
wyx

раскомментируйте эти строки String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav

Ответы:


130

САМЫЙ БЫСТРЫЙ И ХОРОШИЙ ДЛЯ ПРОТОТИПА

Быстрое решение - сохранить его в sharedPrefs и добавить эту логику в onCreateметод в вашем MainActivity или классе, расширяющем 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 :("));

ЧИСТЫЙ ПУТЬ

Лучше создать сервис и придерживаться аналогичной логики. Сначала создайте новую службу

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/…
Сара,

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

Да, но это случается очень часто
Хоанг Дык Туан

Токен кэшируется (скорее всего, in-mem) после того, как он был получен один раз. Это означает, что вам нужно получить его один раз или заставить Firebase каким-то образом повторно выпустить для вас другой токен. См. Здесь, как получить вручную stackoverflow.com/a/51630819/2102748
milosmns

13

Согласно док.

Перенос клиентского приложения GCM на FCM

onTokenRefresh()

Вызывается только при обновлении токена InstanceID

Поэтому он будет вызывать только в первый раз, когда вы устанавливаете приложение на свое устройство.

Поэтому я предлагаю удалить приложение вручную и попробовать запустить снова.

обязательно получите ТОКЕН


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

раскомментируйте эти строки 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

Эта строка должна предоставить вам токен firebase FCM.

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

Сделайте Log.d, чтобы распечатать его на мониторе Android.


Возвращает null
Кишан Соланки

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 (), но получил
ОШИБКУ

2
Вам нужно запустить FirebaseInstanceId.getInstance().deleteInstanceId()другую тему
rockar06 02

6

В то же время не забудьте включить это в свой файл манифеста, чтобы получить идентификатор токена.

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

            }
        });

0

FirebaseInstanceId.getInstance().getInstanceId()Является устаревшим . На основе документа firebase вы можете получить текущий регистрационный токен, используя следующий код:

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

Вы можете использовать следующее в Firebase (FCM), чтобы получить токен:

FirebaseInstanceId.getInstance().getToken();

2
getToken () устарел! Лучший ответ сейчас от @rzaaeeff.
Damiii

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

Этот код предназначен для получения идентификатора Android устройства, а не токена firebase.
Сайед Афиф,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.