Reputation: 6577
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
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
Reputation: 1267
I found a simple hack that works in Flutter iOS/Android apps and doesn't require any additional plugins or packages.
pubspec.yaml
itself as asset:
...
version: 1.2.3+45
...
flutter:
...
assets:
- pubspec.yaml
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
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
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
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
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
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
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
Reputation: 103541
You can use package_info_plus.
The versions are extracted from:
Android:
build.gradle, versionCode and versionName
iOS:
Info.plist, CFBundleVersion
dependencies:
package_info_plus: ^1.0.6
import 'package:package_info_plus/package_info_plus.dart';
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
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.
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.
In pubspec.yaml add the package_info_plus
package.
dependencies:
package_info_plus: ^1.0.2
Update the version number to the current one.
In the file that you need it, add the following import.
import 'package:package_info_plus/package_info_plus.dart';
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;
Upvotes: 119
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
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.
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