FirebasePushNotificationPlugin icon indicating copy to clipboard operation
FirebasePushNotificationPlugin copied to clipboard

OnTokenRefresh is never called after an app update (new release)

Open Leftyx opened this issue 5 years ago • 4 comments

🐛 Bug Report

After an app update notifications are not received on any Android device.
OnTokenRefresh event is never called and no matter what the user does, the notification will never be received.
The only work-around is to uninstall and re-install the app.

Expected behavior

OnTokenRefresh should always be called and notifications should be received even after an app updated.

Reproduction steps

Create a sample application following the guidelines found in the documentation.
Test your notifications. Update the package version. Release the new version.

Configuration

Version: 3.3.10

Platform:

  • [ ] :iphone: iOS
  • [x] :robot: Android
  • [ ] :checkered_flag: WPF
  • [ ] :earth_americas: UWP
  • [ ] :apple: MacOS
  • [ ] :tv: tvOS
  • [x] :monkey: Xamarin.Forms

Leftyx avatar Nov 08 '20 11:11 Leftyx

Hi, I have the problem, see #319

I implemented a workaround, that sets the new token on the server, when the first notification is received by the app. If the server is not available at this moment, it is a problem

Freddyvdh avatar Nov 18 '20 20:11 Freddyvdh

@Freddyvdh, I've followed that tip and it seems to work better now. I only delay the Initialize for 3 seconds and I only do it when I am sure there's a new version / release.

This is the code I am using (MainApplication):

#if DEBUG
    [Application(Debuggable = true)]
#else
    [Application(Debuggable = false)]
#endif
public class MainApplication : Application
{
    public MainApplication(IntPtr handle, JniHandleOwnership transer) : base(handle, transer) {    }

    public override void OnCreate()
    {
        base.OnCreate();

        CrossCurrentActivity.Current.Init(this);

        if (IsPlayServicesAvailable())
        {
            ConfigureNotifications();
        }
    }

    private bool IsFirstLaunchForRelease => VersionTracking.IsFirstLaunchForCurrentVersion || 
                                            VersionTracking.IsFirstLaunchForCurrentBuild;

    /// <summary>
    /// Configures the Firebase Notifications
    /// </summary>
    private void ConfigureNotifications()
    {
        //Set the default notification channel for your app when running Android Oreo +
        if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
        {
            //Change for your default notification channel id here
            FirebasePushNotificationManager.DefaultNotificationChannelId = "MyChannel";

            //Change for your default notification channel name here
            FirebasePushNotificationManager.DefaultNotificationChannelName = "General";
        }

        Action initializeFirebasePushNotificationManager = () =>
        {
#if DEBUG
            //If debug you should reset the token each time.
            FirebasePushNotificationManager.Initialize(this, resetToken: true);
#else
            FirebasePushNotificationManager.Initialize(this, resetToken: false);
#endif

            // Only when auto-registration is false
            // CrossFirebasePushNotification.Current.RegisterForPushNotifications();

            //Handle notification when app is closed here
            CrossFirebasePushNotification.Current.OnNotificationReceived += (sender, eventArgs) => { };
        };

        if (IsFirstLaunchForRelease)
        {
            new Handler().PostDelayed(delegate
            {
                initializeFirebasePushNotificationManager();
            }, 3000);
        }
        else 
        {
            initializeFirebasePushNotificationManager();
        }

    }

    /// <summary>
    /// Checks Google Play Services is available
    /// </summary>
    /// <returns>Result</returns>
    public bool IsPlayServicesAvailable()
    {
        int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);

        if (resultCode == ConnectionResult.Success) return true;

        var errorMessage = "Google Play Services: This device is not supported";

        if (GoogleApiAvailability.Instance.IsUserResolvableError(resultCode))
        {
            errorMessage = "Google Play Services: " + GoogleApiAvailability.Instance.GetErrorString(resultCode);
        }

        Crashes.TrackError(new Exception(errorMessage));

        return false;
    }
}

Leftyx avatar Nov 19 '20 08:11 Leftyx

I checked my code, it some corona time in between ;)

In the delayed initialization I have two other timers: First is checking CrossFirebasePushNotification.Current.Token != StoredToken Second checks, if a new token has been retrieved, if not a local notification is shown, that no notifications can be received and that the app has to be opened.

Both timers are stopped, if OnTokenRefresh() is called.

May be it is too much, but know the app works without any problems.

I thought about making a pull request about changing the resetToken in line 139, without that, the plugin would not reset the token with a new version, which is not required, I think.

But to have the code is better, because Firebase could change the token.

Freddyvdh avatar Nov 19 '20 16:11 Freddyvdh

Is there an official solution to this problem?

scriptBoris avatar Feb 14 '21 10:02 scriptBoris