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.
This commit is contained in:
1 parent
9f1bfe8940
commit
262aa439db
2 files changed
+25
-16
No files matched your search
@@ -97,8 +97,16 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
// Check exact alarm permission for Android 12+
|
// Check exact alarm permission for Android 12+
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !Alert.isExactAlarmAllowed(this)) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !Alert.isExactAlarmAllowed(this)) {
|
||||||
if (DEBUG) Log.w(tag, "Exact alarm permission not granted, requesting...");
|
if (DEBUG) Log.w(tag, "Exact alarm permission not granted, requesting...");
|
||||||
Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);
|
new AlertDialog.Builder(MainActivity.this)
|
||||||
startActivity(intent);
|
.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){
|
if (DEBUG){
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import android.app.NotificationChannel;
|
|||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.media.MediaPlayer;
|
import android.media.Ringtone;
|
||||||
|
import android.media.RingtoneManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
@@ -18,7 +19,6 @@ public class TimerForegroundService extends Service {
|
|||||||
private static final int NOTIFICATION_ID = 1001;
|
private static final int NOTIFICATION_ID = 1001;
|
||||||
|
|
||||||
private PowerManager.WakeLock wakeLock;
|
private PowerManager.WakeLock wakeLock;
|
||||||
private MediaPlayer mediaPlayer;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
@@ -28,16 +28,15 @@ public class TimerForegroundService extends Service {
|
|||||||
// Android 8+ requires foreground service to play sound reliably while backgrounded
|
// Android 8+ requires foreground service to play sound reliably while backgrounded
|
||||||
startForeground(NOTIFICATION_ID, buildNotification());
|
startForeground(NOTIFICATION_ID, buildNotification());
|
||||||
|
|
||||||
|
// Acquire a wake lock briefly to ensure the CPU stays awake during playback
|
||||||
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
|
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
|
||||||
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TimerWakeLock");
|
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);
|
wakeLock.acquire(60 * 1000L);
|
||||||
|
|
||||||
playSound();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
playSound();
|
||||||
return START_NOT_STICKY; // Don't restart immediately if killed
|
return START_NOT_STICKY; // Don't restart immediately if killed
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,18 +63,20 @@ public class TimerForegroundService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void playSound() {
|
private void playSound() {
|
||||||
if (mediaPlayer != null && mediaPlayer.isPlaying()) return;
|
|
||||||
|
|
||||||
try {
|
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);
|
Uri uri = android.media.RingtoneManager.getDefaultUri(android.media.RingtoneManager.TYPE_NOTIFICATION);
|
||||||
mediaPlayer = MediaPlayer.create(this, uri);
|
Ringtone r = RingtoneManager.getRingtone(this, uri);
|
||||||
|
if (r != null) {
|
||||||
if (mediaPlayer != null) {
|
r.play();
|
||||||
mediaPlayer.setOnCompletionListener(mp -> stopSelf()); // Stop immediately after playing
|
// Allow time for sound to buffer and play before stopping
|
||||||
mediaPlayer.start();
|
new android.os.Handler().postDelayed(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
stopSelf();
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
stopSelf(); // Fallback if media player fails
|
stopSelf();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Failed to play sound", e);
|
Log.e(TAG, "Failed to play sound", e);
|
||||||
|
|||||||
Reference in new issue
Block a user