flutter_chen_updater 1.0.0 copy "flutter_chen_updater: ^1.0.0" to clipboard
flutter_chen_updater: ^1.0.0 copied to clipboard

A comprehensive Flutter app update library supporting background downloads and iOS App Store redirects.

example/lib/main.dart

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://d3165xrbgac637.cloudfront.net/AstroX.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();
  }
}
2
likes
0
points
351
downloads

Publisher

unverified uploader

Weekly Downloads

A comprehensive Flutter app update library supporting background downloads and iOS App Store redirects.

Repository (GitHub)
View/report issues

Topics

#updater

License

unknown (license)

Dependencies

crypto, flutter, path_provider, permission_handler, url_launcher

More

Packages that depend on flutter_chen_updater