【问题标题】:Android: Firebase token is null at first runAndroid:Firebase 令牌在第一次运行时为空
【发布时间】:2016-10-16 14:59:21
【问题描述】:

我正在使用 FCM 在我的应用中提供通知。一切运行良好,但现在我意识到,当我使用 Android Studio(不是来自 GooglePlay)安装我的应用程序时,令牌在第一次运行时为空。当我关闭我的应用程序并重新启动它时,令牌不再为空。是什么导致了这个问题,我该如何避免?

InstanceIDService:

public class InstanceIDService extends FirebaseInstanceIdService {

    @Override
    public void onTokenRefresh() {

        String token = FirebaseInstanceId.getInstance().getToken();
        registerToken(token);
    }

    private void registerToken(String token) {

        OkHttpClient client = new OkHttpClient();
        RequestBody body = new FormBody.Builder()
                .add("Token",token)
                .build();

        Request request = new Request.Builder()
                .url("url_to_registration_script")
                .post(body)
                .build();

        try {
            client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在 MainActivity 中:

FirebaseMessaging.getInstance().subscribeToTopic("topic");
String token = FirebaseInstanceId.getInstance().getToken();
Log.d("TOKEN", token);

第一次安装和启动应用时,Last log 返回 null

注册脚本:

 <?php 
 if (isset($_POST["Token"])) {

       $_uv_Token=$_POST["Token"];
       $conn = mysqli_connect("localhost","user","pass","db") or die("Error connecting");
       $q="INSERT INTO users (Token) VALUES ( '$_uv_Token') "
          ." ON DUPLICATE KEY UPDATE Token = '$_uv_Token';";

  mysqli_query($conn,$q) or die(mysqli_error($conn));
  mysqli_close($conn);
}
?>

【问题讨论】:

    标签: android firebase firebase-cloud-messaging


    【解决方案1】:

    在首次应用启动时异步获取令牌。您必须等待在您的FirebaseInstanceIdService 中调用onTokenRefresh(),然后才能访问令牌。

    【讨论】:

    • 我怀疑为什么我们每次都需要调用它 FirebaseMessaging.getInstance().subscribeToTopic("topic");在获取令牌实例之前。
    • 其实 String refreshedToken = FirebaseInstanceId.getInstance().getToken("send_id", "FCM");是正确的答案。
    【解决方案2】:

    从模拟器中卸载应用程序并再次运行,以便再次调用onTokenRefreshed方法。

    检查您是否已经注册并且您只想知道 FCM 令牌

    String refreshedToken = FirebaseInstanceId.getInstance().getToken();
    

    在 MyFirebaseMessagingService 类中的任何位置(在 oncreate 方法中)添加上述行,然后只需 Toast 或记录 refreshedToken。

    【讨论】:

      【解决方案3】:

      只需替换:

      String token = instanceID.getToken();
      

      与:

      String token = instanceID.getToken($SENDER_ID, "FCM");
      

      它会起作用的。

      【讨论】:

      • 这里的 $SENDER_ID 是什么?
      • 获取 FCM 发件人 ID:打开 Firebase 控制台。找到您的 Firebase 项目并点击项目名称。单击设置图标并选择“项目设置”菜单选择“Could Messaging”选项卡并使用页面上的发件人 ID
      • 嗨,Alaa,我通过实时调用这个来获得异常。 java.io.IOException: MAIN_THREAD try { String Token = FirebaseInstanceId.getInstance().getToken("", "FCM");整数a = 0;一个++; } catch (IOException e) { e.printStackTrace(); }
      • M.Homan 在其他 Thread 上运行该代码。为什么发送Sender Id 后此代码有效?有什么解释吗?
      【解决方案4】:

      我也遇到了同样的问题。我浏览了很多 SO 帖子和其他论坛,找到了适合我的解决方案。 FCM 文档说要使用这种方法来获取令牌。

      String refreshedToken = FirebaseInstanceId.getInstance().getToken();
      

      我在网上找到了一个帖子(我很抱歉,我不记得是哪一个了。我前一阵子找到了)使用了这种方法:

      String refreshedToken = FirebaseInstanceId.getInstance().getToken() (String authorizedEntity, String scope);
      

      FCM 文档将第一种方法描述为:

      返回默认 Firebase 项目的主令牌。

      而第二个被描述为:

      返回一个令牌,该令牌授权实体代表由实例 ID 标识的应用程序执行操作。 这类似于 OAuth2 令牌,只是它适用于应用程序实例而不是用户。 例如,要获取可用于通过 FirebaseMessaging 向应用程序发送消息的令牌,请设置为发件人 ID,并设置为“FCM”。

      我一直在研究为什么第一个方法调用需要更长的时间才能返回一个令牌,但我还没有找到答案。希望这会有所帮助。

      【讨论】:

      • 好像传2个参数,方法是在主线程中执行的。否则它的运行异步
      【解决方案5】:

      即使我也有同样的问题。我已经在启动器活动的 onCreate 中给出了 Log 语句来打印令牌。卸载应用程序后刷新令牌需要时间。这就是你得到空值的原因。您必须稍等片刻才能刷新令牌。

      【讨论】:

        【解决方案6】:

        有时可能会出现网络问题,即使互联网工作正常...... 检查您在 Android 项目的清单文件中定义的 FirebaseInstancId 类。

        【讨论】:

          【解决方案7】:

          我刚遇到同样的问题,这就是我修复它的方式。在您活动的 onCreate() 方法中的某处调用块。我想将 Token 发送到我的 Parse 服务器,因此您必须根据需要进行更改。

          This is我关注的样本。

          private void subscribeUserToParse() {
                  String deviceToken = FirebaseInstanceId.getInstance().getToken();
                  if (TextUtils.isEmpty(deviceToken)) {
                      Intent intent = new Intent(this, MyFirebaseInstanceIDService.class);
                      startService(intent);
                      return;
                  }
          
                  User user = UserUtil.retrieveUserFromDB(mRealm);
                  String objectId = user.getParseObjectId();
                  if (!TextUtils.isEmpty(objectId)) {
                      ParseUtils.subscribeWithUsersObjectId(objectId, deviceToken);
                  }
              }
          

          【讨论】:

            【解决方案8】:

            编写正确代码后我面临的最大问题是:- 不是 build-gradle 中最新版本的 google play services, 因此,请始终使用 firebase 在设置对话框中显示的 google-play-services 版本

            【讨论】:

            • 这真的可以解决所提出的问题吗?
            • 是的,我从昨晚开始就在尝试为什么我的代码没有显示 firebase 令牌然后我在 build gradle 中升级了我在 google-play-services 上的版本号,现在它可以工作了
            【解决方案9】:

            我在 Android 4.2 设备上遇到了同样的问题。 所以,要解决这个问题,首先,检查清单中的服务是否具有如下优先级:

                <service
                    android:name=".other.MyFirebaseInstanceIDService"
                    android:exported="false">
                    <intent-filter android:priority="1000">
                        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
                    </intent-filter>
                </service>
            

            其次,使用广播意图通知您的 MainActivity 更改了令牌:

            public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
            
            @Override
            public void onTokenRefresh() {
                // Get updated InstanceID token.
                String refreshedToken = FirebaseInstanceId.getInstance().getToken();
            
                final Intent intent = new Intent("tokenReceiver");
                final LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this);
                intent.putExtra("token",refreshedToken);
                broadcastManager.sendBroadcast(intent);
            }
            

            然后在 MainActivity 的 onCreate 中,添加:

                 @Override
            protected void onCreate(Bundle savedInstanceState) {
            ...
            LocalBroadcastManager.getInstance(this).registerReceiver(tokenReceiver,
                        new IntentFilter("tokenReceiver"));
            }
            

            并且,在 MainActivity 中,添加一个新的 BroadcastReceiver:

            BroadcastReceiver tokenReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    String token = intent.getStringExtra("token");
            
                    if(token != null)
                    {
                        Log.e("firebase", String.valueOf(token));
            
                        // send token to your server 
                    }
            
                }
            };
            

            【讨论】:

              【解决方案10】:

              由于getToken() 方法已弃用,您必须将其替换为侦听器。

              只需替换 String token = FirebaseInstanceId.getInstance().getToken(); 为以下代码 sn-p:

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

              你可以在这里找到官方的谷歌文档:https://firebase.google.com/docs/cloud-messaging/android/client

              一篇不错的中型帖子也会对您有所帮助:https://medium.com/@cdmunoz/fcm-getinstance-gettoken-in-android-is-now-deprecated-how-to-fix-it-3922a94f4fa4

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2016-01-12
                • 2023-04-09
                • 2017-08-10
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2022-01-20
                • 1970-01-01
                相关资源
                最近更新 更多