我在该应用程序的版本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'
答案 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);
}
}