Firebase(FCM)如何获取令牌

wyx*_*wyx 76 android firebase firebase-cloud-messaging

这是我第一次使用FCM.

我从firebase/quickstart-android下载了一个示例,我安装了FCM Quickstart.But我甚至无法从日志中获取任何令牌,甚至点击应用程序中的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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.
    }
}
Run Code Online (Sandbox Code Playgroud)

在MainActivity.java中添加它.

 Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
Run Code Online (Sandbox Code Playgroud)

完成上面后,你可以在logcat中获取令牌.但最后我找到了一个方便的方法来获取它.只需使用调试模式安装示例应用程序,您就可以在第一次安装时获取令牌.

但是我t why it can安装时不打印日志.可能与移动系统有关.

然后我为什么不能得到通知.FirebaseMessagingService.onMessageReceived未调用sendNotification

Eli*_*ala 94

最快和最好的原型

快速解决方案是将其存储在sharedPrefs中,并将此逻辑添加到onCreateMainActivity或扩展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 :("));
Run Code Online (Sandbox Code Playgroud)

清洁方式

更好的选择是创建服务并保持类似的逻辑.首先创建新服务

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将其添加到AndroidManifest文件中

<service
        android:name=".MyFirebaseMessagingService"
        android:stopWithTask="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
</service>
Run Code Online (Sandbox Code Playgroud)

最后,您可以使用服务中的静态方法 MyFirebaseMessagingService.getToken(Context);

最快,但已弃用

Log.d("Firebase", "token "+ FirebaseInstanceId.getInstance().getToken());
Run Code Online (Sandbox Code Playgroud)

当您使用旧的firebase库而不是版本17.xx时,它仍然有效

  • 但是第二种方法仅在清除共享首选项之前有效。如果清除了应用程序数据并且该字符串值丢失了怎么办?由于没有* new *令牌,因此Android不会调用“ onNewtoken()”。但是,我们如何请求令牌?它到处都说“只使用onNewToken()”,但是该方法仅在存在* new *令牌时才运行。假设该方法已经运行,但是我们不必费心存储令牌。稍后,我们执行检查,发现未设置令牌,然后该怎么办?如何触发FCM再次告诉我令牌? (3认同)

sNa*_*ash 20

FirebaseInstanceId类及其方法getInstanceId也已弃用。所以你必须使用FirebaseMessagingclass 和它的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()));
Run Code Online (Sandbox Code Playgroud)

该方法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()));
Run Code Online (Sandbox Code Playgroud)


Yog*_*thi 19

重要信息.

如果谷歌播放服务挂起或未运行,则fcm返回令牌= null

如果播放服务正常工作,则FirebaseInstanceId.getInstance().getToken()方法返回token

Log.d("FCMToken", "token "+ FirebaseInstanceId.getInstance().getToken());
Run Code Online (Sandbox Code Playgroud)

  • 很旧的答案。请更新。 (2认同)

rza*_*eff 14

Firebase Android SDK背后的团队稍微改变了API.我已经实现了"Token to Server"逻辑,如下所示:

在我的FirebaseMessagingService实例中:

public class FirebaseCloudMessagingService extends FirebaseMessagingService {

    ...

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

    ...

}
Run Code Online (Sandbox Code Playgroud)

请记住,令牌是每台设备,无论您的登录逻辑如何,它都可以由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
        }
    });
Run Code Online (Sandbox Code Playgroud)

祝好运!


Gau*_*rav 13

根据文件

将GCM客户端应用程序迁移到FCM

onTokenRefresh()
Run Code Online (Sandbox Code Playgroud)

仅在更新InstanceID令牌时调用

因此,只有在您的设备上安装应用时才会调用它.

所以我建议您手动卸载您的应用并尝试再次运行

肯定你会得到TOKEN

  • @ de_la_vega_66,您必须在首次登录时存储您的令牌 (3认同)
  • 不重新安装,*卸载*手动然后运行项目, (2认同)

小智 10

如果您使用上面的“com.google.firebase:firebase-messaging:22.0.0”

使用 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")
}
Run Code Online (Sandbox Code Playgroud)

您可以通过 onNewToken 方法获取令牌。(这个类必须实现)

class PushNotificationService: FirebaseMessagingService() {

    override fun onNewToken(token: String) {
        Log.e("PUSH_TOKEN", "Refreshed firebase token: $token")
    }
}
Run Code Online (Sandbox Code Playgroud)

您需要将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>
Run Code Online (Sandbox Code Playgroud)


Fir*_*ser 9

试试这个.你为什么用RegistrationIntentService

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

    private void registerToken(String token) {

    }
}
Run Code Online (Sandbox Code Playgroud)


小智 8

这一行应该为您提供firebase FCM令牌.

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

做Log.d将它打印到android监视器.


act*_*e93 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]
Run Code Online (Sandbox Code Playgroud)

做这个:

    // [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]
Run Code Online (Sandbox Code Playgroud)

还有一件事:

sendRegistrationToServer()如果要从服务器发送推送通知,则需要调用将更新服务器上的令牌的方法.

更新:

在以下情况下生成(onTokenRefresh()被调用)新的Firebase令牌:

  • 该应用程序删除实例ID
  • 该应用程序将在新设备上恢复
  • 用户卸载/重新安装应用程序
  • 用户清除应用数据.

  • 你需要在另一个线程中运行`FirebaseInstanceId.getInstance().deleteInstanceId()` (2认同)

khe*_*109 6

FirebaseInstanceId.getInstance().getInstanceId()弃用。基于firebase document,您可以使用以下代码检索当前的注册令牌:

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();
        }
    });
Run Code Online (Sandbox Code Playgroud)


Roh*_*har 6

如果您使用 kotlin 和协程,则添加 kotlin 协程播放库

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:x.x.x'
Run Code Online (Sandbox Code Playgroud)

使用这个简单的方法:

FirebaseMessaging.getInstance().token.await()
Run Code Online (Sandbox Code Playgroud)


Kha*_*rak 5

同时,不要忘记将其包含在清单文件中以接收令牌ID

<service
    android:name=".MyFirebaseInstanceIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service>
Run Code Online (Sandbox Code Playgroud)


Nil*_*hod 5

更新 11-12-2020

当您使用'com.google.firebase:firebase-messaging:21.0.0'FirebaseInstanceId是现在depreacted

现在我们需要使用FirebaseInstallations.getInstance().getToken()FirebaseMessaging.getInstance().token

示例代码

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

// OR

FirebaseMessaging.getInstance().token.addOnCompleteListener {
            if(it.isComplete){
                firebaseToken = it.result.toString()
                Util.printLog(firebaseToken)
            }
        }
Run Code Online (Sandbox Code Playgroud)


Naj*_*Ali 5

您可以使用此方法通过 firebase 获取设备令牌

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