flutter_chen_updater 1.2.0
flutter_chen_updater: ^1.2.0 copied to clipboard
A comprehensive Flutter app update library supporting background downloads and iOS App Store redirects.
import 'package:flutter/material.dart';
import 'package:flutter_chen_updater/flutter_chen_updater.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Chen Updater Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String currentVersion = '1.0.0';
bool isLoading = false;
String statusMessage = '';
@override
void initState() {
super.initState();
_getAppVersion();
}
Future<void> _getAppVersion() async {
try {
final version = await NativePluginHelper.getAppVersion();
if (mounted) {
setState(() {
currentVersion = version ?? '1.0.0';
});
}
} catch (e) {
if (mounted) {
setState(() {
statusMessage = '获取版本失败: $e';
});
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Chen Updater Demo'),
centerTitle: true,
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
// 版本信息卡片
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'应用信息',
style:
TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
Row(
children: [
const Icon(Icons.info_outline, size: 20),
const SizedBox(width: 8),
Text('当前版本: $currentVersion'),
],
),
if (statusMessage.isNotEmpty) ...[
const SizedBox(height: 8),
Row(
children: [
const Icon(Icons.warning_amber_outlined,
size: 20, color: Colors.orange),
const SizedBox(width: 8),
Expanded(
child: Text(statusMessage,
style:
const TextStyle(color: Colors.orange))),
],
),
],
],
),
),
),
const SizedBox(height: 24),
// 更新按钮组
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: double.infinity,
height: 48,
child: ElevatedButton.icon(
onPressed: isLoading ? null : () => _checkUpdate(false),
label: Text(isLoading ? '检查中...' : '检查更新'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
),
),
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
height: 48,
child: ElevatedButton.icon(
onPressed: isLoading ? null : () => _checkUpdate(true),
label: Text(isLoading ? '检查中...' : '检查强制更新'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.white,
),
),
),
const SizedBox(height: 32),
// 功能说明
const Card(
child: Padding(
padding: EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'功能说明:',
style: TextStyle(fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Text('• 检查更新: 用户可以选择取消更新'),
Text('• 检查强制更新: 用户无法取消,必须更新'),
Text('• 支持 Android APK 和 iOS App Store'),
Text('• 自动处理权限和文件校验'),
],
),
),
),
],
),
),
],
),
),
);
}
Future<void> _checkUpdate(bool isForceUpdate) async {
if (isLoading) return;
setState(() {
isLoading = true;
statusMessage = '';
});
try {
// 模拟从服务器获取更新信息
final updateInfo = UpdateInfo(
version: '1.2.0',
downloadUrl: 'https://er-dong-chen.github.io/assets/app-debug.apk',
iosUrl: 'https://apps.apple.com/app/id123456789',
description: '''新版本更新内容:
• 修复已知问题
• 优化用户体验
• 新增功能特性
• 提升应用性能
• 增强安全性''',
isForceUpdate: isForceUpdate,
fileHash: null, // 在生产环境中应该提供文件哈希
hashAlgorithm: 'md5',
fileSize: 15 * 1024 * 1024, // 15MB
);
await Updater.checkAndUpdate(
context,
updateInfo,
dialogBuilder: (context, updateInfo) async {
return await showDialog(
context: context,
builder: (_) {
return UpdateDialog(
updateInfo: updateInfo,
);
});
},
onProgress: (progress) {
// 下载进度回调
final percent = (progress.progress * 100).toStringAsFixed(1);
setState(() {
statusMessage =
'下载进度: $percent% (${_formatBytes(progress.downloaded)}/${_formatBytes(progress.total)})';
});
},
onAlreadyLatest: () {
setState(() {
statusMessage = '🎉 当前已是最新版本!';
});
_showSnackBar('当前已是最新版本', Colors.green);
},
onConfirm: () {
setState(() {
statusMessage = '开始下载更新...';
});
_showSnackBar('开始下载更新', Colors.blue);
},
onCancel: () {
setState(() {
statusMessage = '用户取消了更新';
});
_showSnackBar('已取消更新', Colors.orange);
},
);
} catch (e) {
setState(() {
statusMessage = '检查更新失败: $e';
});
_showSnackBar('检查更新失败', Colors.red);
} finally {
if (mounted) {
setState(() {
isLoading = false;
});
}
}
}
String _formatBytes(int bytes) {
if (bytes == 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
final i = (bytes.bitLength - 1) ~/ 10;
return '${(bytes / (k * i)).toStringAsFixed(1)} ${sizes[i]}';
}
void _showSnackBar(String message, Color color) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: color,
behavior: SnackBarBehavior.floating,
margin: const EdgeInsets.all(16),
duration: const Duration(seconds: 3),
),
);
}
@override
void dispose() {
// 清理更新器资源
Updater.dispose();
super.dispose();
}
}