iProgram
iProgram

Reputation: 6577

How to get build and version number of Flutter app

I am currently developing an application which is currently in beta mode. Due to this, I would like to show them what version they are on. For example, "v1.0b10 - iOS". So far, I have got this code: Text("Build: V1.0b10 - " + (Platform.isIOS ? "iOS" : "Android")). How would I be able to get the build version and number within flutter?

Upvotes: 232

Views: 261682

Answers (12)

Mike
Mike

Reputation: 6405

Here's a simple compile-time bash solution if (like me) you don't want to add a big clunky dependency just to copy a string. This assumes there's a file at lib/constants.dart with values that look like this:

const buildNumber = 1;
const versionString = "0.1.0";

Here's the bash script:

full=$(cat pubspec.yaml | grep -m 1 -i "version:")

build=$(echo "$full" | awk -F '+' '{print $2}')
version=$(echo "$full" | awk -F '+' '{print $1}' | awk '{print $2}')

sed -i "s/const buildNumber.*/const buildNumber = $build;/g" ./lib/constants.dart
sed -i "s/const versionString .*/const versionString = \"$version\";/g" ./lib/constants.dart

Just run the script and it will copy the values from pubspec.yaml into the constants file.

Upvotes: 0

I found a simple hack that works in Flutter iOS/Android apps and doesn't require any additional plugins or packages.

  1. Register the pubspec.yaml itself as asset:

...

version: 1.2.3+45

...

flutter:

  ...

  assets:
    - pubspec.yaml

  1. Parse the version number from the text file:
final bundle = DefaultAssetBundle.of(context);
// or use root bundle if no BuildContext is available
final pubspec = await bundle.loadString("pubspec.yaml");
final version = pubspec.split("version: ")[1].split("+")[0];
// or use a fancy YAML parser if you prefer

Upvotes: 1

Paulo Belo
Paulo Belo

Reputation: 4447

Yet another solution (using yaml package):

final String pubspecString = await rootBundle.loadString('pubspec.yaml');
final parsedYaml = loadYaml(pubspecString);
print(parsedYaml['version']);

to get his working you must:

install yaml package (if not already):

flutter pub add yaml

in your code:

import 'package:yaml/yaml.dart';
import 'package:flutter/services.dart'; // needed to read the file

To be able to read the file, you must add it to assets. In pubspec.yaml add:

assets:
    - pubspec.yaml

Upvotes: 0

CharlyKeleb
CharlyKeleb

Reputation: 754

you can also do this using method channel

In your MainActivity.kt add this;

package "your package name"
import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity: FlutterActivity() {
    private val CHANNEL = "version_info"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            when (call.method) {
                "getAppVersion" -> {
                    val versionName = BuildConfig.VERSION_NAME
                    result.success(versionName)
                }
                "getBuildNumber" -> {
                    val versionCode = BuildConfig.VERSION_CODE
                    result.success(versionCode.toString())
                }
                else -> result.notImplemented()
            }
        }
    }
}

For IOS, add this in your AppDelegate.swift

   let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
let versionChannel = FlutterMethodChannel(name: "version_info", binaryMessenger: controller.binaryMessenger)

versionChannel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
  if call.method == "getAppVersion" {
    if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
      result(version)
    } else {
      result(FlutterError(code: "UNAVAILABLE",
                          message: "App version unavailable",
                          details: nil))
    }
  } else if call.method == "getBuildNumber" {
    if let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
      result(buildNumber)
    } else {
      result(FlutterError(code: "UNAVAILABLE",
                          message: "Build number unavailable",
                          details: nil))
    }
  } else {
    result(FlutterMethodNotImplemented)
  }
}

Now in make a dart class to invoke the method channels

   class VersionInfo {
  static const MethodChannel _channel = MethodChannel('version_info');

  static Future<String> get appVersion async {
    final String version = await _channel.invokeMethod('getAppVersion');
    return version;
  }

  static Future<String> get buildNumber async {
    final String buildNumber = await _channel.invokeMethod('getBuildNumber');
    return buildNumber;
  }
}

