简体   繁体   English

Firebase(FCM)如何获取令牌

[英]Firebase (FCM) how to get token

It's my first time using FCM.这是我第一次使用 FCM。

I download a sample from firebase/quickstart-android and I install the FCM Quickstart.我从firebase/quickstart-android下载了一个示例,然后安装了 FCM Quickstart。 But I can't get any token from the log even hit the LOG TOKEN button in the app.但我无法从日志中获取任何令牌,甚至点击应用程序中的LOG TOKEN 按钮

Then I try to send a message with Firebase console and set to target my app package name.然后我尝试使用 Firebase 控制台发送消息并设置为目标我的应用程序包名称。 I got incoming messages.我收到了传入的消息。

I want to know can FCM be used?GCM everything is ok.我想知道FCM可以用吗?GCM一切正常。

Solution:解决方案:

Because I am not an Android developer, just a backend developer.因为我不是安卓开发者,只是后端开发者。 So it takes me some time to solve it.所以我需要一些时间来解决它。 In my opinion, there`re some bugs in the sample app.在我看来,示例应用程序中存在一些错误。

在此处输入图像描述

Code:代码:

RegistrationIntentService.java注册意图服务.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 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.
    }
}

Add this in the MainActivity.java.在 MainActivity.java 中添加它。

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

After do above,you get the Token in Logcat.完成上述操作后,您就得到了 Logcat 中的 Token。 But finally, I find a convenient way to get it.但最后,我找到了一种方便的方法来获得它。 Just use debug mode to install the sample app and you can get the token when you first time to install it.只需使用调试模式安装示例应用程序,即可在第一次安装时获取令牌。

But I don't know why it can't print the log when I install it.但是不知道为什么安装的时候不能打印日志。 Maybe be related to the mobile system.可能与移动系统有关。

And then why I can't get the Notification.然后为什么我无法收到通知。 FirebaseMessagingService.onMessageReceived did not call sendNotification FirebaseMessagingService.onMessageReceived没有调用sendNotification

FASTEST AND GOOD FOR PROTOTYPE最快且最适合原型

The quick solution is to store it in sharedPrefs and add this logic to onCreate method in your MainActivity or class which is extending Application.快速的解决方案是将其存储在 sharedPrefs 中,并将此逻辑添加到 MainActivity 或扩展 Application 的类中的onCreate方法中。

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

CLEANER WAY更清洁的方式

A better option is to create a service and keep inside a similar logic.更好的选择是创建服务并保持类似的逻辑。 Firstly create new Service首先创建新服务

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

And then add it to AndroidManifest file然后将其添加到 AndroidManifest 文件中

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

Finally, you are able to use a static method from your Service MyFirebaseMessagingService.getToken(Context);最后,您可以使用服务中的静态方法MyFirebaseMessagingService.getToken(Context);

THE FASTEST BUT DEPRECATED最快但已弃用

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

It's still working when you are using older firebase library than version 17.xx当您使用比 17.xx 版本更旧的 firebase 库时,它仍然有效

Complete Solution:完整的解决方案:

The team behind Firebase Android SDK change API a little bit. Firebase Android SDK 背后的团队稍微改变了 API。 I've implemented "Token to Server" logic like this:我已经实现了这样的“令牌到服务器”逻辑:

In my instance of FirebaseMessagingService:在我的 FirebaseMessagingService 实例中:

public class FirebaseCloudMessagingService extends FirebaseMessagingService {

    ...

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

    ...

}

Keep in mind that token is per device, and it can be updated by Firebase regardless of your login logic.请记住,令牌是每个设备的,无论您的登录逻辑如何,它都可以由 Firebase 更新。 So, if you have Login and Logout functionality, you have to consider extra cases:因此,如果您具有登录和注销功能,则必须考虑额外的情况:

  1. When a new user logs in, you need to bind token to the new user (send it to the server).当新用户登录时,您需要将令牌绑定到新用户(将其发送到服务器)。 Because token might be updated during the session of old user and server doesn't know token of the new user.因为令牌可能会在旧用户会话期间更新,而服务器不知道新用户的令牌。
  2. When the user logs out, you need to unbind token.当用户注销时,您需要取消绑定令牌。 Because user should not receive notifications/messages anymore.因为用户不应该再收到通知/消息了。

Using new API, you can get token like this:使用新的 API,您可以获得这样的令牌:

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

Good luck!祝你好运!

FirebaseInstanceId class and it's method getInstanceId are also deprecated. FirebaseInstanceId类及其方法getInstanceId也已弃用。 So you have to use FirebaseMessaging class and it's getToken method instead.所以你必须使用FirebaseMessaging类,它是getToken方法。

FirebaseMessaging.getInstance().getToken().addOnSuccessListener(token -> {
        if (!TextUtils.isEmpty(token)) {
            Log.d(TAG, "retrieve token successful : " + token);
        } else{
            Log.w(TAG, "token should not be null...");
        }
    }).addOnFailureListener(e -> {
        //handle e
    }).addOnCanceledListener(() -> {
        //handle cancel
    }).addOnCompleteListener(task -> Log.v(TAG, "This is the token : " + task.getResult()));

The method getToken() is deprecated.方法getToken()已弃用。 You can use getInstanceId() instead.您可以改用getInstanceId()

If you want to handle results when requesting instanceId(token) , check this code.如果您想在请求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()));

Important information.重要信息。

if google play service hung or not running, then fcm return token = null如果 google play 服务挂起或未运行,则 fcm return token = null

If play service working properly then FirebaseInstanceId.getInstance().getToken() method returns token如果播放服务正常工作,则FirebaseInstanceId.getInstance().getToken()方法返回token

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

According to doc根据文档

Migrate a GCM client app to FCM 将 GCM 客户端应用程序迁移到 FCM

onTokenRefresh()

only Called if InstanceID token is updated仅在更新 InstanceID 令牌时调用

So it will call only at first time when you install an app to your device.因此,它只会在您将应用程序安装到您的设备时第一次调用。

So I suggest please uninstall your app manually and try to run again所以我建议请手动卸载您的应用程序并尝试再次运行

definitely you will get TOKEN你肯定会得到TOKEN

Try this.尝试这个。 Why are you using RegistrationIntentService ?你为什么使用RegistrationIntentService

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

    private void registerToken(String token) {

    }
}

This line should get you the firebase FCM token.此行应该为您提供 firebase FCM 令牌。

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

Do Log.d to print it out to the android monitor.执行 Log.d 将其打印到 android 监视器。

If you are using above 'com.google.firebase:firebase-messaging:22.0.0'如果您使用上面的 'com.google.firebase:firebase-messaging:22.0.0'

Get FCM Token (Force) with Kotlin way:用 Kotlin 方式获取 FCM Token (Force):

FirebaseMessaging.getInstance().token.addOnCompleteListener { task: Task<String> ->
   if (!task.isSuccessful) {
     return@addOnCompleteListener
   }

   pushToken = task.result
   Log.i("PUSH_TOKEN", "pushToken: $pushToken")
}

And you can get token via onNewToken method.您可以通过 onNewToken 方法获取令牌。 (This class must be implemented) (这个类必须实现)

class PushNotificationService: FirebaseMessagingService() {

    override fun onNewToken(token: String) {
        Log.e("PUSH_TOKEN", "Refreshed firebase token: $token")
    }
}

You need add PushNotificationService to AndroidManifest.xml您需要将PushNotificationService添加到AndroidManifest.xml

<service
  android:name=".PushNotificationService"
  android:exported="false"
  tools:ignore="Instantiatable">
  <intent-filter>
    <action android:name="com.google.firebase.MESSAGING_EVENT" />
  </intent-filter>
</service>

Instead of this:而不是这个:

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

Do this:做这个:

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

And one more thing:还有一件事情:

You need to call sendRegistrationToServer() method which will update token on server, if you are sending push notifications from server.如果您从服务器发送推送通知,您需要调用sendRegistrationToServer()方法来更新服务器上的令牌。

UPDATE:更新:

New Firebase token is generated ( onTokenRefresh() is called) when:在以下情况下会生成新的 Firebase 令牌( onTokenRefresh() ):

  • The app deletes Instance ID应用删除实例 ID
  • The app is restored on a new device该应用程序已在新设备上恢复
  • The user uninstalls/reinstall the app用户卸载/重新安装应用程序
  • The user clears app data.用户清除应用数据。

At the same time don not forget to include this in your manifest file to receive token id同时不要忘记将其包含在您的清单文件中以接收令牌 ID

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

The FirebaseInstanceId.getInstance().getInstanceId() is deprecated . FirebaseInstanceId.getInstance().getInstanceId()弃用 Based on firebase document , you can retrieve the current registration token using following code:基于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();
        }
    });

UPDATE 11-12-2020 2020 年 11 月 12 日更新

When you use 'com.google.firebase:firebase-messaging:21.0.0' is FirebaseInstanceId is depreacted now当您使用'com.google.firebase:firebase-messaging:21.0.0'FirebaseInstanceId现在已被弃用

Now we need to use FirebaseInstallations.getInstance().getToken() and FirebaseMessaging.getInstance().token现在我们需要使用FirebaseInstallations.getInstance().getToken()FirebaseMessaging.getInstance().token

SAMPLE CODE示例代码

FirebaseInstallations.getInstance().getToken(true).addOnCompleteListener {
            firebaseToken = it.result!!.token
        }

// OR

FirebaseMessaging.getInstance().token.addOnCompleteListener {
            if(it.isComplete){
                firebaseToken = it.result.toString()
                Util.printLog(firebaseToken)
            }
        }

You can use this method to get device token with firebase您可以使用此方法通过 firebase 获取设备令牌

 FirebaseMessaging.getInstance().getToken().addOnCompleteListener(new OnCompleteListener<String>() {
        @Override
        public void onComplete(@NonNull Task<String> task) {
            String deviceToken = task.getResult();
        }
    });

In firebase-messaging:17.1.0 and newer the FirebaseInstanceIdService is deprecated, you can get the onNewToken on the FirebaseMessagingService class as explained on https://stackoverflow.com/a/51475096/1351469firebase-messaging:17.1.0和更新版本中,不推荐使用 FirebaseInstanceIdService,您可以按照https://stackoverflow.com/a/51475096/1351469中的说明在FirebaseMessagingService类上获取onNewToken

But if you want to just get the token any time, then now you can do it like this:但是,如果您想随时获取令牌,那么现在您可以这样做:

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

If you are using kotlin and co-routine then add kotlin coroutine play library如果你使用的是 kotlin 和协程然后添加 kotlin 协程播放库

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:x.x.x'

use this simple method:使用这个简单的方法:

FirebaseMessaging.getInstance().token.await()

If are using some auth function of firebase, you can take token using this:如果正在使用 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();
                      // ...
                }
            }
        });

Work well if user are logged.如果用户已登录,则工作良好。 getCurrentUser()获取当前用户()

This the latest code to get fcm token in Activity (2021).这是在 Activity (2021) 中获取 fcm 令牌的最新代码。

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.d(TAG, "fcm token : "+token);
                        
                    }
                });

For new Token just add the newToken Method in FirebaseMessagingService extended class.对于新 Token,只需在 FirebaseMessagingService 扩展类中添加 newToken 方法。

@Override
    public void onNewToken(String token) {
        super.onNewToken(token);
        Log.d(TAG, token);
    }

try this尝试这个

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

for those who land here, up to now FirebaseInstanceIdService is deprecated now, use instead:对于那些登陆这里的人,到目前为止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);
    }
}

and declare in AndroidManifest并在 AndroidManifest 中声明

<application... >

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

            }
        });

Example to get firebase token inside suspend function在挂起函数中获取 firebase 令牌的示例

override suspend fun sendTokenToServer() {
    try {
 
        val token = FirebaseMessaging.getInstance().token.await()
        Log.i("TAG", "token " + token)
    } catch (exception:Exception) {

    }
}

I'll make this short.我会把这个简短的。 This is the only non-deprecated way to retrieve the Firebase's token:这是检索 Firebase 令牌的唯一不被弃用的方法:

FirebaseInstallations.getInstance().getToken(true).addOnCompleteListener(task -> { 
   // get token 
   String token = task.getResult().getToken();      
})

Use below code for latest firebase version - 'com.google.firebase:firebase-messaging:22.0.0'使用以下代码获取最新的 firebase 版本 - 'com.google.firebase:firebase-messaging:22.0.0'

FirebaseMessaging.getInstance().getToken()
                        .addOnCompleteListener(task -> {

                            if (!task.isSuccessful()) {
                                //handle token error
                                return;
                            }

                            strAppToken = task.getResult();

                        });

您可以在 Firebase (FCM) 中使用以下内容来获取令牌:

FirebaseInstanceId.getInstance().getToken();

FirebaseInstanceId.getInstance().getInstanceId() deprecated. FirebaseInstanceId.getInstance().getInstanceId() 已弃用。 Now get user FCM token现在获取用户 FCM 令牌

 FirebaseMessaging.getInstance().getToken()
            .addOnCompleteListener(new OnCompleteListener<String>() {
                @Override
                public void onComplete(@NonNull Task<String> task) {
                    if (!task.isSuccessful()) {
                        System.out.println("--------------------------");
                        System.out.println(" " + task.getException());
                        System.out.println("--------------------------");
                        return;
                    }

                    // Get new FCM registration token
                    String token = task.getResult();

                    // Log 
                    String msg = "GET TOKEN " + token;
                    System.out.println("--------------------------");
                    System.out.println(" " + msg);
                    System.out.println("--------------------------");

                }
            });

颤振解决方案:

var token = await FirebaseMessaging.instance.getToken();
Settings.Secure.getString(getContentResolver(),
                     Settings.Secure.ANDROID_ID);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM