import 'dart:async'; import 'package:app_upgrade_plugin/app_upgrade_plugin_enhanced.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; void main() { runApp(const MyEnhancedApp()); } class MyEnhancedApp extends StatelessWidget { const MyEnhancedApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: '增强版App升级插件示例', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const EnhancedUpgradePage(), ); } } class EnhancedUpgradePage extends StatefulWidget { const EnhancedUpgradePage({super.key}); @override State createState() => _EnhancedUpgradePageState(); } class _EnhancedUpgradePageState extends State with SingleTickerProviderStateMixin { final _plugin = AppUpgradePluginEnhanced.instance; late TabController _tabController; // 状态变量 Map? _appInfo; NetworkStatus? _networkStatus; DownloadTask? _currentDownload; UpgradeInfo? _upgradeInfo; Map? _cacheStats; // 配置选项 bool _wifiOnly = true; bool _autoCheck = true; bool _supportBreakpoint = true; bool _verifyIntegrity = true; VersionCompareStrategy _versionStrategy = VersionCompareStrategy.semantic; // 测试数据 final _testVersions = ['1.0.0', '1.1.0', '1.2.0', '2.0.0-beta.1', '2.0.0']; String _currentTestVersion = '1.0.0'; String _remoteTestVersion = '2.0.0'; @override void initState() { super.initState(); _tabController = TabController(length: 4, vsync: this); _initPlugin(); _loadData(); } @override void dispose() { _tabController.dispose(); _plugin.removeUpgradeCallback(_onUpgradeInfo); _plugin.removeDownloadCallback(_onDownloadProgress); _plugin.removeErrorCallback(_onError); super.dispose(); } void _initPlugin() { // 配置插件 _plugin.configure( debugMode: true, autoCheck: _autoCheck, wifiOnly: _wifiOnly, supportBreakpoint: _supportBreakpoint, verifyIntegrity: _verifyIntegrity, versionStrategy: _versionStrategy, ); // 添加回调 _plugin.addUpgradeCallback(_onUpgradeInfo); _plugin.addDownloadCallback(_onDownloadProgress); _plugin.addErrorCallback(_onError); // 监听网络状态 NetworkMonitor.instance.statusStream.listen((status) { setState(() { _networkStatus = status; }); }); } Future _loadData() async { // 请求权限 await _requestPermissions(); // 获取App信息 _appInfo = await _plugin.getAppInfo(); // 获取网络状态 _networkStatus = _plugin.networkStatus; // 获取缓存统计 _cacheStats = await _plugin.getCacheStats(); setState(() {}); } Future _requestPermissions() async { if (Theme.of(context).platform == TargetPlatform.android) { await [ Permission.storage, Permission.requestInstallPackages, Permission.notification, ].request(); } } void _onUpgradeInfo(UpgradeInfo info) { setState(() { _upgradeInfo = info; }); // 显示升级对话框 UpgradeDialog.show( context, upgradeInfo: info, primaryColor: Theme.of(context).colorScheme.primary, ); } void _onDownloadProgress(DownloadTask task) { setState(() { _currentDownload = task; }); } void _onError(String error) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(error), backgroundColor: Colors.red, ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('增强版App升级插件'), backgroundColor: Theme.of(context).colorScheme.inversePrimary, bottom: TabBar( controller: _tabController, tabs: const [ Tab(text: '基础功能'), Tab(text: '高级配置'), Tab(text: '网络监测'), Tab(text: '版本管理'), ], ), ), body: TabBarView( controller: _tabController, children: [ _buildBasicTab(), _buildConfigTab(), _buildNetworkTab(), _buildVersionTab(), ], ), ); } // 基础功能标签页 Widget _buildBasicTab() { return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // App信息卡片 if (_appInfo != null) Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'App信息', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 12), Text('应用名称: ${_appInfo!['appName']}'), Text('包名: ${_appInfo!['packageName']}'), Text('版本: ${_appInfo!['version']}'), Text('构建号: ${_appInfo!['buildNumber']}'), ], ), ), ), const SizedBox(height: 16), // 升级信息卡片 if (_upgradeInfo != null) Card( color: Colors.amber.shade50, child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.system_update, color: Colors.amber), const SizedBox(width: 8), const Text( '发现新版本', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), ], ), const SizedBox(height: 12), Text('版本: ${_upgradeInfo!.versionName}'), Text('强制更新: ${_upgradeInfo!.isForceUpdate ? "是" : "否"}'), if (_upgradeInfo!.apkSize != null) Text('大小: ${_formatBytes(_upgradeInfo!.apkSize!)}'), ], ), ), ), const SizedBox(height: 16), // 下载进度卡片 if (_currentDownload != null) Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '下载进度', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 12), LinearProgressIndicator(value: _currentDownload!.progress), const SizedBox(height: 8), Text('状态: ${_getDownloadStatusText(_currentDownload!.status)}'), Text('进度: ${(_currentDownload!.progress * 100).toStringAsFixed(1)}%'), if (_currentDownload!.totalSize != null) Text( '${_formatBytes(_currentDownload!.downloadedSize)} / ${_formatBytes(_currentDownload!.totalSize!)}'), if (_currentDownload!.errorMessage != null) Text('错误: ${_currentDownload!.errorMessage}', style: const TextStyle(color: Colors.red)), ], ), ), ), const SizedBox(height: 16), // 操作按钮 Wrap( spacing: 8, runSpacing: 8, children: [ ElevatedButton.icon( onPressed: () => _checkUpdate(), icon: const Icon(Icons.refresh), label: const Text('检查更新'), ), if (_currentDownload != null) ...[ if (_currentDownload!.status == DownloadStatus.downloading) ElevatedButton.icon( onPressed: () => _plugin.pauseDownload(), icon: const Icon(Icons.pause), label: const Text('暂停'), ), if (_currentDownload!.status == DownloadStatus.paused) ElevatedButton.icon( onPressed: () => _plugin.resumeDownload(), icon: const Icon(Icons.play_arrow), label: const Text('继续'), ), if (_currentDownload!.status == DownloadStatus.failed) ElevatedButton.icon( onPressed: () => _plugin.retryDownload(), icon: const Icon(Icons.replay), label: const Text('重试'), ), OutlinedButton.icon( onPressed: () => _plugin.cancelDownload(), icon: const Icon(Icons.cancel), label: const Text('取消'), ), ], ], ), ], ), ); } // 高级配置标签页 Widget _buildConfigTab() { return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '升级配置', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), const SizedBox(height: 16), SwitchListTile( title: const Text('仅WiFi下载'), subtitle: const Text('只在WiFi环境下自动下载更新'), value: _wifiOnly, onChanged: (value) { setState(() { _wifiOnly = value; }); _plugin.configure(wifiOnly: value); }, ), SwitchListTile( title: const Text('自动检查更新'), subtitle: const Text('定期自动检查是否有新版本'), value: _autoCheck, onChanged: (value) { setState(() { _autoCheck = value; }); _plugin.configure(autoCheck: value); }, ), SwitchListTile( title: const Text('断点续传'), subtitle: const Text('支持暂停后继续下载'), value: _supportBreakpoint, onChanged: (value) { setState(() { _supportBreakpoint = value; }); _plugin.configure(supportBreakpoint: value); }, ), SwitchListTile( title: const Text('文件校验'), subtitle: const Text('下载完成后校验文件完整性'), value: _verifyIntegrity, onChanged: (value) { setState(() { _verifyIntegrity = value; }); _plugin.configure(verifyIntegrity: value); }, ), const Divider(), ListTile( title: const Text('版本比较策略'), subtitle: Text(_getVersionStrategyText(_versionStrategy)), trailing: DropdownButton( value: _versionStrategy, onChanged: (value) { if (value != null) { setState(() { _versionStrategy = value; }); _plugin.configure(versionStrategy: value); } }, items: VersionCompareStrategy.values.map((strategy) { return DropdownMenuItem( value: strategy, child: Text(_getVersionStrategyText(strategy)), ); }).toList(), ), ), const Divider(), // 缓存管理 Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '缓存管理', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 12), if (_cacheStats != null) ...[ Text( '内存缓存: ${_cacheStats!['memoryCache']['sizeFormatted']} (${_cacheStats!['memoryCache']['count']}项)'), Text( '磁盘缓存: ${_cacheStats!['diskCache']['sizeFormatted']} (${_cacheStats!['diskCache']['count']}项)'), Text('总计: ${_cacheStats!['total']['sizeFormatted']} (${_cacheStats!['total']['count']}项)'), ], const SizedBox(height: 12), Row( children: [ ElevatedButton( onPressed: () async { _cacheStats = await _plugin.getCacheStats(); setState(() {}); }, child: const Text('刷新'), ), const SizedBox(width: 8), OutlinedButton( onPressed: () async { await _plugin.clearCache(); _cacheStats = await _plugin.getCacheStats(); if (mounted) { setState(() {}); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('缓存已清空')), ); } }, child: const Text('清空缓存'), ), ], ), ], ), ), ), ], ), ); } // 网络监测标签页 Widget _buildNetworkTab() { return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '网络状态', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), const SizedBox(height: 16), if (_networkStatus != null) ...[ Card( color: _networkStatus!.isConnected ? Colors.green.shade50 : Colors.red.shade50, child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon( _networkStatus!.isConnected ? Icons.wifi : Icons.wifi_off, color: _networkStatus!.isConnected ? Colors.green : Colors.red, ), const SizedBox(width: 8), Text( _networkStatus!.isConnected ? '已连接' : '未连接', style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), ], ), const SizedBox(height: 12), Text('网络类型: ${_getNetworkTypeText(_networkStatus!.type)}'), Text('网络质量: ${_getNetworkQualityText(_networkStatus!.quality)}'), Text('计费网络: ${_networkStatus!.isMetered ? "是" : "否"}'), if (_networkStatus!.downloadSpeed != null) Text('下载速度: ${_formatBytes(_networkStatus!.downloadSpeed!.toInt())}/s'), if (_networkStatus!.ping != null) Text('延迟: ${_networkStatus!.ping} ms'), const SizedBox(height: 12), Text( '适合大文件下载: ${_networkStatus!.isSuitableForLargeDownload ? "是" : "否"}', style: TextStyle( color: _networkStatus!.isSuitableForLargeDownload ? Colors.green : Colors.orange, fontWeight: FontWeight.bold, ), ), ], ), ), ), const SizedBox(height: 16), // 下载策略建议 Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '下载策略建议', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 12), ...NetworkMonitor.instance.getSuggestedDownloadStrategy().entries.map((e) { return Text('${e.key}: ${e.value}'); }), ], ), ), ), ] else const Center(child: CircularProgressIndicator()), ], ), ); } // 版本管理标签页 Widget _buildVersionTab() { final comparator = _plugin.versionComparator; return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '版本比较测试', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), const SizedBox(height: 16), // 版本选择 Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('当前版本:'), DropdownButton( value: _currentTestVersion, isExpanded: true, onChanged: (value) { setState(() { _currentTestVersion = value!; }); }, items: _testVersions.map((v) { return DropdownMenuItem(value: v, child: Text(v)); }).toList(), ), ], ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('远程版本:'), DropdownButton( value: _remoteTestVersion, isExpanded: true, onChanged: (value) { setState(() { _remoteTestVersion = value!; }); }, items: _testVersions.map((v) { return DropdownMenuItem(value: v, child: Text(v)); }).toList(), ), ], ), ), ], ), const SizedBox(height: 16), // 比较结果 Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '比较结果', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 12), Text('需要更新: ${comparator.isUpdateAvailable(_currentTestVersion, _remoteTestVersion) ? "是" : "否"}'), Text('更新类型: ${comparator.getVersionDifference(_currentTestVersion, _remoteTestVersion)}'), Text('主要版本更新: ${comparator.isMajorUpdate(_currentTestVersion, _remoteTestVersion) ? "是" : "否"}'), Text('次要版本更新: ${comparator.isMinorUpdate(_currentTestVersion, _remoteTestVersion) ? "是" : "否"}'), Text('修订版本更新: ${comparator.isPatchUpdate(_currentTestVersion, _remoteTestVersion) ? "是" : "否"}'), ], ), ), ), const SizedBox(height: 16), // 版本列表排序 Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '版本排序', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 12), Text('升序: ${comparator.sortVersions(_testVersions).join(', ')}'), Text('降序: ${comparator.sortVersions(_testVersions, descending: true).join(', ')}'), Text('最新版本: ${comparator.getLatestVersion(_testVersions)}'), ], ), ), ), ], ), ); } // 检查更新 Future _checkUpdate() async { // 模拟服务器地址 const url = 'https://api.example.com/check-update'; final info = await _plugin.checkUpdateSmart( url, forceRefresh: true, cacheDuration: const Duration(hours: 1), ); if (info == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('已是最新版本')), ); } } // 工具方法 String _formatBytes(int bytes) { if (bytes < 1024) return '$bytes B'; if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(2)} KB'; if (bytes < 1024 * 1024 * 1024) return '${(bytes / (1024 * 1024)).toStringAsFixed(2)} MB'; return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(2)} GB'; } String _getDownloadStatusText(DownloadStatus status) { switch (status) { case DownloadStatus.pending: return '等待中'; case DownloadStatus.downloading: return '下载中'; case DownloadStatus.paused: return '已暂停'; case DownloadStatus.completed: return '已完成'; case DownloadStatus.failed: return '失败'; case DownloadStatus.cancelled: return '已取消'; } } String _getNetworkTypeText(NetworkType type) { switch (type) { case NetworkType.none: return '无网络'; case NetworkType.mobile: return '移动网络'; case NetworkType.wifi: return 'WiFi'; case NetworkType.ethernet: return '以太网'; case NetworkType.bluetooth: return '蓝牙'; case NetworkType.vpn: return 'VPN'; case NetworkType.other: return '其他'; } } String _getNetworkQualityText(NetworkQuality quality) { switch (quality) { case NetworkQuality.unknown: return '未知'; case NetworkQuality.poor: return '差'; case NetworkQuality.moderate: return '中等'; case NetworkQuality.good: return '良好'; case NetworkQuality.excellent: return '优秀'; } } String _getVersionStrategyText(VersionCompareStrategy strategy) { switch (strategy) { case VersionCompareStrategy.numeric: return '数字比较'; case VersionCompareStrategy.semantic: return '语义化版本'; case VersionCompareStrategy.timestamp: return '时间戳'; case VersionCompareStrategy.buildNumber: return '构建号'; case VersionCompareStrategy.custom: return '自定义'; } } }