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

Flutter发布模式白屏求助:关联SharedPreferences与Kotlin通知代码

Flutter Release模式启动白屏/停在闪屏,Debug模式正常(添加Kotlin本地通知代码后触发)

问题描述

Debug模式下应用运行完全正常,但切换到Release模式后,启动时要么显示白屏,要么卡在闪屏页面,无法进行导航和交互。这个问题是在添加了用于发送、设置本地通知的Kotlin代码后出现的,而且Debug模式没有明显报错,定位问题很困难。

应用必须依赖初始化的Services才能正常运行,如果取消初始化Services,应用虽然能启动,但界面处于实验性状态,无法正常使用。


相关代码

主入口代码(main.dart)

import 'package:al_muezzin/bindings/initialbindings.dart';
import 'package:al_muezzin/core/constant/color.dart';
import 'package:al_muezzin/core/localization/translation.dart';
import 'package:al_muezzin/core/service/services.dart';
import 'package:al_muezzin/route.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:timeago/timeago.dart' as timeago;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await initialServices();
  timeago.setLocaleMessages('ar', timeago.ArMessages());
  runApp(const MyApp());
}

final MethodChannel _channel = MethodChannel('com.example.al_muezzin/AlarmManagement');

Future<void> setNextAlarm() async {
  try {
    await _channel.invokeMethod('setNextAlarm');
  } on PlatformException catch (e) {
    Fluttertoast.showToast(msg: 'Failed to set alarm: ${e.message}');
  }
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        fontFamily: 'AL-JAZEERA',
        appBarTheme: AppBarTheme(
          backgroundColor: AppColor.secondColor
        ),
        scaffoldBackgroundColor: Color(0xffF2F2F2),
      ),
      locale: Locale('ar'),
      translations: MyTranslation(),
      initialBinding: InitialBindings(),
      getPages: getPages,
    );
  }
}

服务初始化代码(services.dart)

import 'package:al_muezzin/core/function/print.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';

class MyServices extends GetxService {
  late SharedPreferences sharedPreferences;

  Future<MyServices> init() async {
    sharedPreferences = await SharedPreferences.getInstance();
    return this;
  }
}

initialServices() async {
  await Get.putAsync(() => MyServices().init());
}

排查与解决方案

1. 优先排查Kotlin原生代码的Release兼容性

问题是添加Kotlin通知代码后出现的,先从原生层入手:

  • 检查Kotlin代码中是否有仅Debug模式生效的逻辑(比如依赖调试日志、测试权限),Release模式下这些逻辑失效会导致阻塞。
  • 确认MethodChannel注册是否正确:确保在Android的MainActivity或自定义Application类中,正确注册了com.example.al_muezzin/AlarmManagement通道,Release模式下通道未注册会导致方法调用阻塞,卡住初始化流程。
  • 检查通知权限申请逻辑:Release模式下权限策略更严格,若权限申请失败且未做异常处理,会导致后续代码阻塞。可以在初始化Services前主动申请POST_NOTIFICATIONS权限,确保权限获取成功后再执行后续操作。

2. 排查Release模式下的初始化阻塞

应用依赖initialServices()完成初始化,Release模式下该方法可能因异常卡住:

  • 给初始化方法添加错误捕获与日志输出:
    initialServices() async {
      try {
        await Get.putAsync(() => MyServices().init());
        print('Services initialized successfully');
      } catch (e) {
        print('Services init failed: $e');
      }
    }
    
    用flutter run --release启动应用,通过adb logcat查看原生日志,定位初始化过程中的异常。
  • 检查SharedPreferences初始化:部分设备在Release模式下,SharedPreferences.getInstance()可能因存储权限问题卡住,需确保应用已获取对应存储权限(targetSdk >=33时需额外处理)。

3. 检查Flutter Release编译配置

  • 防止MethodChannel被混淆:在android/app/proguard-rules.pro中添加规则,保护通道名称不被混淆:
    -keep class io.flutter.plugin.common.MethodChannel { *; }
    -keep class io.flutter.plugin.common.MethodChannel$MethodCallHandler { *; }
    -keep class com.example.al_muezzin.AlarmManagement { *; } // 替换为你的通道相关类
    
  • 检查R8优化:若Kotlin通知代码被R8误删,会导致方法调用失败进而卡住应用,可暂时关闭R8测试是否恢复正常。

4. 验证闪屏与导航逻辑

  • 添加初始化超时处理:防止初始化卡住导致应用无法启动:
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      // 超时处理,避免初始化无限阻塞
      await initialServices().timeout(Duration(seconds: 5), onTimeout: () {
        print('Services init timed out');
      });
      timeago.setLocaleMessages('ar', timeago.ArMessages());
      runApp(const MyApp());
    }
    
  • 检查InitialBindings逻辑:若InitialBindings依赖未初始化完成的服务,Release模式下异步顺序问题可能导致页面无法加载。

5. 最小化复现测试

  • 暂时移除Kotlin通知相关代码,重新打包Release版本,若应用恢复正常,说明问题出在原生通知代码中,再逐步添加代码定位具体出错点。
  • 单独测试MethodChannel调用:先不调用setNextAlarm,看Release模式下应用能否正常启动,再逐步加入该方法排查是否是调用导致的阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 20:21:04