Now you can easily get your app version and version code
    String appVersion = await VersionInfo.appVersion;
    String appBuildNumber = await VersionInfo.buildNumber;

Upvotes: 0

Eel
Eel

Reputation: 1449

Using a plugin that have native code and method channel between dart and Kotlin/Swift etc... just to get basic data like the build number might be a little bit overkill, plugins has many build issues problems, when new things come out you will have to wait or send them PR yourself to update it

but there is another solution which is to having a script that extract the data from pubspec.yaml file into dart code, you will have to run that script every time you change the version in pubspec.yaml or when building the release app

here is a little script I wrote:


import 'dart:io' show File;

import 'package:yaml/yaml.dart';

// Extract data like the app version from pubspec.yaml file into dart code

void main(List<String> args) async {
  final pubspecYamlFile = File('./pubspec.yaml');
  final pubspecYamlContent = await pubspecYamlFile.readAsString();
  final yamlDocument = loadYaml(pubspecYamlContent) as YamlMap;
  final version = yamlDocument['version'].toString();
  final appVersion = version.split('+')[0];
  final appBuildNumber = version.split('+')[1];

  final repository = yamlDocument['repository'].toString();

  final generatedDartFile = '''
const appVersion = '$appVersion';
const appBuildNumber = $appBuildNumber;
const repository = '$repository';
''';
  final file = File('./lib/gen/pubspec.g.dart');
  if (!(await file.exists())) {
    await file.create(recursive: true);
  }
  await file.writeAsString(generatedDartFile);
}


I might create a dev package and publish it in pubspec because I need it in multiple projects

also this way you can get the data in your widget without using FutureBuilder widget because it's not a Future

Edit: There is already a dev package for this, check pubspec_extract and pubspec_generator

Upvotes: 1

Fakhriddin Abdullaev
Fakhriddin Abdullaev

Reputation: 4930

In Flutter mobile applications the version number is in pubspec.yaml file. like below:

version: 1.0.0+1

To get the version name and code, add the package_info dependency into pubspec.yaml file, like below:

dependencies:
  package_info: ^0.4.0+16

And

import 'package:package_info/package_info.dart'; // import the package_info

Future<void> _initPackageInfo() async {
    final _packageInfo = await PackageInfo.fromPlatform();
    setState(() {
          String AppName = _packageInfo.appName;
          String PackageName = _packageInfo.packageName;
          String AppVersion = _packageInfo.version;
          String BuildNumber = _packageInfo.buildNumber;
          String BuildSignature = _packageInfo.buildSignature;
    });
  }

Upvotes: 4

Asaf Pinhassi
Asaf Pinhassi

Reputation: 15573

For using it from command line or CLI, you need a pure Dart code.

I used the following script:

// ignore_for_file: avoid_print
import 'dart:io';

import 'package:path/path.dart';
import 'package:yaml/yaml.dart';

String pathToYaml = join(dirname(Platform.script.toFilePath()), '../pubspec.yaml');

Future<YamlMap> loadPubspec() async => loadYaml(await File(pathToYaml).readAsString());

void main() async {
  var pubspec = await loadPubspec();
  print(pubspec['version'].toString().split('+')[0]);
}

You can run it from the project root folder:

dart run scripts/get_version_name.dart

Upvotes: 8

Hashem Aboonajmi
Hashem Aboonajmi

Reputation: 13890

install package_info_plus, then you can use it directly with future builder in your widget tree:

 FutureBuilder<PackageInfo>(
              future: PackageInfo.fromPlatform(),
              builder: (context, snapshot) {
                switch (snapshot.connectionState) {
                  case ConnectionState.done:
                    return Align(
                      alignment: Alignment.bottomCenter,
                      child: Text(
                        'Version: ${snapshot.data!.version}',),
                      );
                  default:
                    return const SizedBox();
                }
              },
            ),

Upvotes: 19

diegoveloper
diegoveloper

Reputation: 103541

You can use package_info_plus.

The versions are extracted from:

Android:

build.gradle, versionCode and versionName

iOS:

Info.plist, CFBundleVersion

Usage

