FCM代币发行

时间:2019-05-21 09:24:43

标签: android firebase-cloud-messaging

我在该应用程序的版本1中实现了UrbanAirship。 现在,我在应用程序的版本2中扩展了FirebaseMessagingService。 我没有接到onNewToken()的电话才能将令牌发送到我的服务器。 我的样板代码看起来像

AndroidManifest.xml

  <service
        android:name=".services.fcm.PushMessageReceiver"
        android:enabled="true"
        android:exported="true"
        android:stopWithTask="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

Receiver

        public class PushMessageReceiver extends FirebaseMessagingService {  ...
            @Override
            public void onMessageReceived(RemoteMessage remoteMessage) {
            ...
            }

            @Override
            public void onNewToken(String s) {
            Log.i(Config.LOGTAG, "######**** new token for fcm called");
                Context ctx =ApplicationCustom.getContext();
                SharedPreferences preferences = ctx.getSharedPreferences(Config.SHARED_PREFERENCES, Context.MODE_PRIVATE);
                preferences.edit().putString(Config.SHARED_PREFS_DEVICE_TOKEN, s).apply();
                Intent intent = new Intent(this, XmppConnectionService.class);
                intent.setAction(XmppConnectionService.ACTION_FCM_TOKEN_REFRESH);
                intent.putExtra("token", s);
                startService(intent);
                pushToServer();
            }

               public static void getToken() {
                Log.i(Config.LOGTAG, "######**** get token for fcm called");

                try {
                    Log.i(Config.LOGTAG, "######**** delete token for fcm called");
                    FirebaseInstanceId.getInstance().deleteInstanceId();
                    FirebaseInstanceId.getInstance().getInstanceId();
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.w(Config.LOGTAG, "######**** delete InstanceId failed", e);
                }

                FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener(task
        -> {
                    if (!task.isSuccessful()) {
                        Log.w(Config.LOGTAG, "getInstanceId failed", task.getException());
                        return;
                    }

                    Log.i(Config.LOGTAG, "######**** getInstanceId successful");

                    // Get new Instance ID token
                    String token = task.getResult().getToken();
                    Context ctx = ApplicationCustom.getContext();
                    SharedPreferences preferences = ctx.getSharedPreferences(Config.SHARED_PREFERENCES, Context.MODE_PRIVATE);
                    preferences.edit().putString(Config.SHARED_PREFS_DEVICE_TOKEN, token).apply(); 
            pushToServer();
           }); 
        }

    public void pushToServer(){
        // Logic to push token to a server reading from preferences
    }
}

观察:

1)onNewToken永远不会被正在更新的应用程序调用。

2)新安装获得令牌

3)我向FirebaseInstanceId.getInstance().deleteInstanceId()添加了通话 也不会调用OnComplete。

4)在真实电话(不是仿真器)上致电getToken(senderId, "FCM")总是导致

java.io.IOException: TOO_MANY_REGISTRATIONS
    at com.google.firebase.iid.zzr.zza(Unknown Source:66)
    at com.google.firebase.iid.zzr.zza(Unknown Source:79)
    at com.google.firebase.iid.zzu.then(Unknown Source:4)
    at com.google.android.gms.tasks.zzd.run(Unknown Source:5)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:764)

我该如何解决观察问题1.是否因为令牌已经交付给UrbanAirship而未调用onNewToken? 在服务的onCreate()方法中调用Fyi getToken。

implementation 'com.google.firebase:firebase-messaging:17.3.4'

3 个答案:

答案 0 :(得分:2)

您可以通过以下方式获取fcm令牌:-

FirebaseInstanceId.getInstance().getInstanceId()
                .addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
                    @Override
                    public void onComplete(@NonNull Task<InstanceIdResult> task) {
                        if (task.isSuccessful()) {
                            String firebaseToken = task.getResult().getToken();
                        } else {
                            getFirebaseToken();
                        }
                    }
                });

答案 1 :(得分:1)

如果没有调用onNewToken()没关系。您可以获得Firebase已为您的设备制作的最新令牌。 onNewToken()在特定情况下被调用。

在以下情况下,注册令牌可能会更改:

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

请阅读firebase文档: https://firebase.google.com/docs/cloud-messaging/android/client#retrieve-the-current-registration-token

对于第二个查询,deleteInstanceId是一个阻塞调用,因此您必须在后台线程中执行此操作。像这样

new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        FirebaseInstanceId.getInstance().deleteInstanceId();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();

答案 2 :(得分:1)

有时onTokenRefresh()方法调用会延迟一些时间,并且在新安装发生时它将生成令牌,说明其行为如何,我们需要实现以下功能来克服这些问题,同时还要保持新用户登录

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {


        private String TAG = getClass().getName();

        public static final String TOKEN_BROADCAST = "myfcmtokenbroadcast";

        @Override
        public void onTokenRefresh() {

            //For registration of token
            String refreshedToken = FirebaseInstanceId.getInstance().getToken();

            //To displaying token on logcat
            Log.d("TOKEN: ", refreshedToken);

            //calling the method store token and passing token
            getApplicationContext().sendBroadcast(new Intent(TOKEN_BROADCAST));
            storeToken(refreshedToken);

        }

        private void storeToken(String token) {
            //we will save the token in sharedpreferences later
            SharedPrefManager.getInstance(getApplicationContext()).saveDeviceToken(token);
        }


    }

在MainActivity类的onCreate方法中调用此方法

private void registerFCMToken(){
        registerReceiver(broadcastReceiver, new IntentFilter(MyFirebaseInstanceIDService.TOKEN_BROADCAST));
        final boolean isRegisterFcm = preferences.getBoolean("IS_REGISTER_FCM", false);
//      FCM token Register when onTokenRefresh method call
        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String fcmToken = SharedPrefManager.getInstance(MainActivity.this).getDeviceToken();
                if(!isRegisterFcm) {
                    RegisterFcmTokenRequest request = new RegisterFcmTokenRequest();
                    request.setFcmtoken(fcmToken);
                    performRegisterFcmRequest(request);
                }
            }
        };

//        FCM token Register when new user Login
        if(SharedPrefManager.getInstance(this).getDeviceToken() != null && !isRegisterFcm) {
            String fcmToken = SharedPrefManager.getInstance(MainActivity.this).getDeviceToken();
            RegisterFcmTokenRequest request = new RegisterFcmTokenRequest();
            request.setFcmtoken(fcmToken);

            performRegisterFcmRequest(request);
        }
    }

在onDestroy方法中

 unregisterReceiver(broadcastReceiver);

此类维护FCM令牌的Shredpreferance

public class SharedPrefManager {
private static final String SHARED_PREF_NAME = "FCMSharedPref";
private static final String TAG_TOKEN = "tagtoken";

private static SharedPrefManager mInstance;
private static Context mCtx;

private SharedPrefManager(Context context) {
    mCtx = context;
}

public static synchronized SharedPrefManager getInstance(Context context) {
    if (mInstance == null) {
        mInstance = new SharedPrefManager(context);
    }
    return mInstance;
}

//this method will save the device token to shared preferences
public boolean saveDeviceToken(String token){
    SharedPreferences sharedPreferences = mCtx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putString(TAG_TOKEN, token);
    editor.apply();
    return true;
}

//this method will fetch the device token from shared preferences
public String getDeviceToken(){
    SharedPreferences sharedPreferences = mCtx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
    return  sharedPreferences.getString(TAG_TOKEN, null);
}

}