When I open the app everything works fine but when i close it and reopen it from the home screen it crashes on TestFlight.
Here's the crash log of the thread its crashing on:
Thread 0 name:
Thread 0 Crashed:
0 libswiftCore.dylib 0x00000001847363fc _assertionFailure(_:_:file:line:flags:) + 264 (AssertCommon.swift:144)
1 PurchasesHybridCommon 0x00000001019af1a4 closure #1 in variable initialization expression of static FatalErrorUtil.defaultFatalErrorClosure + 64 (FatalErrorUtil.swift:15)
2 PurchasesHybridCommon 0x00000001019a73a0 fatalError(_:file:line:) + 60 (FatalErrorUtil.swift:27)
3 PurchasesHybridCommon 0x00000001019a73a0 static CommonFunctionality.sharedInstance.getter + 84 (CommonFunctionality.swift:21)
4 PurchasesHybridCommon 0x00000001019a73a0 static CommonFunctionality.customerInfo(fetchPolicy:completion:) + 84 (<compiler-generated>:405)
5 PurchasesHybridCommon 0x00000001019a73a0 specialized static CommonFunctionality.customerInfo(completion:) + 372 (CommonFunctionality.swift:398)
6 PurchasesHybridCommon 0x00000001019a3964 @objc static CommonFunctionality.restorePurchases(completion:) + 76
7 purchases_flutter 0x0000000102cf5f2c -[PurchasesFlutterPlugin getCustomerInfoWithResult:] + 48 (PurchasesFlutterPlugin.m:347)
8 purchases_flutter 0x0000000102cf493c -[PurchasesFlutterPlugin handleMethodCall:result:] + 2048 (PurchasesFlutterPlugin.m:100)
9 Flutter 0x000000010342196c 0x102e40000 + 6166892
10 Flutter 0x0000000102e83c00 0x102e40000 + 277504
11 libdispatch.dylib 0x00000001933106a8 _dispatch_call_block_and_release + 32 (init.c:1530)
12 libdispatch.dylib 0x0000000193312300 _dispatch_client_callout + 20 (object.m:561)
13 libdispatch.dylib 0x0000000193320998 _dispatch_main_queue_drain + 984 (queue.c:7813)
14 libdispatch.dylib 0x00000001933205b0 _dispatch_main_queue_callback_4CF + 44 (queue.c:7973)
15 CoreFoundation 0x000000018b34cf9c __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16 (CFRunLoop.c:1780)
16 CoreFoundation 0x000000018b349ca8 __CFRunLoopRun + 1996 (CFRunLoop.c:3149)
17 CoreFoundation 0x000000018b3493f8 CFRunLoopRunSpecific + 608 (CFRunLoop.c:3420)
18 GraphicsServices 0x00000001ce8d74f8 GSEventRunModal + 164 (GSEvent.c:2196)
19 UIKitCore 0x000000018d76f8a0 -[UIApplication _run] + 888 (UIApplication.m:3685)
20 UIKitCore 0x000000018d76eedc UIApplicationMain + 340 (UIApplication.m:5270)
21 Runner 0x000000010030877c main + 64 (AppDelegate.swift:7)
22 dyld 0x00000001ae09edcc start + 2240 (dyldMain.cpp:1269)
this is my main.dart code:
import 'dart:io';
import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:presentpal/api/constants.dart';
import 'package:presentpal/api/firebase_api.dart';
import 'package:presentpal/api/purchases_api.dart';
import 'package:presentpal/pages/gift_chose.dart';
import 'package:presentpal/pages/home.dart';
import 'package:presentpal/provider/locale_provider.dart';
import 'package:presentpal/services/analytics_service.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'provider/theme_provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'services/preferences_service.dart';
import 'pages/change_notifier.dart' as presentpal;
import 'package:provider/provider.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'pages/onboarding.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'store_config.dart';
import 'package:purchases_flutter/purchases_flutter.dart';
import 'package:presentpal/services/set_notifications.dart';
import 'package:timezone/data/latest.dart' as tz;
final navigatorKey = GlobalKey<NavigatorState>();
Future<void> configureLocalTimeZone() async {
tz.initializeTimeZones();
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
presentpal.AppState appState = presentpal.AppState();
try {
MobileAds.instance.initialize();
//get user data
await Firebase.initializeApp();
FlutterError.onError = (errorDetails) {
FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
};
await FirebaseApi().initNotifications();
await setNotifications.initializeNotifications();
await configureLocalTimeZone();
String? initialLocale = await getLocale();
if (initialLocale != null && initialLocale.isNotEmpty) {
appState.setLocale(initialLocale);
}
try {
await dotenv.load(fileName: ".env");
} catch (e) {
print(e.toString());
}
if (Platform.isIOS) {
StoreConfig(
store: Store.appStore,
apiKey: appleApiKey,
);
} else if (Platform.isAndroid) {
StoreConfig(
store: Store.playStore,
apiKey: googleApiKey,
);
}
await PurchaseApi.init();
} catch (e) {
print(e.toString());
AnalyticsService analyticsService = AnalyticsService();
analyticsService.logEvent('error: ${e.toString()}');
}
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => LocaleModel()),
],
child: MyApp(appState: appState),
),
);
}
class MyApp extends StatefulWidget {
final presentpal.AppState appState;
const MyApp({super.key, required this.appState});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool hasSeenOnboarding = false;
@override
void initState() {
super.initState();
_populateFields();
checkOnboardingStatus();
AwesomeNotifications().isNotificationAllowed().then((isAllowed) {
if (!isAllowed) {
AwesomeNotifications().requestPermissionToSendNotifications();
}
});
}
Future<void> checkOnboardingStatus() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final bool seenOnboarding = prefs.getBool('hasSeenOnboarding') ?? false;
setState(() {
hasSeenOnboarding = seenOnboarding;
});
}
final _preferenceServices = PreferencesService();
String selectedLanguage = 'en';
void _populateFields() async {
final settings = await _preferenceServices.getSettings();
String? storedLanguage = settings.languageCode;
if (storedLanguage.isNotEmpty) {
setState(() {
selectedLanguage = storedLanguage;
});
widget.appState.setLocale(selectedLanguage);
} else {
String languageCode;
try {
//get locale from settings
Locale userLocale = WidgetsBinding.instance.window.locale;
languageCode = userLocale.languageCode;
if ([
'en',
'ar',
'bn',
'de',
'es',
'fr',
'hi',
'it',
'ko',
'pt',
'ru',
'zh',
'zh_HK'
].contains(languageCode)) {
setState(() {
selectedLanguage = languageCode;
});
widget.appState.setLocale(selectedLanguage);
}
} catch (e) {
languageCode = 'en';
}
}
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => LocaleProvider(),
builder: (context, child) {
final provider = Provider.of<LocaleProvider>(context);
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'PresentPal',
themeMode: ThemeMode.system,
theme: MyThemes.lightTheme,
navigatorObservers: [AnalyticsService().getAnalyticsObserver()],
navigatorKey: navigatorKey,
locale: provider.locale,
supportedLocales: const [
Locale('en'), // English
Locale('ar'), //Arabic
Locale('bn'), //Bengali
Locale('de'), //German
Locale('es'), //Spanish
Locale('fr'), //French
Locale('hi'), //Hindi
Locale('it'), //Italian
Locale('ko'), //Korean
Locale('pt'), //Portuguese
Locale('ru'), //Russian
Locale('zh'), //Chinese
Locale('zh_HK') //Chinese (Hong Kong)
],
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
darkTheme: MyThemes.darkTheme,
routes: {
'/home': (context) => const HomePage(),
'/onboarding': (context) => const OnboardingScreen(),
'/giftChoose': (context) => const GiftChoose(),
},
home:
hasSeenOnboarding ? const HomePage() : const OnboardingScreen(),
);
}
);
}
}
Future<void> setLocale(String languageCode) async {
final SharedPreferences preferences = await SharedPreferences.getInstance();
preferences.setString('languageCode', languageCode);
}
Future<String?> getLocale() async {
WidgetsFlutterBinding.ensureInitialized();
final SharedPreferences preferences = await SharedPreferences.getInstance();
return preferences.getString('languageCode');
}
class LocaleModel extends ChangeNotifier {
Locale? _locale;
Locale? get locale => _locale;
void set(Locale locale) {
_locale = locale;
notifyListeners();
}
}