FCM – 重新调试应用程序后发送消息时出现Android Xamarin NotRegistered错误

我正在Xamarin Android中开发一个应用程序,用于通知我正在使用FCM预发布包: https : //www.nuget.org/packages/Xamarin.Firebase.Messaging/

现在一切正常,如果我清理App数据,会触发OnTokenRefresh事件并生成新令牌 – 当我在此令牌上发送新通知时,设备在OnMessageReceived()发送和接收通知 –

问题是当我对代码进行更改并再次运行应用程序时,如果我使用旧令牌,则在发送通知时会收到NotRegistered错误,但如果我去清理App Data,则会触发OnTokenRefresh()生成新令牌 – 新令牌有效。

类似的问题在这里,但这是GCM(我使用的是FCM):

Google云消息“未注册”失败并取消订阅最佳做法?

https://stackoverflow.com/a/36856867/1910735

https://forums.xamarin.com/discussion/65205/google-cloud-messaging-issues#latest

我的FCMInstanceIdService

 [Service, IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })] public class FCMInstanceIdService : FirebaseInstanceIdService { private string Tag = "FCMInstanceIdService"; public override void OnTokenRefresh() { var fcmDeviceId = FirebaseInstanceId.Instance.Token; if (Settings.DeviceId != fcmDeviceId) { var oldDeviceId = Settings.DeviceId; Settings.DeviceId = fcmDeviceId; //TODO: update token on DB - Currently OnTokenRefresh is only called when: 1. App data is cleaned, 2. The app is re-installed //_usersProvider.UpdateUserDeviceId(oldDeviceId, fcmDeviceId); } base.OnTokenRefresh(); } } 

我的留言接收服务:

 [Service, IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })] public class FCMListenerService : FirebaseMessagingService { private string Tag = "FCM_Listener_Service"; public override void OnMessageReceived(RemoteMessage message) { base.OnMessageReceived(message); var notification = message.GetNotification(); var data = message.Data; var title = notification.Title; var body = notification.Body; SendNotification(title, body); } private void SendNotification(string title, string body) { //TODO: Display notification to user } } 

表现:

           

如何在DEBUG模式下强制刷新FCM令牌,这样我每次运行应用程序时都不必删除应用程序数据?

由于此问题仅在调试应用程序时从Visual Studio运行应用程序时发生(而不是在部署到PlayStore的版本中),我暂时解决问题的方法是创建以下服务:

  [Service] public class FCMRegistrationService : IntentService { private const string Tag = "FCMRegistrationService"; static object locker = new object(); protected override void OnHandleIntent(Intent intent) { try { lock (locker) { var instanceId = FirebaseInstanceId.Instance; var token = instanceId.Token; if (string.IsNullOrEmpty(token)) return; #if DEBUG instanceId.DeleteToken(token, ""); instanceId.DeleteInstanceId(); #endif } } catch (Exception e) { Log.Debug(Tag, e.Message); } } } 

然后在我的启动Activity中(每当打开应用程序时加载的活动都执行以下操作:

 protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); #if DEBUG if (!IsMyServiceRunning("FCMRegistrationService")) { var intent = new Intent(this, typeof(FCMRegistrationService)); StartService(intent); } // For debug mode only - will accept the HTTPS certificate of Test/Dev server, as the HTTPS certificate is invalid /not trusted ServicePointManager.ServerCertificateValidationCallback += (o, certificate, chain, errors) => true; #endif } 

这将取消注册您现有的FCMToken并刷新令牌,因此将调用OnTokenRefresh方法,然后您必须编写一些逻辑来更新服务器上的FCMToken。

 [Service, IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })] public class FCMInstanceIdService : FirebaseInstanceIdService { // private string LogTag = "FCMInstanceIdService"; public override void OnTokenRefresh() { var fcmDeviceId = FirebaseInstanceId.Instance.Token; // Settings (is Shared Preferences) - I save the FCMToken Id in shared preferences // if FCMTokenId is not the same as old Token then update on the server if (Settings.FcmTokenId != fcmDeviceId) { var oldFcmId = Settings.FcmTokenId; var validationContainer = new ValidationContainer(); // HERE UPDATE THE TOKEN ON THE SERVER TBApp.Current._usersProvider.UpdateFcmTokenOnServer(oldFcmId, fcmDeviceId, validationContainer); Settings.FcmTokenId = fcmDeviceId; } base.OnTokenRefresh(); } } 

我正在尝试像这样初始化

  var options = new FirebaseOptions.Builder() .SetApplicationId("YOURAPPID") .SetApiKey("YOURAPIKEY") //.SetDatabaseUrl(Keys.Firebase.Database_Url) //i'M not using it .SetGcmSenderId("YOURSENDERID") //.SetStorageBucket(Keys.Firebase.StorageBucket)//i'M not using it .Build(); try { //try to initilize firebase app to get token FirebaseApp.InitializeApp(Forms.Context, options);//initializeto get token } catch { //if app already initialized it will throw exception, so get the previous active token and send to your server-database etc var instanceId = FirebaseInstanceId.Instance; var token = instanceId.Token; Service.MyFirebaseMessagingService.RegisterForAndroid(token); //this method sends the token to my server app, you have to write your own } 

因此,当用户打开应用时,我正在尝试重新初始化Firebase应用。 如果它已经被初始化它将抛出exception:)我正在那里获取令牌所以它给了我活跃的注册令牌。 如果应用程序未初始化,一切都将顺利进行,因此您的OnTokenRefresh方法将按预期触发。 希望这对你有所帮助。