add sentry
This commit is contained in:
121
lib/main.dart
121
lib/main.dart
@@ -1,17 +1,17 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:onesignal_flutter/onesignal_flutter.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'package:worker/app.dart';
|
||||
import 'package:worker/core/database/app_settings_box.dart';
|
||||
import 'package:worker/core/database/hive_initializer.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'firebase_options.dart';
|
||||
import 'package:worker/core/services/onesignal_service.dart';
|
||||
import 'package:worker/core/services/sentry_service.dart';
|
||||
import 'package:worker/firebase_options.dart';
|
||||
|
||||
/// Main entry point of the Worker Mobile App
|
||||
///
|
||||
@@ -45,72 +45,35 @@ void main() async {
|
||||
|
||||
/// Initialize all app dependencies with comprehensive error handling
|
||||
Future<void> _initializeApp() async {
|
||||
// Set up error handlers before anything else
|
||||
_setupErrorHandlers();
|
||||
// Initialize Sentry first to capture any initialization errors
|
||||
// Sentry wraps the app runner to capture errors during startup
|
||||
await SentryService.init(
|
||||
appRunner: () async {
|
||||
// Set up error handlers
|
||||
_setupErrorHandlers();
|
||||
|
||||
try {
|
||||
// Initialize core dependencies in parallel for faster startup
|
||||
await Future.wait([_initializeHive(), _initializeSharedPreferences()]);
|
||||
try {
|
||||
// Initialize core dependencies in parallel for faster startup
|
||||
await Future.wait([_initializeHive(), _initializeSharedPreferences()]);
|
||||
|
||||
// Initialize OneSignal with verbose logging for debugging
|
||||
OneSignal.Debug.setLogLevel(OSLogLevel.verbose);
|
||||
// Initialize OneSignal push notifications
|
||||
await OneSignalService.init();
|
||||
|
||||
// Initialize with your OneSignal App ID
|
||||
OneSignal.initialize("778ca22d-c719-4ec8-86cb-a6b911166066");
|
||||
// Run the app with Riverpod ProviderScope
|
||||
runApp(const ProviderScope(child: WorkerApp()));
|
||||
} catch (error, stackTrace) {
|
||||
// Critical initialization error - capture and show error screen
|
||||
debugPrint('Failed to initialize app: $error');
|
||||
debugPrint('StackTrace: $stackTrace');
|
||||
|
||||
debugPrint('🔔 OneSignal initialized');
|
||||
// Report to Sentry
|
||||
await SentryService.captureException(error, stackTrace: stackTrace);
|
||||
|
||||
// Add observer BEFORE requesting permission to catch the subscription event
|
||||
OneSignal.User.pushSubscription.addObserver((state) {
|
||||
debugPrint('🔔 Push subscription state changed:');
|
||||
debugPrint(' Previous - optedIn: ${state.previous.optedIn}, id: ${state.previous.id}');
|
||||
debugPrint(' Current - optedIn: ${state.current.optedIn}, id: ${state.current.id}');
|
||||
debugPrint(' Subscription ID: ${state.current.id}');
|
||||
debugPrint(' Push Token: ${state.current.token}');
|
||||
|
||||
// Save subscription info when available
|
||||
if (state.current.id != null) {
|
||||
debugPrint('🔔 ✅ Device successfully subscribed!');
|
||||
// Run minimal error app
|
||||
runApp(_buildErrorApp(error, stackTrace));
|
||||
}
|
||||
});
|
||||
|
||||
// Add notification permission observer
|
||||
OneSignal.Notifications.addPermissionObserver((isGranted) {
|
||||
debugPrint('🔔 Notification permission changed: $isGranted');
|
||||
});
|
||||
|
||||
// Request permission - TRUE to show the native permission prompt
|
||||
final accepted = await OneSignal.Notifications.requestPermission(true);
|
||||
debugPrint('🔔 Permission request result: $accepted');
|
||||
|
||||
// Give OneSignal SDK time to complete initialization and server registration
|
||||
// This is necessary because the subscription happens asynchronously
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
|
||||
// Check current subscription status after initialization completes
|
||||
final optedIn = OneSignal.User.pushSubscription.optedIn;
|
||||
final id = OneSignal.User.pushSubscription.id;
|
||||
final token = OneSignal.User.pushSubscription.token;
|
||||
|
||||
debugPrint('🔔 Current subscription status (after delay):');
|
||||
debugPrint(' Opted In: $optedIn');
|
||||
debugPrint(' Subscription ID: $id');
|
||||
debugPrint(' Push Token: $token');
|
||||
|
||||
if (id == null) {
|
||||
debugPrint('🔔 ⚠️ Subscription ID is still null - check device connectivity and OneSignal app ID');
|
||||
}
|
||||
|
||||
// Run the app with Riverpod ProviderScope
|
||||
runApp(const ProviderScope(child: WorkerApp()));
|
||||
} catch (error, stackTrace) {
|
||||
// Critical initialization error - show error screen
|
||||
debugPrint('Failed to initialize app: $error');
|
||||
debugPrint('StackTrace: $stackTrace');
|
||||
|
||||
// Run minimal error app
|
||||
runApp(_buildErrorApp(error, stackTrace));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Initialize Hive database
|
||||
@@ -164,7 +127,8 @@ Future<void> _initializeSharedPreferences() async {
|
||||
|
||||
/// Set up global error handlers
|
||||
///
|
||||
/// Captures and logs all Flutter framework errors and uncaught exceptions
|
||||
/// Captures and logs all Flutter framework errors and uncaught exceptions.
|
||||
/// Reports errors to Sentry for crash analytics.
|
||||
void _setupErrorHandlers() {
|
||||
// Handle Flutter framework errors
|
||||
FlutterError.onError = (FlutterErrorDetails details) {
|
||||
@@ -176,8 +140,11 @@ void _setupErrorHandlers() {
|
||||
debugPrint('StackTrace: ${details.stack}');
|
||||
}
|
||||
|
||||
// In production, you would send to crash analytics service
|
||||
// Example: FirebaseCrashlytics.instance.recordFlutterError(details);
|
||||
// Report to Sentry
|
||||
SentryService.captureException(
|
||||
details.exception,
|
||||
stackTrace: details.stack,
|
||||
);
|
||||
};
|
||||
|
||||
// Handle errors outside of Flutter framework
|
||||
@@ -187,27 +154,11 @@ void _setupErrorHandlers() {
|
||||
debugPrint('StackTrace: $stackTrace');
|
||||
}
|
||||
|
||||
// In production, you would send to crash analytics service
|
||||
// Example: FirebaseCrashlytics.instance.recordError(error, stackTrace);
|
||||
// Report to Sentry
|
||||
SentryService.captureException(error, stackTrace: stackTrace);
|
||||
|
||||
return true; // Return true to indicate error was handled
|
||||
};
|
||||
|
||||
// Handle zone errors (async errors not caught by Flutter)
|
||||
runZonedGuarded(
|
||||
() {
|
||||
// App will run in this zone
|
||||
},
|
||||
(error, stackTrace) {
|
||||
if (kDebugMode) {
|
||||
debugPrint('Zone Error: $error');
|
||||
debugPrint('StackTrace: $stackTrace');
|
||||
}
|
||||
|
||||
// In production, you would send to crash analytics service
|
||||
// Example: FirebaseCrashlytics.instance.recordError(error, stackTrace);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Build minimal error app when initialization fails
|
||||
|
||||
Reference in New Issue
Block a user