Skip to content

Fix/snoozed alarm sound#15

Open
itsmeaabhii wants to merge 3 commits into
CCExtractor:mainfrom
itsmeaabhii:fix/snoozed-alarm-sound
Open

Fix/snoozed alarm sound#15
itsmeaabhii wants to merge 3 commits into
CCExtractor:mainfrom
itsmeaabhii:fix/snoozed-alarm-sound

Conversation

@itsmeaabhii
Copy link
Copy Markdown

@itsmeaabhii itsmeaabhii commented Feb 22, 2026

Description

Fixed snoozed alarm sound not playing. The issue was that the ringtone and vibrator instances were being stopped but not set to null in AlarmSnoozeReceiver, causing the snoozed alarm to reuse the stopped instances instead of creating fresh ones.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (code improvement/cleanup without logical changes)
  • UI/Design change

Proposed Changes

  • Updated AlarmSnoozeReceiver.kt to properly clean up ringtone and vibrator instances
  • Added null assignment to AlarmServiceHolder.ringtone and AlarmServiceHolder.vibrator after stopping them
  • Added logging for better debugging of ringtone and vibration lifecycle
  • Ensured snoozed alarms create fresh ringtone instances when triggered

Fixes #4

Screenshots

N/A - Audio/notification fix without UI changes

Checklist

  • Tests have been added or updated to cover the changes
  • Documentation has been updated to reflect the changes
  • Code follows the established coding style guidelines
  • All tests are passing

- Added BootBroadcastReceiver to handle BOOT_COMPLETED intent
- Added RECEIVE_BOOT_COMPLETED permission to AndroidManifest.xml
- Automatically reschedules all active alarms from database on boot
- Fixes issue CCExtractor#9
- Implemented dynamic location fetching using fl_location package
- Added fetchCurrentLocation() method with permission handling
- Replaced hardcoded New Delhi coordinates with real-time user location
- Added fallback to default location if permission denied or unavailable
- Added loading indicator in UI while fetching location
- Graceful error handling with user-friendly snackbar notifications
- Fixes issue CCExtractor#6
Copilot AI review requested due to automatic review settings February 22, 2026 05:44
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a bug where snoozed alarms don’t replay sound/vibration by ensuring alarm playback resources are fully cleaned up before rescheduling; additionally introduces boot-time alarm rescheduling and location-condition UX changes.

Changes:

  • Nulls out AlarmServiceHolder.ringtone / vibrator after stopping/cancelling to force fresh instances on the next trigger.
  • Adds a boot-complete broadcast receiver and manifest permission/registration to reschedule alarms after reboot.
  • Updates location-condition flow to fetch current location with permission/service checks and show a loading indicator.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
pubspec.lock Updates resolved Dart/Flutter dependency versions and recorded SDK resolution constraints.
lib/app/modules/smart_control/views/location/location_condition_view.dart Disables taps during location fetch and shows a progress indicator for the selected option.
lib/app/modules/smart_control/controllers/location_controller.dart Adds current-location fetching with permission/service handling and sets picker start location accordingly.
android/app/src/main/kotlin/com/example/uac_companion/AlarmServices/BroadcastReceivers/BootBroadcastReceiver.kt Adds a boot receiver that reschedules alarms after device reboot.
android/app/src/main/kotlin/com/example/uac_companion/AlarmServices/BroadcastReceivers/AlarmSnoozeReceiver.kt Stops and clears ringtone/vibrator instances when snoozing to avoid reusing stopped objects.
android/app/src/main/AndroidManifest.xml Adds RECEIVE_BOOT_COMPLETED permission and registers the new boot receiver.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The manifest registers QUICKBOOT_POWERON, but BootBroadcastReceiver currently only handles ACTION_BOOT_COMPLETED. Either add handling for QUICKBOOT_POWERON in the receiver or remove this <action> to avoid a dead/unused intent-filter entry.

Suggested change
<action android:name="android.intent.action.QUICKBOOT_POWERON" />

Copilot uses AI. Check for mistakes.
Comment on lines +21 to +36

