package com.timesafari.dailynotification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.provider.Settings; import android.util.Log; /** * Manages notification channels and ensures they are properly configured * for reliable notification delivery. * * Handles channel creation, importance checking, and provides deep links * to channel settings when notifications are blocked. * * @author Matthew Raymer * @version 1.0 */ public class ChannelManager { private static final String TAG = "ChannelManager"; private static final String DEFAULT_CHANNEL_ID = "timesafari.daily"; private static final String DEFAULT_CHANNEL_NAME = "Daily Notifications"; private static final String DEFAULT_CHANNEL_DESCRIPTION = "Daily notifications from TimeSafari"; private final Context context; private final NotificationManager notificationManager; public ChannelManager(Context context) { this.context = context; this.notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); } /** * Ensures the default notification channel exists and is properly configured. * Creates the channel if it doesn't exist. * * @return true if channel is ready for notifications, false if blocked */ public boolean ensureChannelExists() { try { Log.d(TAG, "Ensuring notification channel exists"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = notificationManager.getNotificationChannel(DEFAULT_CHANNEL_ID); if (channel == null) { Log.d(TAG, "Creating notification channel"); createDefaultChannel(); return true; } else { Log.d(TAG, "Channel exists with importance: " + channel.getImportance()); return channel.getImportance() != NotificationManager.IMPORTANCE_NONE; } } else { // Pre-Oreo: channels don't exist, always ready Log.d(TAG, "Pre-Oreo device, channels not applicable"); return true; } } catch (Exception e) { Log.e(TAG, "Error ensuring channel exists", e); return false; } } /** * Checks if the notification channel is enabled and can deliver notifications. * * @return true if channel is enabled, false if blocked */ public boolean isChannelEnabled() { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = notificationManager.getNotificationChannel(DEFAULT_CHANNEL_ID); if (channel == null) { Log.w(TAG, "Channel does not exist"); return false; } int importance = channel.getImportance(); Log.d(TAG, "Channel importance: " + importance); return importance != NotificationManager.IMPORTANCE_NONE; } else { // Pre-Oreo: always enabled return true; } } catch (Exception e) { Log.e(TAG, "Error checking channel status", e); return false; } } /** * Gets the current channel importance level. * * @return importance level, or -1 if channel doesn't exist */ public int getChannelImportance() { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = notificationManager.getNotificationChannel(DEFAULT_CHANNEL_ID); if (channel != null) { return channel.getImportance(); } } return -1; } catch (Exception e) { Log.e(TAG, "Error getting channel importance", e); return -1; } } /** * Opens the notification channel settings for the user to enable notifications. * * @return true if settings intent was launched, false otherwise */ public boolean openChannelSettings() { try { Log.d(TAG, "Opening channel settings"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) .putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName()) .putExtra(Settings.EXTRA_CHANNEL_ID, DEFAULT_CHANNEL_ID) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); Log.d(TAG, "Channel settings opened"); return true; } else { Log.d(TAG, "Channel settings not available on pre-Oreo"); return false; } } catch (Exception e) { Log.e(TAG, "Error opening channel settings", e); return false; } } /** * Creates the default notification channel with high importance. */ private void createDefaultChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( DEFAULT_CHANNEL_ID, DEFAULT_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH ); channel.setDescription(DEFAULT_CHANNEL_DESCRIPTION); channel.enableLights(true); channel.enableVibration(true); channel.setShowBadge(true); notificationManager.createNotificationChannel(channel); Log.d(TAG, "Default channel created with HIGH importance"); } } /** * Gets the default channel ID for use in notifications. * * @return the default channel ID */ public String getDefaultChannelId() { return DEFAULT_CHANNEL_ID; } /** * Logs the current channel status for debugging. */ public void logChannelStatus() { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = notificationManager.getNotificationChannel(DEFAULT_CHANNEL_ID); if (channel != null) { Log.i(TAG, "Channel Status - ID: " + channel.getId() + ", Importance: " + channel.getImportance() + ", Enabled: " + (channel.getImportance() != NotificationManager.IMPORTANCE_NONE)); } else { Log.w(TAG, "Channel does not exist"); } } else { Log.i(TAG, "Pre-Oreo device, channels not applicable"); } } catch (Exception e) { Log.e(TAG, "Error logging channel status", e); } } }