From 262aa439db86c0df39f6c311d581e8ce7a9d0ac2 Mon Sep 17 00:00:00 2001 From: Hyperling Date: Tue, 3 Nov 2026 13:16:32 -0700 Subject: [PATCH] Model's attempt to fix: 1) Only the first itnerval making a sound, all subsequent countdowns being silent. 2) App opening up directly to the Alarms & Reminders screen to get permissions approved without any prompting the user on what is going on. --- .../apps/infinitetimer/MainActivity.java | 12 ++++++-- .../infinitetimer/TimerForegroundService.java | 29 ++++++++++--------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/hyperling/apps/infinitetimer/MainActivity.java b/app/src/main/java/com/hyperling/apps/infinitetimer/MainActivity.java index e5b339c..d0599a3 100755 --- a/app/src/main/java/com/hyperling/apps/infinitetimer/MainActivity.java +++ b/app/src/main/java/com/hyperling/apps/infinitetimer/MainActivity.java @@ -97,8 +97,16 @@ public class MainActivity extends AppCompatActivity { // Check exact alarm permission for Android 12+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !Alert.isExactAlarmAllowed(this)) { if (DEBUG) Log.w(tag, "Exact alarm permission not granted, requesting..."); - Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM); - startActivity(intent); + new AlertDialog.Builder(MainActivity.this) + .setTitle("Alarm Permission Required") + .setMessage("To ensure the timer alerts you reliably, please grant 'Alarms & Reminders' permission in system settings.") + .setPositiveButton("Grant Permission", (d, w) -> { + Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM); + startActivity(intent); + }) + .setNegativeButton("Not Now", (d, w) -> d.dismiss()) + .setCancelable(false) + .show(); } if (DEBUG){ diff --git a/app/src/main/java/com/hyperling/apps/infinitetimer/TimerForegroundService.java b/app/src/main/java/com/hyperling/apps/infinitetimer/TimerForegroundService.java index 450d2a2..dcb103d 100644 --- a/app/src/main/java/com/hyperling/apps/infinitetimer/TimerForegroundService.java +++ b/app/src/main/java/com/hyperling/apps/infinitetimer/TimerForegroundService.java @@ -4,7 +4,8 @@ import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.Service; import android.content.Intent; -import android.media.MediaPlayer; +import android.media.Ringtone; +import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; import android.os.IBinder; @@ -18,7 +19,6 @@ public class TimerForegroundService extends Service { private static final int NOTIFICATION_ID = 1001; private PowerManager.WakeLock wakeLock; - private MediaPlayer mediaPlayer; @Override public void onCreate() { @@ -28,16 +28,15 @@ public class TimerForegroundService extends Service { // Android 8+ requires foreground service to play sound reliably while backgrounded startForeground(NOTIFICATION_ID, buildNotification()); + // Acquire a wake lock briefly to ensure the CPU stays awake during playback PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TimerWakeLock"); - // Lock for up to 60 seconds to ensure audio finishes playing even if CPU sleeps wakeLock.acquire(60 * 1000L); - - playSound(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { + playSound(); return START_NOT_STICKY; // Don't restart immediately if killed } @@ -64,18 +63,20 @@ public class TimerForegroundService extends Service { } private void playSound() { - if (mediaPlayer != null && mediaPlayer.isPlaying()) return; - try { - // Plays default notification sound. Replace with R.raw.your_sound if you want custom audio Uri uri = android.media.RingtoneManager.getDefaultUri(android.media.RingtoneManager.TYPE_NOTIFICATION); - mediaPlayer = MediaPlayer.create(this, uri); - - if (mediaPlayer != null) { - mediaPlayer.setOnCompletionListener(mp -> stopSelf()); // Stop immediately after playing - mediaPlayer.start(); + Ringtone r = RingtoneManager.getRingtone(this, uri); + if (r != null) { + r.play(); + // Allow time for sound to buffer and play before stopping + new android.os.Handler().postDelayed(new Runnable() { + @Override + public void run() { + stopSelf(); + } + }, 1000); } else { - stopSelf(); // Fallback if media player fails + stopSelf(); } } catch (Exception e) { Log.e(TAG, "Failed to play sound", e);