MicrosoftDocs / azure-docs

Open source documentation of Microsoft Azure
https://docs.microsoft.com/azure
Creative Commons Attribution 4.0 International
10.24k stars 21.41k forks source link

How To Get Current FCM Token #42933

Closed TonyLugg closed 4 years ago

TonyLugg commented 4 years ago

The doc shows how to setup FCM in the Android app with an OnNewToken override which seems to work if I uninstall the app. But, how can one retrieve the current token? If for some reason our attempt to send the "new" token to our back end fails, the app is left without the ability to resend the token the next time the user opens the app. I've seen Android docs about using FirebaseInstanceId.getInstance().instanceId but Xamarin doesn't like this.


Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

AdamS-MSFT commented 4 years ago

Thanks for the feedback! We are investigating the issue.

RyanHill-MSFT commented 4 years ago

Hi @TonyLugg, apologies for the late reply. Assuming you have your manifest settings and class overrides setup, you shouldn't need to manually resend tokens. You can make use of FirebaseInstanceId.Instance.Token to fetch the existing token. If you do; however, need to destroy your token and force a refresh, you should be able to make use of FirebaseIntsanceId.Instance.DeleteToken(). You can refer to https://docs.microsoft.com/en-us/xamarin/xamarin-forms/data-cloud/azure-services/azure-notification-hub#configure-the-android-application-for-notifications.

Let me know if this helps.

TonyLugg commented 4 years ago

Hi Ryan,

Thanks for the reply. The documentation you pointed to is outdated. I used to do it that way but FirebaseInstanceIdService is deprecated in Xamarin.Firebase.Messaging v71.1740.0, which I am using. And OnTokenRefresh is replaced with OnNewToken.

I decided to take a different approach and persist the token to Properties and resend it if necessary. Not sure how this will work with the next app update, but hopefully the existing token is still good if OnNewToken is not called.

RyanHill-MSFT commented 4 years ago

No problem @TonyLugg. I'll assign this to our doc author for further investigation so they can be aware this doc is outdated and has breaking changes due to package updates.

TonyLugg commented 4 years ago

Great. It would still be nice to have an answer of "how to" get the current token.

RyanHill-MSFT commented 4 years ago

Hi @TonyLugg, we are currently updating our docs but we have discovered some breaking changes that are outlined in https://github.com/xamarin/xamarin-forms-samples/pull/558. For an example, take a look at https://github.com/xamarin/xamarin-forms-samples/blob/master/WebServices/AzureNotificationHub/NotificationHubSample/NotificationHubSample.Android/FirebaseService.cs and let us know if that helps.

TonyLugg commented 4 years ago

Hi @RyanHill-MSFT,

I don't use the notification hub code in my app, our back-end service handles the notification hub. Also, your sample is still using the deprecated OnMessageReceived method. I have everything working with the new firebase code. I just wasn't able to retrieve the current token.

RyanHill-MSFT commented 4 years ago

Sorry about that @TonyLugg. Glad you did find a workaround. I'm sure the doc author will update the doc appropriately addressing these gaps.

TonyLugg commented 4 years ago

@RyanHill-MSFT I rewrote my firebase service class and removed the deprecated firebase ID class as necessary for Xamarin.Firebase.Messaging v71.1740.0. The Android doc shows a way of getting the "current token" but it doesn't work in Xamarin. I'm relying on the OnNewToken method which doesn't always get fired, so I am now caching the token for subsequent uses. I also incorrectly stated in my previous reply that OnMessageReceived is deprecated, which it is not (it is OnTokenReceived that is deprecated). I see that the new doc sample has been updated. Sorry for misreading it the first time.

RyanHill-MSFT commented 4 years ago

No worries @TonyLugg. Under which condition were you expecting the event to fire.

• The app deletes the Instance ID • The app is restored on a new device • The user uninstalls/reinstalls the app • The user clears app data

Does the event fire if when you force delete the existing token as outlined in https://firebase.google.com/docs/reference/android/com/google/firebase/iid/FirebaseInstanceId.html#public-void-deletetoken-string-senderid,-string-scope

sethmanheim commented 4 years ago

@TonyLugg Thank you for taking the time to submit this feedback. I have updated the Notification Hubs tutorial code to match the recent changes to the Xamarin Android tutorial. More info can be found here: https://docs.microsoft.com/xamarin/xamarin-forms/data-cloud/azure-services/azure-notification-hub#configure-the-android-application-for-notifications. Hope that is helpful. If not, please open a new issue. #please-close

