0 purchases
upgrade
In App Upgrade #
A Flutter plugin for prompting and help users to upgrade when there is a newer version of this app in the app store or server repository.
#
This is an developing plugin. The plugin's API maybe has breaking changes. Please use with caution or continuous attention updates.
Contents #
Overview
Platform Support
How it work?
Getting Started
Basic Concepts
Custom View
Core API Reference
License
Overview #
This plugin has the following functions:
Check for whether has a newer app version
When a newer app version is available in the app store, notify user to update.
When a newer app version is available in custom app version management server, download and install it.
With today's modern app stores, there is little need to persuade users to upgrade because most are already using the auto upgrade feature. However, there may be times when an app needs to be updated more quickly than usual, and nagging a user to upgrade will entice the upgrade sooner.
Also, Flutter supported more than just Android and iOS platforms that doesn't has the dominant app store, like macOS, linux and windows, need to handle distribution and upgrade ourselves.
Platform Support #
Platform
Open App Store
Download/Install Installer
Third-party App Store
iOS
✅Yes
❌No
android
✅Yes
✅Yes
Google Play, 酷安, 应用宝, 百度手机助手, 360手机助手, 豌豆荚
macOS
✅Yes
✅Yes
linux
❌No
✅Yes
windows
❌No
✅Yes
How it work? #
Getting Started #
0. Preparation #
You should supply a server that offer App Version Config File lookup and install files download services.
Example server at Upgrade Server.
1. Installing #
add this code in pubspec.yaml
dependencies:
...
upgrade: last version
copied to clipboard
2. Config Before Use #
Android
Create file_provider_path.xml at android/app/src/main/res/xml, and add below content:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="files" path="." />
<cache-path name="cache" path="." />
<external-path name="external" path="." />
<external-cache-path name="cache" path="." />
<external-files-path name="files" path="." />
</paths>
copied to clipboard
Add below attributes in android/app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="your.package">
<!--other attributes-->
<!--(if you want to upload google store,can not add this permission)-->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application>
<!--other attributes-->
<provider
android:authorities="${applicationId}.fileProvider"
android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_path"/>
</provider>
</application>
</manifest>
copied to clipboard
MacOS
You should set below attributes in *.entitlements
<dict>
<!--other attributes-->
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.files.downloads.read-write</key>
<true/>
</dict>
copied to clipboard
3. Create Version Config File at local to mark current app's version. #
Example at AppcastItem.
4. Init plugin in suitable places. #
void main() {
UpgradeManager.instance.init(
url: '', // upgrade server url
currentVersionPath: '',
);
runApp(const MyApp());
}
copied to clipboard
5. Download if need and install. #
how to use? see UpgradeManager
// Download if need
UpgradeManager.instance.download()
// Install
UpgradeManager.instance.install()
copied to clipboard
Basic Concepts #
Appcast #
(⚠️ If incorrently profile or lack config file, the plugin will not work.)
An Array of AppcastItem. will select the best one as the latest version.
AppcastItem
Name
Type
Description
release_notes
dynamic
Any types, all data will pass to CustomUpgradeDialog completely.
date
DateTime?
The appcast's release date.
version
String | Object
The semantic Versioning spec at https://semver.org/, must be a string same with the spec or an object like Version Object
display_version_string
String?
Custom display version string, If you don't like version' string
os
ios | android | macos | linux | windows
Enum, must one of ios | android | macos | linux | windows, the appcast only used in the os
minimum_system_version
String?
Not implementation yet
maximum_system_version
String?
Not implementation yet
installers
Array<Map<String, dynamic>>
The appcast's installers. Execute in sequence, one execution fails to select the next, see Installer
Appcast config file example as below:
/// version.json
[
{
"name": "Flutter-InAppUpgrade",
"description": "this is Flutter-InAppUpgrade local example app",
"release_notes": "\n1. \n2. \n3.",
"version": "0.3.1-beta+20130313144700",
"os": "macos",
"installers": [{
"initializer": "macos_app_store",
"app_id": "1233593954"
}, {
"initializer": "file",
"file_url": "http://localhost:8000/download/flutter-inappupgrade-v0.3.2-beta.dmg"
}]
},
{
"name": "Flutter-InAppUpgrade",
"description": "this is Flutter-InAppUpgrade local example app",
"release_notes": "\n1. \n2. \n3.",
"version": "0.3.1-beta+20130313144700",
"os": "ios",
"installers": [{
"initializer": "ios_app_store",
"app_id": "",
"in_app": false
}]
},
{
"name": "Flutter-InAppUpgrade",
"description": "this is Flutter-InAppUpgrade local example app",
"release_notes": "\n1. \n2. \n3.",
"version": "0.3.1-beta+20130313144700",
"os": "android",
"installers": [{
"initializer": "android_app_market",
"market": "official"
}]
}
]
copied to clipboard
Additional: Version Object
major, minor, patch at least one must be greater than 0
Name
major
required
Int, greater than 0
minor
required
Int, greater than 0
patch
required
Int, greater than 0
pre_release
optional
Array
build
optional
String, must contain only [0-9A-Za-z-.]
UpgradeStatus #
Plugin's state, will auto update when state changes.
Name
Description
loadingLocalConfig
Plugin's state will be loadingLocalConfig when init() load local version config file
idle
Plugin's state will be idle when init() finished, Initial state
checking
Plugin's state will be checking when calling checkForUpdates()
available
Plugin's state will be available when has newer version after checkForUpdates()
upToDate
Plugin's state will be upToDate when no newer version after checkForUpdates()
downloading
Plugin's state will be downloading when downloading install file
readyToInstall
Plugin's state will be readToInstall when downloaded install file
installing
Plugin's state will be installing when install download file or open app store
error
Plugin's state will be error when catch error
dismissed
Plugin's state will be dismissed when call dismiss()
Installer #
Appcast's installer, specifies how to install update.
System Installers
1. file installer
Download install file and install it.
{
"identifier": "file", // must
"file_url": "", // parameter, where to download
"close_on_installing": true, // parameter, default is true, If if ture, will close app when installing.
}
copied to clipboard
2. android apk installer
Download android apk and install it.
Don't use file installer, it does not work because of system limitations.
{
"identifier": "android_apk", // must
"file_url": "", // parameter, where to download
}
copied to clipboard
3. android app market installer
open android app market.
{
"identifier": "android_app_market", // must
"market": "official | google_play | cool | tencent | baidu | 360 | wandoujia", // enum, app market
}
copied to clipboard
4. ios app store installer
open ios app store.
{
"identifier": "ios_app_store", // must
"app_id": "", // parameter, app id
"in_app": false, // parameter, default is false, If ture, will open app store in app.
}
copied to clipboard
5. macos app store installer
open macos app store.
{
"identifier": "macos_app_store", // must
"app_id" "", // parameter, app id
}
copied to clipboard
Custom Installers
If system installers cannot meet your requirements. you can define your custom installer like below:
1. Define custom install.
/// custom installer define file.
class CustomInstallerInitializer extends InstallInitializer {
@override
String get identifier => "custom installer identifer, unique";
@override
Installer init({
required UpgradeStateChangeNotifier state,
required Map<String, dynamic> data,
}) {
return CustomInstaller(
state: state,
param: data['param'],
);
}
}
class CustomInstaller extends Installer {
var param;
CustomInstaller({
required super.state,
required this.param,
}) : super.init();
@override
bool hasDownload() => true;
@override
void download({
String? url,
File? file,
void Function(int received, int total, bool failed)? onReceiveProgress,
void Function()? onDone,
}) async {
/// How to download, can empty if has download is false.
}
@override
Future<bool> install() async {
/// How to install.
}
}
copied to clipboard
2. Register custom installer when plugin init.
UpgradeManager.instance.init({
url: "",
currentVersionPath: "",
customInstallInitializers: const [
CustomInstallerInitializer(),
],
})
copied to clipboard
Custom View #
If you want build some UI view rely on Upgrade state, you can use CustomUpgradeView widget.
CustomUpgradeView #
The widget will pass plugin's all state to you, and responsively.
Widget build(BuildContext context) {
return CustomUpgradeView(
builder: (context, state) {
return Text("implement your widget");
}
);
}
copied to clipboard
There are two convenient widgets of CustomUpgradeView:
1. CustomUpgradeStatusIndicator #
The widget will pass #UpgradeStatus to you, it is convenient for you to create components that prompt the user for changes in upgrage state.
Widget build(BuildContext context) {
return CustomUpgradeStatusIndicator(
builder: (context, status) {
return Text(status.toString());
}
);
}
copied to clipboard
2. CustomUpgradeDialog #
The widget will pass latest AppcastItem's releaseNotes, it is convenient for you to create dialog that prompt the user about what's update.
Widget build(BuildContext context) {
return CustomUpgradeDialog(
builder: (context, releaseNotes) {
return Text(releaseNotes.toString());
}
);
}
copied to clipboard
Core API Reference #
UpgradeManager #
Plugin's core class, manage app's upgrade.
Member Variables
UpgradeStatus staus;
copied to clipboard
Plugin's state, see UpgradeStatus
AppcastItem? current;
copied to clipboard
App's current version, see Appcast, AppcastItem.
AppcastItem? latest;
copied to clipboard
App's latest version, see Appcast, AppcastItem.
Installer? installer;
copied to clipboard
Current Installer.
Methods
void UpgradeManager.instance.init({
required String url,
required String currentVersionPath,
List<InstallInitializer> customInstallInitializers = const [],
bool crashIfNoLegalConfigFile = false,
})
copied to clipboard
Init UpgradeManger.
Parameters
url: A URL used to detect if there is a new version of the app.
currentVersionPath: A config file path that mark current version, see Appcast, Create Version Config File at Local.
customInstallInitializers: custom InstallInitializer, see Custom Installers.
crashIfNoLegalConfigFile: Whether crash if no legal config file in local, default is false.
void UpgradeManager.instance.checkForUpdates()
copied to clipboard
Check for updates.
void UpgradeManager.instance.download({
String? url,
File? file,
void Function(int received, int total, bool failed)? onReceiveProgress,
void Function()? onDone,
})
copied to clipboard
Download install file, if has new version.
Parameters
url: A URL to download install file. if null, it will try to download from file installer's file_url.
file: Where the downloaded file is stored, If null, will store at Temporary Directory.
onReceiveProgress: Download progress.
onDone: call on download finish.
Future<bool> UpgradeManager.instance.install();
copied to clipboard
Install from current installer, will return install success or failure.
bool UpgradeManager.instance.nextInstaller();
copied to clipboard
If install failure, you can call nextInstaller() to change to next installer, and then call install() to install it.
License #
MIT
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.