Выпуск токена FCM - PullRequest
2 голосов
/ 21 мая 2019

У меня был UrbanAirship реализован в версии 1 приложения. Теперь я расширил 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. Не вызван ли onNewToken из-за того, что токен уже доставлен в UrbanAirship? Fyi getToken вызывается в методе onCreate () службы.

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

Ответы [ 3 ]

2 голосов
/ 21 мая 2019

вы можете получить токен 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 голос
/ 21 мая 2019

Некоторое время вызывается метод 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);
        }


    }

В вашем методе onCreate в классе MainActivity вызовите этот метод

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

Этот класс поддерживает Shredpreferance для токена FCM

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

}

1 голос
/ 21 мая 2019

Ничего страшного, если ваш onNewToken () не вызывается.Вы можете получить последний токен, уже созданный firebase для вашего устройства.onNewToken () вызывается в определенных случаях.

Токен регистрации может измениться, когда:

-Приложение удаляет идентификатор экземпляра
-Приложение восстанавливается на новом устройстве
-Пользователь удаляет / переустанавливает приложение
-Пользователь очищает данные приложения.

Прочтите документацию по 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...