Local Way to Prompt Users to Update Your Flutter App Based on App Version Check and Handling Staged Rollouts

Local Way to Prompt Users to Update Your Flutter App Based on App Version Check and Handling Staged Rollouts

Keeping your users on the latest version of your app is crucial for providing them with new features, bug fixes, and improvements. In mobile app development, it’s essential to notify users when a new version is available in the app store and prompt them to update. In Flutter, you can implement this functionality locally using Firebase Firestore and package_info_plus and url_launcher to retrieve the app's current version, compare it with the latest version available, and re-route for an app update.

In this blog post, we’ll dive into how to prompt users to download a new version of your app based on an app update check, covering the following:

  1. Setting up Firebase Firestore to store the latest app version

  2. Retrieving the current app version using package_info_plus

  3. Checking for an update and prompting the user

  4. Handling different scenarios (iOS and Android)


Step 1: Setting up Firebase Firestore to Store the Latest App Version

Before you can notify users of a new update, you need a way to track the latest version of your app. Firebase Firestore is a great choice for this since it allows for real-time updates and easy retrieval of data.

  1. Create a Firestore Collection: In your Firebase console, create a collection (e.g., current_app_version) where you’ll store the latest app version.

    • Go to the Firebase console → Firestore Database.

    • Create a new collection named current_app_version.

    • Add a document with a field version that holds the latest app version (e.g., "1.2.0").

Example:

    {
      "version": "1.2.0"
    }
  1. Firestore Structure: Ensure that your collection follows this structure:

    • Collection: current_app_version

    • Document: version (with the latest app version as the value)


Step 2: Retrieving the Current App Version Using package_info_plus

In Flutter, the package_info_plus package provides an easy way to get the app version installed on the user’s device. This version will be compared to the version stored in Firestore.

Adding package_info_plus and url_launcher to Your Project

  1. Open your pubspec.yaml and add the following dependency:

     dependencies:
       url_launcher: ^6.3.0
       package_info_plus: ^8.0.2
    
  2. Run flutter pub get to install the package.

Fetching the App Version

Now, use package_info_plus to get the current version of the app installed on the user’s device. Here’s a utility function to retrieve the app version:

import 'package:package_info_plus/package_info_plus.dart';

Future<String> getDeviceAppVersion() async {
  try {
    final PackageInfo packageInfo = await PackageInfo.fromPlatform();
    return packageInfo.version;
  } catch (e) {
    print('Error fetching app version: $e');
    return 'unknown';
  }
}

This function safely retrieves the app version and handles any errors that might occur.


Step 3: Checking for an Update and Prompting the User

With the app version now retrievable, the next step is to compare it with the version stored in Firestore. If the stored version is higher than the current app version, prompt the user to download the new version.

Firestore Setup

Ensure you have the Firebase SDK configured in your app. You can follow the official Firebase documentation for adding Firebase to your Flutter app: Firebase Setup.

Once Firebase is set up, use the following function to check the latest version from Firestore:

import 'package:cloud_firestore/cloud_firestore.dart';

Future<String> getLatestAppVersionFromFirestore() async {
  final FirebaseFirestore firestore = FirebaseFirestore.instance;
  try {
    QuerySnapshot snapshot = await firestore.collection('current_app_version').get();
    if (snapshot.docs.isNotEmpty) {
      return snapshot.docs.first.get('version');
    } else {
      throw Exception('No version data found');
    }
  } catch (e) {
    print('Error fetching latest app version: $e');
    return 'unknown';
  }
}

Comparing App Versions and Showing an Update Dialog

Now, put everything together and check if an update is needed. If the version from Firestore is greater than the installed version, show a dialog that prompts the user to download the update. This can be plugged into the initState of your entry screen

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

void checkForUpdate(BuildContext context) async {
  String currentVersion = await getDeviceAppVersion();
  String latestVersion = await getLatestAppVersionFromFirestore();

  if (latestVersion != 'unknown' && currentVersion != 'unknown') {
    if (currentVersion != latestVersion) {
      // Show update dialog
      _showUpdateDialog(context);
    }
  }
}

void _showUpdateDialog(BuildContext context) {
  showDialog(
    context: context,
    builder: (context) {
      return AlertDialog(
        title: Text('Update Available'),
        content: Text('A new version of the app is available. Please update to continue using the app.'),
        actions: [
          TextButton(
            onPressed: () {
              Navigator.pop(context);
            },
            child: Text('Later'),
          ),
          TextButton(
            onPressed: () async {
              // Launch the app store or play store URL
              const url = 'https://play.google.com/store/apps/details?id=com.example.yourapp'; // Change this URL for your app
              if (await canLaunch(url)) {
                await launch(url);
              }
            },
            child: Text('Update Now'),
          ),
        ],
      );
    },
  );
}