try {
// Get all enabled alarms from the database
val alarms = AlarmUtils.getAllAlarmsFromDb(context)
val enabledAlarms = alarms.filter { it.isEnabled == 1 }

Log.d(TAG, "Found ${enabledAlarms.size} enabled alarms to reschedule")

// Reschedule each alarm using the AlarmScheduler
// The scheduler will automatically pick the next upcoming alarm
if (enabledAlarms.isNotEmpty()) {
AlarmScheduler.scheduleNextAlarm(context)
Log.d(TAG, "Successfully rescheduled alarms after boot")
} else {
Log.d(TAG, "No active alarms to reschedule")
}
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AlarmScheduler.scheduleNextAlarm(context) already reads enabled alarms from the DB. The extra getAllAlarmsFromDb() + filter { it.isEnabled == 1 } here duplicates work and increases boot-time overhead; consider calling the scheduler directly (or refactor the scheduler to accept the pre-fetched list).

Suggested change
try {
// Get all enabled alarms from the database
val alarms = AlarmUtils.getAllAlarmsFromDb(context)
val enabledAlarms = alarms.filter { it.isEnabled == 1 }
Log.d(TAG, "Found ${enabledAlarms.size} enabled alarms to reschedule")
// Reschedule each alarm using the AlarmScheduler
// The scheduler will automatically pick the next upcoming alarm
if (enabledAlarms.isNotEmpty()) {
AlarmScheduler.scheduleNextAlarm(context)
Log.d(TAG, "Successfully rescheduled alarms after boot")
} else {
Log.d(TAG, "No active alarms to reschedule")
}
try {
// Delegate to AlarmScheduler, which reads enabled alarms from the database
AlarmScheduler.scheduleNextAlarm(context)
Log.d(TAG, "AlarmScheduler invoked to reschedule alarms after boot")

Copilot uses AI. Check for mistakes.
Comment on lines +21 to +39

try {
// Get all enabled alarms from the database
val alarms = AlarmUtils.getAllAlarmsFromDb(context)
val enabledAlarms = alarms.filter { it.isEnabled == 1 }

Log.d(TAG, "Found ${enabledAlarms.size} enabled alarms to reschedule")

// Reschedule each alarm using the AlarmScheduler
// The scheduler will automatically pick the next upcoming alarm
if (enabledAlarms.isNotEmpty()) {
AlarmScheduler.scheduleNextAlarm(context)
Log.d(TAG, "Successfully rescheduled alarms after boot")
} else {
Log.d(TAG, "No active alarms to reschedule")
}
} catch (e: Exception) {
Log.e(TAG, "Error rescheduling alarms after boot: ${e.message}", e)
}
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This receiver does synchronous DB IO inside onReceive. If the alarms table grows, this can risk slow boot handling / ANR. Consider using goAsync() + background work (or scheduling a WorkManager job) and returning quickly from onReceive.

Suggested change
try {
// Get all enabled alarms from the database
val alarms = AlarmUtils.getAllAlarmsFromDb(context)
val enabledAlarms = alarms.filter { it.isEnabled == 1 }
Log.d(TAG, "Found ${enabledAlarms.size} enabled alarms to reschedule")
// Reschedule each alarm using the AlarmScheduler
// The scheduler will automatically pick the next upcoming alarm
if (enabledAlarms.isNotEmpty()) {
AlarmScheduler.scheduleNextAlarm(context)
Log.d(TAG, "Successfully rescheduled alarms after boot")
} else {
Log.d(TAG, "No active alarms to reschedule")
}
} catch (e: Exception) {
Log.e(TAG, "Error rescheduling alarms after boot: ${e.message}", e)
}
// Use goAsync to offload potentially long-running DB work off the main thread
val pendingResult = goAsync()
Thread {
try {
// Get all enabled alarms from the database
val alarms = AlarmUtils.getAllAlarmsFromDb(context)
val enabledAlarms = alarms.filter { it.isEnabled == 1 }
Log.d(TAG, "Found ${enabledAlarms.size} enabled alarms to reschedule")
// Reschedule each alarm using the AlarmScheduler
// The scheduler will automatically pick the next upcoming alarm
if (enabledAlarms.isNotEmpty()) {
AlarmScheduler.scheduleNextAlarm(context)
Log.d(TAG, "Successfully rescheduled alarms after boot")
} else {
Log.d(TAG, "No active alarms to reschedule")
}
} catch (e: Exception) {
Log.e(TAG, "Error rescheduling alarms after boot: ${e.message}", e)
} finally {
pendingResult.finish()
}
}.start()

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +41
currentUserLocation.value = fallbackLatLng;
isLoadingLocation.value = false;
return;
}
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These early returns manually set isLoadingLocation to false, but the finally block also sets it to false even when returning. Removing the intermediate assignments avoids duplication and makes the loading state handling less error-prone.

Copilot uses AI. Check for mistakes.
Comment on lines +104 to +108
// Fetch current location before opening picker
await fetchCurrentLocation();

// Use current user location or fallback
pickerLatLng.value = currentUserLocation.value ?? fallbackLatLng;
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description/title are about fixing snoozed alarm sound, but this hunk adds location fetching/permission flow before opening the picker. If this isn’t required for the alarm fix, consider splitting these location changes into a separate PR to reduce review and revert risk.

Copilot uses AI. Check for mistakes.
@Abhishek14104
Copy link
Copy Markdown
Collaborator

Looks good overall

However, this PR includes 3 commits addressing 3 different issues. It would be much clearer and easier to review if each issue was handled in a separate branch and raised as separate PRs.
Please separate these issues and raise individual PRs for each one.

Also, going forward, please attach a short demo video with each PR showing the final working state. For example, for the “replace hardcoded location with user’s current location” change, include a small video demonstrating that functionality working properly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Snoozed alarm triggers notification but fails to play sound

3 participants