Android: Firebase 令牌最初为空 运行

Android: Firebase token is null at first run

我正在使用 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();
        }
    }
}

在主要活动中:

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

最后一个日志returns 首次安装并启动应用程序时为空

注册脚本:

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

令牌在应用程序首次启动时异步获取。在可以访问令牌之前,您必须等待 onTokenRefresh() 在您的 FirebaseInstanceIdService 中被调用。

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

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

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

在 MyFirebaseMessagingService class 任何地方(在 oncreate 方法中)添加以上行,然后只是 Toast 或记录 refreshedToken。

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

我刚遇到同样的问题,我就是这样解决的。在 activity 的 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);
        }
    }

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

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

我在网上找到一个post(抱歉,我不记得是哪一个了,我是前段时间找到的)改用了这个方法:

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

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

Return the master token for the default Firebase project.

而第二个被描述为:

Returns a token that authorizes an Entity to perform an action on behalf of the application identified by Instance ID. This is similar to an OAuth2 token except, it applies to the application instance instead of a user. For example, to get a token that can be used to send messages to an application via FirebaseMessaging, set to the sender ID, and set to "FCM".

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

只需替换:

String token = instanceID.getToken();

与:

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

它会起作用。

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

我在 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 
        }

    }
};

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

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

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

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

您可以在此处找到官方 google 文档:https://firebase.google.com/docs/cloud-messaging/android/client

一个不错的媒介 post 也会帮助你:https://medium.com/@cdmunoz/fcm-getinstance-gettoken-in-android-is-now-deprecated-how-to-fix-it-3922a94f4fa4