runDiagnostics method
Runs a best-effort diagnostics sweep and returns actionable hints.
Implementation
Future<NotificationDiagnosticsResult> runDiagnostics() async {
try {
final NotificationSettings settings =
await _fcmService.getNotificationSettings();
final bool fcmSupported = _fcmService.isSupportedOnCurrentPlatform;
final bool permissionsGranted =
!fcmSupported || _isAuthorized(settings.authorizationStatus);
final String? storedToken = await _storageService.getFcmToken();
final bool tokenAvailable = storedToken != null && storedToken.isNotEmpty;
final bool badgeSupported = await _notificationService.isBadgeSupported();
final List<dynamic> pendingNotifications =
await _notificationService.getPendingNotifications();
final String webPermission =
await _notificationService.getWebNotificationPermissionStatus();
final bool webAllowed = webPermission == 'granted';
final Map<String, dynamic> webRuntimeDiagnostics =
await _notificationService.getWebRuntimeDiagnostics();
final Map<String, dynamic> deliveryDiagnostics =
_inAppMessageManager.getDeliveryDiagnostics(DateTime.now());
final int queuedBackgroundMessages =
(await _storageService.getQueuedBackgroundMessages()).length;
final List<String> recommendations = <String>[];
if (!permissionsGranted) {
recommendations.add(
'Prompt the user for notification permissions; current status: '
'${settings.authorizationStatus.name}.');
}
if (!fcmSupported) {
recommendations.add(
_fcmService.unsupportedPlatformReason ??
'Firebase Cloud Messaging is unavailable on this platform.');
recommendations.add(
'Use local notifications, scheduling, inbox, and in-app templates on desktop. For remote delivery, send through your own backend and handle desktop presentation locally.');
}
if (fcmSupported && !tokenAvailable) {
recommendations.add(
'No stored FCM token found. Ensure init() completed and updateTokenCallback saved the token.');
}
if (!badgeSupported) {
recommendations.add(
'App icon badges are not supported on $currentPlatformName or the current launcher.');
}
if (isWeb && !webAllowed) {
recommendations.add(
'Browser notifications are currently "$webPermission". Trigger a permission prompt or guide the user to allow notifications.');
}
if (isWeb &&
webRuntimeDiagnostics['notificationApiAvailable'] == false) {
recommendations.add(
'This browser does not expose the Notification API. Use a supported browser such as Chrome, Edge, or Safari with web notifications enabled.');
}
if (isWeb && webRuntimeDiagnostics['isSecureContext'] == false) {
recommendations.add(
'Web notifications require a secure context. Serve the app from HTTPS or localhost before testing push delivery.');
}
if (isWeb &&
webRuntimeDiagnostics['serviceWorkerApiAvailable'] == false) {
recommendations.add(
'Service workers are unavailable in this browser context. Web push will not function until service worker support is available.');
}
if (isWeb &&
webRuntimeDiagnostics['serviceWorkerApiAvailable'] == true &&
webRuntimeDiagnostics['serviceWorkerControllerPresent'] == false) {
recommendations.add(
'No active service worker is controlling this page. Verify the Firebase messaging service worker is registered at the expected scope.');
}
if (pendingNotifications.length > 16) {
recommendations.add(
'There are ${pendingNotifications.length} pending notifications queued locally. Consider pruning scheduled notifications.');
}
return NotificationDiagnosticsResult(
success: true,
permissionsGranted: permissionsGranted,
authorizationStatus: settings.authorizationStatus.name,
fcmTokenAvailable: tokenAvailable,
badgeSupported: badgeSupported,
webNotificationsAllowed: webAllowed,
pendingNotificationCount: pendingNotifications.length,
platform: currentPlatformName,
recommendations: recommendations,
metadata: {
'alertSetting': settings.alert.name,
'badgeSetting': settings.badge.name,
'soundSetting': settings.sound.name,
'showPreviews': settings.showPreviews.name,
'providesAppNotificationSettings':
settings.providesAppNotificationSettings.name,
'fcmSupported': fcmSupported,
'fcmUnsupportedReason': _fcmService.unsupportedPlatformReason,
'webPermission': webPermission,
'webDiagnostics': webRuntimeDiagnostics,
'storedTokenPresent': tokenAvailable,
'deliveryPolicy': deliveryDiagnostics,
'queuedBackgroundMessages': queuedBackgroundMessages,
'dataBridgeEnabled': _dataOnlyMessageBridge != null,
'backgroundHandlerRegistered': _backgroundHandlerRegistered,
'invalidPayloadCount': _invalidPayloadCount,
},
);
} catch (error, stack) {
_logMessage('[NotificationManager] Diagnostics error: $error');
_logMessage('[NotificationManager] Stack trace: $stack');
return NotificationDiagnosticsResult.failure(
platform: currentPlatformName,
error: error.toString(),
);
}
}