pchandravadan commented 4 years ago

The recent update doesn't address the issue, appreciate it if the issue status changed to open. No information is provided on how to access token on subsequent usage of the app. I am using Xamarin.Essentials.SecureStorage for caching the token as a workaround. thanks.

tracy-hunt commented 3 years ago

@pchandravadan I was able to retrieve the current push token in MainActivity.cs with the following code: (Xamarin Forms 4.6.0.726, Xamarin Firebase Messaging 71.1740.0)

await Task.Run(() =>
  {
    var token = FirebaseInstanceId.Instance.GetToken("<your sender ID here>", "FCM");  // https://firebase.google.com/docs/reference/android/com/google/firebase/iid/FirebaseInstanceId.html#public-string-gettoken-string-senderid,-string-scope
    if (token != <saved token value>)
      {
        // update saved token, send it to the backend, etc.
      }                  
  });
pchandravadan commented 3 years ago

@tracy-hunt Thanks for your response. Can you clarify for me what is "" in the sample code? is this something you get from the google-service.json file?

tracy-hunt commented 3 years ago

@pchandravadan Yes, "<your sender ID here>" is in the google-services.json file as project_number. I believe it's also available from one of the Google consoles where you configure GCM/FCM, and there it's referred to as Sender ID.

WilkoSki commented 3 years ago

@tracy-hunt the code you specified works and is what is contained in the currently outdated Xamarin documentation.

But the point is though that FirebaseInstanceId.Instance.GetToken is all deprecated, FirebaseInstance, the Instance and GetToken method are all marked as deprecated. Yes they currently work but at some point they won't work.

Being reliant upon overriding OnNewToken from Firebase.Messaging.FirebaseMessagingService to obtain the token only when a new token is generated is a very weak implementation. You'll get it once per app install or if Android decides to issue a new token.

cgwcool commented 2 years ago

@WilkoSki I use below code to get token;

FirebaseOptions baseOptions = FirebaseOptions.FromResource(Android.App.Application.Context);
FirebaseOptions options = new FirebaseOptions.Builder(baseOptions).SetProjectId(baseOptions.StorageBucket.Split('.')[0]).Build();
FirebaseApp.ClearInstancesForTest();
FirebaseApp app = FirebaseApp.InitializeApp(Android.App.Application.Context, options);
var refreshedToken = await FirebaseMessaging.Instance.GetToken();
PhilHardingRiver commented 2 years ago

@WilkoSki I use below code to get token;

FirebaseOptions baseOptions = FirebaseOptions.FromResource(Android.App.Application.Context);
FirebaseOptions options = new FirebaseOptions.Builder(baseOptions).SetProjectId(baseOptions.StorageBucket.Split('.')[0]).Build();
FirebaseApp.ClearInstancesForTest();
FirebaseApp app = FirebaseApp.InitializeApp(Android.App.Application.Context, options);
var refreshedToken = await FirebaseMessaging.Instance.GetToken();

Regarding this snippet, I'm using the Xamarin.Firebase.Messaging nuget version 122.0.0.3 and the signature for GetToken() is this: public virtual Task GetToken(); This means if I await the method, the refreshedToken variable has a type of Java.Lang.Object which I currently suspect is due to an incorrect interop signature. If it is a correct signature, how do convert the Java.Lang.Object into a string token?

Thanks.

alexmartinezm commented 2 years ago

@WilkoSki I use below code to get token;

FirebaseOptions baseOptions = FirebaseOptions.FromResource(Android.App.Application.Context);
FirebaseOptions options = new FirebaseOptions.Builder(baseOptions).SetProjectId(baseOptions.StorageBucket.Split('.')[0]).Build();
FirebaseApp.ClearInstancesForTest();
FirebaseApp app = FirebaseApp.InitializeApp(Android.App.Application.Context, options);
var refreshedToken = await FirebaseMessaging.Instance.GetToken();

Regarding this snippet, I'm using the Xamarin.Firebase.Messaging nuget version 122.0.0.3 and the signature for GetToken() is this: public virtual Task GetToken(); This means if I await the method, the refreshedToken variable has a type of Java.Lang.Object which I currently suspect is due to an incorrect interop signature. If it is a correct signature, how do convert the Java.Lang.Object into a string token?

Thanks.

Have a look at this blog, it has an example with this exact method from FirebaseMessaging: https://www.damirscorner.com/blog/posts/20210416-AwaitingGooglePlayServicesTasks.html