You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中Android即时更新实现及强制更新问题求助

Flutter强制即时更新问题:用户可跳过更新的解决方案

我是Flutter新手,想实现强制即时更新——用户必须更新到新版本才能使用应用,我有Google Play Console权限。了解in_app_update库但不确定用法和是否为最佳实践,目前我的代码能弹出更新弹窗,但用户可以通过返回或关闭按钮跳过更新,试过SystemNavigator.pop()和exit(0)都无效,求解决方法。

以下是我的主页面代码:

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:in_app_update/in_app_update.dart';
import 'package:perhitungan_pkt_kgb/hitung_kgb.dart';
import 'package:perhitungan_pkt_kgb/hitung_pkt.dart';
import 'package:perhitungan_pkt_kgb/tentang.dart';
import 'package:perhitungan_pkt_kgb/utama.dart';

void main() {
  runApp(const MainApp());
}

class MainApp extends StatefulWidget {
  const MainApp({super.key});

  @override
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  @override
  void initState() {
    super.initState();
    checkForUpdate();
  }

  Future<void> checkForUpdate() async {
    print('checking for Update');
    InAppUpdate.checkForUpdate().then((info) {
      setState(() {
        if (info.updateAvailability == UpdateAvailability.updateAvailable) {
          print('update available');
          update();
        }
      });
    }).catchError((e) {
      print(e.toString());
    });
  }

  void update() async {
print('Updating');
await InAppUpdate.performImmediateUpdate();
InAppUpdate.performImmediateUpdate().then((appUpdateResult) {
  if (appUpdateResult == AppUpdateResult.userDeniedUpdate) {
    print('User tried to cancel the update. Exiting...');
    exit(0);
  }
});
}

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Homepage(),
    );
  }
}

class DrawerItem {
  String title;
  IconData icon;
  DrawerItem(this.title, this.icon);
}

class Homepage extends StatefulWidget {
  Homepage({super.key});
  final drawerItems = [
    DrawerItem("Beranda", Icons.home),
    DrawerItem("Hitung 1", Icons.military_tech),
    DrawerItem("Hitung 2", Icons.paid),
    DrawerItem("Tentang", Icons.account_circle),
  ];
  @override
  State<Homepage> createState() => _HomepageState();
}

class _HomepageState extends State<Homepage> {
  int _selectedDrawerIndex = 0;

  _getDrawerItemWidget(int pos) {
    switch (pos) {
      case 0:
        return Utama();
      case 1:
        return HitungPkt();
      case 2:
        return HitungKgb();
      case 3:
        return Tentang();

      default:
        return Text("Error");
    }
  }

  _onSelectItem(int index) {
    setState(() => _selectedDrawerIndex = index);
    Navigator.of(context).pop(); // close the drawer
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> drawerOptions = [];
    for (var i = 0; i < widget.drawerItems.length; i++) {
      var d = widget.drawerItems[i];
      drawerOptions.add(ListTile(
        leading: Icon(d.icon),
        title: Text(d.title),
        selected: i == _selectedDrawerIndex,
        onTap: () => _onSelectItem(i),
      ));
    }

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.drawerItems[_selectedDrawerIndex].title),
      ),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: <Widget>[
            SizedBox(
              height: 150,
              child: const DrawerHeader(
                decoration: BoxDecoration(color: Colors.blue),
                child: Text('Menu',
                    style: TextStyle(color: Colors.white, fontSize: 24)),
              ),
            ),
            Column(children: drawerOptions)
          ],
        ),
      ),
      body: _getDrawerItemWidget(_selectedDrawerIndex),
      bottomNavigationBar: Container(
        height: 25.0,
        color: Colors.grey[200],
        child: Text(
          'Copyright © ISSYAM 2025',
          textAlign: TextAlign.center,
          style: TextStyle(fontSize: 14.0),
        ),
      ),
    );
  }
}

更新说明
更新弹窗已成功弹出,但用户可以通过返回按钮或关闭按钮跳过更新。当用户进行此操作时,我该如何让应用关闭或始终弹出更新提示?我已经尝试使用SystemNavigator.pop();或exit(0);但仍无效。

更新弹窗截图


问题分析与解决方案

1. 修复performImmediateUpdate调用逻辑

你当前代码重复调用了performImmediateUpdate,导致逻辑混乱。正确做法是单次调用并根据返回结果处理:

void update() async {
  print('Updating');
  final result = await InAppUpdate.performImmediateUpdate();
  switch(result) {
    case AppUpdateResult.userDeniedUpdate:
      // 用户拒绝更新,强制终止应用
      exit(0);
    case AppUpdateResult.inAppUpdateFailed:
      // 更新失败,可选择重试检查或直接退出
      checkForUpdate();
      // exit(0);
    case AppUpdateResult.success:
      // 更新成功,应用会自动重启,无需额外处理
      break;
  }
}

2. 确保Google Play配置与库版本

  • 确认新版本已在Google Play Console发布(内部测试/公开测试/正式渠道均可)
  • 确保in_app_update库为最新版本,在pubspec.yaml中更新:
    dependencies:
      in_app_update: ^4.1.0 # 替换为当前最新版本
    

3. 自定义强制更新弹窗(兜底方案)

如果原生即时更新弹窗无法阻止用户跳过,可显示全屏自定义弹窗,禁止用户操作其他界面:

Future<void> checkForUpdate() async {
  print('checking for Update');
  try {
    final info = await InAppUpdate.checkForUpdate();
    if (info.updateAvailability == UpdateAvailability.updateAvailable) {
      print('update available');
      showDialog(
        context: context,
        barrierDismissible: false, // 禁止点击外部关闭弹窗
        builder: (context) => AlertDialog(
          title: const Text("必须更新"),
          content: const Text("应用有重要更新,请立即更新后使用"),
          actions: [
            TextButton(
              onPressed: () async {
                await InAppUpdate.performImmediateUpdate();
              },
              child: const Text("立即更新"),
            ),
          ],
        ),
      );
    }
  } catch(e) {
    print(e.toString());
  }
}

4. 关于exit(0)无效的说明

  • 确保已导入dart:io(你的代码已满足)
  • Android上exit(0)会直接终止进程;iOS上需注意审核规则,强制退出可能违反条款,建议iOS端仅引导更新而非强制关闭

内容的提问来源于stack exchange,提问作者Dreamer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 04:19:58