Flutter实现APP版本更新
前言:
Flutter APP打开后检测到有新版本,Android端可以强制更新APK或者跳转到 Google play 官网去下载,iOS端只能去 App Store 官网下载。因为我们的应用是上架到 Google Play,所以当用户点击下载的按钮,直接跳转到 Google Play 官网或者 App Store 官网去下载APK即可。下面我简单总结一下在Flutter中实现“版本更新”的功能。
思路:
1.第一次打开APP时执行"版本更新"的网络请求;
2.比较服务器的版本号跟当前的版本号,来判断要不要升级APP应用程序;
3.弹出“版本更新”对话框;
4.点击"Later"把时间戳保存下来,每次打开APP获取当前时间戳;
5.如果新旧时间戳的差大于或等于一天,执行网络请求(直到点击"DownLoad"为止);
6.点击"DownLoad"直接到 Google Play 官网去下载APK。
实现的步骤:
1.在pubspec.yaml添加sdk
version: 1.0.2+3 #版本名称:1.0.2 版本号:3
dependencies:
...
cupertino_icons: ^0.1.0
package_info: ^0.3.2+1
2.导包
import 'package:package_info/package_info.dart';
3.第一次打开APP时执行"版本更新"的网络请求
class UpdatePagerState extends State<UpdaterPage> {
var _serviceVersionCode,
_serviceVersionName,
_serviceVersionPlatform,
_serviceVersionApp;;
@override
void initState() {
super.initState();
_getNewVersionAPP();
}
//执行版本更新的网络请求
_getNewVersionAPP() async {
DioUtil.getInstance().get(context, url).then((response) {
if (response != null) {
setState(() {
var data = response.data;
_serviceVersionCode = data["versionCode"].toString(); //版本号
_serviceVersionName = data["versionName"].toString(); //版本名称
_serviceVersionPlatform = data["versionPlatform"].toString();//版本平台
_serviceVersionApp = data["versionApp"].toString();//下载的url
_checkVersionCode();
});
}
});
}
}
4.比较服务器的版本号跟当前的版本号,来判断要不要升级APP应用程序
void _checkVersionCode() {
PackageInfo.fromPlatform().then((PackageInfo packageInfo) {
var _currentVersionCode = packageInfo.version;//获取当前的版本号
int serviceVersionCode = int.parse(_serviceVersionCode); //String -> int
int currentVersionCode = int.parse(_currentVersionCode); //String -> int
//如果获取服务器的版本号比当前应用程序的版本号还高,那么提示升级
if (serviceVersionCode > currentVersionCode) {
_showNewVersionAppDialog();//弹出"版本更新"的对话框
}
});
}
5.弹出“版本更新”对话框
Future<void> _showNewVersionAppDialog() async {
if (_serviceVersionPlatform == "android") {
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: new Row(
children: <Widget>[
new Image.asset("images/ic_launcher_icon.png",
height: 35.0, width: 35.0),
new Padding(
padding: const EdgeInsets.fromLTRB(30.0, 0.0, 10.0, 0.0),
child: new Text("项目名称",
style: dialogButtonTextStyle))
],
),
content: new Text(
'版本更新',
style: dialogTextStyle),
actions: <Widget>[
new FlatButton(
child: new Text('Later', style: dialogButtonTextStyle),
onPressed: () {
Navigator.of(context).pop();
},
),
new FlatButton(
child: new Text('DownLoad', style: dialogButtonTextStyle),
onPressed: () {
//https://play.google.com/store/apps/details?id=项目包名
launch(_serviceVersionApp);//到Google Play 官网下载
Navigator.of(context).pop();
},
)
],
);
});
}else{
//iOS
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: new Row(
children: <Widget>[
new Image.asset("images/ic_launcher_icon.png",
height: 35.0, width: 35.0),
new Padding(
padding: const EdgeInsets.fromLTRB(30.0, 0.0, 10.0, 0.0),
child: new Text(Strings.new_version_title,
style: dialogButtonTextStyle))
],
),
content: new Text(
"New version v$_serviceVersionName is available. " +
Strings.new_version_dialog_content,
style: dialogTextStyle),
actions: <Widget>[
new CupertinoDialogAction(
child: new Text(Strings.new_version_button_later,
style: dialogButtonTextStyle),
onPressed: () {
Navigator.of(context).pop();
},
),
new CupertinoDialogAction(
child: new Text(Strings.new_version_button_download,
style: dialogButtonTextStyle),
onPressed: () {
//_serviceVersionApp="http://itunes.apple.com/cn/lookup?id=项目包名"
launch(_serviceVersionApp);//到APP store 官网下载
Navigator.of(context).pop();
},
)
],
);
});
}
}
6.完整的代码
class UpdaterPage extends StatefulWidget {
final Widget child;
const UpdaterPage(this.child);
@override
UpdatePagerState createState() => UpdatePagerState();
}
class UpdatePagerState extends State<UpdaterPage> {
var _serviceVersionCode,
_serviceVersionName,
_serviceVersionPlatform,
_serviceVersionApp;
@override
void initState() {
super.initState();
//每次打开APP获取当前时间戳
var timeEnd = DateTime.now().millisecondsSinceEpoch;
//获取"Later"保存的时间戳
var timeStart = SpUtil.getInt(Constants.timeStart);
if (timeStart == 0) {//第一次打开APP时执行"版本更新"的网络请求
_getNewVersionAPP();
} else if (timeStart != 0 && timeEnd - timeStart >= 24 * 60 * 60 * 1000) {
//如果新旧时间戳的差大于或等于一天,执行网络请求
_getNewVersionAPP();
}
}
//执行版本更新的网络请求
_getNewVersionAPP() async {
DioUtil.getInstance().get(context, url).then((response) {
if (response != null) {
setState(() {
var data = response.data;
_serviceVersionCode = data["versionCode"].toString();//版本号
_serviceVersionName = data["versionName"].toString();//版本名称
_serviceVersionPlatform = data["versionPlatform"].toString();//版本平台
_serviceVersionApp = data["versionApp"].toString();//下载的URL
_checkVersionCode();
});
}
});
}
//检查版本更新的版本号
_checkVersionCode() async {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String _currentVersionCode = packageInfo.version;
int serviceVersionCode = int.parse(_serviceVersionCode); //String -> int
int currentVersionCode = int.parse(_currentVersionCode); //String -> int
if (serviceVersionCode > currentVersionCode) {
_showNewVersionAppDialog();//弹出对话框
}
}
//弹出"版本更新"对话框
Future<void> _showNewVersionAppDialog() async {
if (_serviceVersionPlatform == "android") {
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: new Row(
children: <Widget>[
new Image.asset("images/ic_launcher_icon.png",
height: 35.0, width: 35.0),
new Padding(
padding: const EdgeInsets.fromLTRB(30.0, 0.0, 10.0, 0.0),
child: new Text("项目名称",
style: dialogButtonTextStyle))
],
),
content: new Text(
'版本更新',
style: dialogTextStyle),
actions: <Widget>[
new FlatButton(
child: new Text('Later', style: dialogButtonTextStyle),
onPressed: () {
Navigator.of(context).pop();
var timeStart = DateTime.now().millisecondsSinceEpoch;
DataUtil.saveCurrentTimeMillis(timeStart);//保存当前的时间戳
},
),
new FlatButton(
child: new Text('DownLoad', style: dialogButtonTextStyle),
onPressed: () {
//https://play.google.com/store/apps/details?id=项目包名
launch(_serviceVersionApp);//到Google Play 官网下载
Navigator.of(context).pop();
},
)
],
);
});
}else{
//iOS
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: new Row(
children: <Widget>[
new Image.asset("images/ic_launcher_icon.png",
height: 35.0, width: 35.0),
new Padding(
padding: const EdgeInsets.fromLTRB(30.0, 0.0, 10.0, 0.0),
child: new Text(Strings.new_version_title,
style: dialogButtonTextStyle))
],
),
content: new Text(
"New version v$_serviceVersionName is available. " +
Strings.new_version_dialog_content,
style: dialogTextStyle),
actions: <Widget>[
new CupertinoDialogAction(
child: new Text(Strings.new_version_button_later,
style: dialogButtonTextStyle),
onPressed: () {
Navigator.of(context).pop();
var timeStart = DateTime.now().millisecondsSinceEpoch;
DataUtil.saveCurrentTimeMillis(timeStart);//保存当前的时间戳
},
),
new CupertinoDialogAction(
child: new Text(Strings.new_version_button_download,
style: dialogButtonTextStyle),
onPressed: () {
//_serviceVersionApp="http://itunes.apple.com/cn/lookup?id=项目包名"
launch(_serviceVersionApp);//到APP store 官网下载
Navigator.of(context).pop();
},
)
],
);
});
}
}
@override
Widget build(BuildContext context) => widget.child;
}
7.在首页调用”版本更新”的类
class IndexPage extends StatefulWidget {
@override
IndexPageState createState() => IndexPageState();
}
class IndexPageState extends State<IndexPage>{
@override
Widget build(BuildContext context) {
return UpdaterPage(Scaffold( //调用UpdaterPage
appBar: _buildAppBar(),
body: getScreen()
));
}
}
8.总结
当有新版本需要升级时,客户端会"版本更新"弹出对话框,Android用户跳转到 Google Play 官网去下载APK,而iOS用户跳转到 App Store 官网下载。APP版本更新的功能已经实现,欢迎大家围观。源码地址: https://github.com/wupeilinloveu/flutter_get_new_version