In the _showUpdateDialog function:

  • If the app is outdated, a dialog is displayed prompting the user to update the app.

  • The url_launcher package is used to open the app’s store page (either Google Play or the App Store) when the user clicks "Update Now".

Ensure that your app’s store URL is correct. For Android, it should look like:

https://play.google.com/store/apps/details?id=com.example.yourapp

For iOS, it would look like:

https://apps.apple.com/us/app/example-app/id123456789

Step 4: Handling iOS and Android Versions

Both iOS and Android users can be notified of updates using the same approach. However, it’s important to ensure that the URLs provided to url_launcher are platform-specific. You can easily add a conditional check for the platform using Flutter’s Platform class.

import 'dart:io' show Platform;

void _showUpdateDialog(BuildContext context) {
  showDialog(
    context: context,
    builder: (context) {
      return AlertDialog(
        title: Text('Update Available'),
        content: Text('A new version of the app is available. Please update to continue using the app.'),
        actions: [
          TextButton(
            onPressed: () {
              Navigator.pop(context);
            },
            child: Text('Later'),
          ),
          TextButton(
            onPressed: () async {
              String url = '';
              if (Platform.isAndroid) {
                url = 'https://play.google.com/store/apps/details?id=com.example.yourapp';
              } else if (Platform.isIOS) {
                url = 'https://apps.apple.com/us/app/example-app/id123456789';
              }

              if (await canLaunch(url)) {
                await launch(url);
              }
            },
            child: Text('Update Now'),
          ),
        ],
      );
    },
  );
}

Handling Staged Rollouts with Firebase Remote Config

When using staged rollouts (where only a subset of users get the update initially), it's essential to avoid prompting users for an update if they're not yet part of the rollout. Firebase Remote Config can be used to control the update prompt so that it only shows up for users who are part of the rollout.

Here’s how to handle it:

  1. Configure Firebase Remote Config:

    In the Firebase console, go to Remote Config and create a parameter (e.g., is_update_required) with a boolean value. You can use Firebase's percentage-based targeting to ensure only a specific percentage of users receive the update prompt.

  2. Retrieve Remote Config Data:

    In your Flutter app, you can check the value of is_update_required from Firebase Remote Config to determine if the user should be prompted for an update.

    Example code to retrieve the Remote Config value:

     import 'package:firebase_remote_config/firebase_remote_config.dart';
    
     Future<bool> isUpdateRequired() async {
       final RemoteConfig remoteConfig = RemoteConfig.instance;
    
       try {
         await remoteConfig.fetchAndActivate();
         return remoteConfig.getBool('is_update_required');
       } catch (e) {
         print('Error fetching remote config: $e');
         return false; // Default to no update required
       }
     }
    
  3. Check the Update Condition:

    Now you can modify the existing app version check logic to also consider the is_update_required flag from Remote Config. If the flag is true, proceed to compare the app versions.

     void checkForUpdate(BuildContext context) async {
       String currentVersion = await getDeviceAppVersion();
       String latestVersion = await getLatestAppVersionFromFirestore();
       bool updateRequired = await isUpdateRequired();
    
       if (updateRequired && latestVersion != 'unknown' && currentVersion != 'unknown') {
         if (currentVersion != latestVersion) {
           // Show update dialog only if the rollout applies to this user
           _showUpdateDialog(context);
         }
       }
     }
    
  4. Control Rollouts via Firebase:

    In Firebase Remote Config, you can control the percentage of users who will see the update prompt. Initially, you can target 20-30% of users, and once you're confident the update is stable, increase the percentage to 100%.

By integrating Firebase Remote Config, you can manage staged rollouts efficiently, ensuring that only users who have access to the update are prompted to install it. This ensures a smoother user experience, preventing cases where users are directed to the store but cannot find the update.


Prompting users to download the latest version of your app is crucial for ensuring they have access to the latest features and bug fixes. With Firebase Firestore and package_info_plus, you can easily compare the app version installed on the user’s device with the latest version available, and notify them when an update is necessary.

By following the steps in this guide, you’ve implemented a robust system for checking and prompting users to update your Flutter app across iOS and Android. This enhances user experience and ensures that your app runs as efficiently as possible with the latest updates.

Takeaways:

  • Use Firebase Firestore to store and manage your app’s latest version.

  • Retrieve the installed app version using package_info_plus.

  • Use url_launcher to redirect users to the app store for updates.

  • Make the solution platform-specific to handle both Android and iOS.

By implementing these best practices, you ensure your users always have the latest version of your app with a smooth update experience!

This can also be achieved using the upgrader package in pub.dev

Did you find this article valuable?

Support Flutter Aware by becoming a sponsor. Any amount is appreciated!