Add the dependency

  1. Add this to your package's pubspec.yaml file:
dependencies:
  package_info_plus: ^1.0.6
  1. Import the file into your dart file:
import 'package:package_info_plus/package_info_plus.dart';
  1. if your method is marked as async:
PackageInfo packageInfo = await PackageInfo.fromPlatform();

String appName = packageInfo.appName;
String packageName = packageInfo.packageName;
String version = packageInfo.version;
String buildNumber = packageInfo.buildNumber;

If you don't want to use await/async:

PackageInfo.fromPlatform().then((PackageInfo packageInfo) {
  String appName = packageInfo.appName;
  String packageName = packageInfo.packageName;
  String version = packageInfo.version;
  String buildNumber = packageInfo.buildNumber;
});

Upvotes: 377

Suragch
Suragch

Reputation: 512506

Note: This answer has been updated to reflect the fact that the package_info plugin is deprecated and redirects to package_info_plus.

Version name and build number

At development time, you can easily find the version name and build number of a Flutter or Dart project by inspecting pubspec.yaml. Here is an example:

version: 1.1.0+2

This is case the version name is 1.1.0 and the build number is 2.

However, if you want to get these values at runtime, you should use a plugin.

Add the dependency

In pubspec.yaml add the package_info_plus package.

dependencies:
  package_info_plus: ^1.0.2

Update the version number to the current one.

Import the package

In the file that you need it, add the following import.

import 'package:package_info_plus/package_info_plus.dart';

Get the version name and code

In your code you can get the app version name and code like this:

PackageInfo packageInfo = await PackageInfo.fromPlatform();
String version = packageInfo.version;
String code = packageInfo.buildNumber;

See also

Upvotes: 119

j-vasil
j-vasil

Reputation: 149

RE the multiple references to package_info, please note that this package has been deprecated and the recommended replacement is the Flutter Community Plus Plugins version, package_info_plus.

Upvotes: 7

Tarun Sharma
Tarun Sharma

Reputation: 1008

You can try new_version plugin. Using this plugin you can get installed App Version, Playstore App Version and app url which can redirect to playstore.

New Version Plugin

void versionCheck() async {
    final NewVersion newVersion = NewVersion(context: context);
    VersionStatus versionStatus = await newVersion.getVersionStatus();
    if (versionStatus != null && versionStatus.canUpdate) {
      await ConfirmDialog(
          context: context,
          title: 'Update Available',
          body: Text('A new version, ${versionStatus.storeVersion}, is available.'),
          acceptButton: 'Update Now',
          cancelButton: 'Update Later'
      ).then((ConfirmAction res) async {
        if (res == ConfirmAction.CONFIRM && await canLaunch(versionStatus.appStoreLink)) {
          await launch(versionStatus.appStoreLink, forceWebView: false);
        }
      });
    }
  }

Custom Alert Dialog Box

enum ConfirmAction{ CONFIRM, CANCEL }
Future<ConfirmAction> ConfirmDialog({
  BuildContext context,
  String title,
  Widget body,
  String acceptButton,
  String cancelButton
})
=> showDialog(
    context: context,
    barrierDismissible: false,
    builder: (BuildContext context) => AlertDialog(
      title: Wrap(
        crossAxisAlignment: WrapCrossAlignment.center,
        spacing: 4,
        children: <Widget>[
          Text(title)
        ],
      ),
      content: Wrap(
        runSpacing: 10,
        children: <Widget>[
          body,
        ],
      ),
      actions: <Widget>[
        FlatButton(
            padding: EdgeInsets.all(6),
            child: Text(acceptButton ?? 'Confirm'),
            onPressed: (){
              Navigator.of(context, rootNavigator: true).pop(ConfirmAction.CONFIRM);
            }
        ),
        FlatButton(
            padding: EdgeInsets.all(6),
            child: Text(cancelButton ?? 'Cancel'),
            onPressed: (){
              Navigator.of(context, rootNavigator: true).pop(ConfirmAction.CANCEL);
            }
        ),
      ],
    )
);

Upvotes: 2

Related Questions