Search code examples
javaandroidalarmmanager

Android Alarm firing instantly when I set alarm on earlier hour or after midnight


Im creating my first app in Android Studio. My Alarm Clock is working almost well, but when I will set Alarm to hour earlier than current or after midnight my alarm is firing instantly. For example, current time is 17:00, when I set alarm for 17:05 everything is fine, but when alarm is for 16:00 or 00:05 alarm is firing instantly. I will be thankful for all your advices. Here is my code:

Alarm.java

public class Alarm extends AppCompatActivity {
private TimePicker timePicker;
private Button vibrationButton;
private Button soundButton;
private Button noteButton;
private Button saveButton;
private Button cancelButton;
private CheckBox wifiCheckBox;
private CheckBox soundCheckBox;
private CheckBox bluetoothCheckBox;
private TextView textView;
private BluetoothAdapter mBluetoothAdapter;
private WifiManager wiFi;
private AudioManager audioManager;
private AlarmManager alarmManager;
private PendingIntent pendingIntent;
private NotificationManager notificationManager;
private Intent intent;
private int hour;
private int minute;
private String minuteString;
private String hourString;
private void turnOnWifi() {
    if (wifiCheckBox.isChecked())
        wiFi.setWifiEnabled(true);
}

private void turnOnBluetooth() {
    if (bluetoothCheckBox.isChecked())
        mBluetoothAdapter.enable();
}

private void turnOnSound() {
    if (soundCheckBox.isChecked())
        audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
}
private void notification() {
    Intent intentNotification = new Intent(this.getApplicationContext(),Alarm.class);
    PendingIntent pendingIntentNotification = PendingIntent.getActivity(this, 0, intentNotification, 0);
    Notification notification = new Notification.Builder(this)
            .setContentTitle("Alarm")
            .setContentText("Next alarm: " + hourString + ":" + minuteString)
            .setContentIntent(pendingIntentNotification)
            .setAutoCancel(false)
            .setSmallIcon(R.mipmap.ic_launcher)
            .build();
    notificationManager.notify(0, notification);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_alarm);
    timePicker = findViewById(R.id.timePicker);
    vibrationButton = findViewById(R.id.vibrationButton);
    soundButton = findViewById(R.id.soundButton);
    noteButton = findViewById(R.id.noteButton);
    saveButton = findViewById(R.id.saveButton);
    cancelButton = findViewById(R.id.cancelButton);
    wifiCheckBox = findViewById(R.id.wifiCheckBox);
    soundCheckBox = findViewById(R.id.soundCheckBox);
    bluetoothCheckBox = findViewById(R.id.bluetoothCheckBox);

    textView = findViewById(R.id.textView);
    wiFi = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    intent = new Intent(this, AlarmReceiver.class);
    timePicker.setIs24HourView(true);
    saveButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Calendar calendar = Calendar.getInstance();
            if (calendar.before(Calendar.getInstance()))
                calendar.add(Calendar.DATE, 1);
            if (Build.VERSION.SDK_INT >= 23) {
                calendar.set(Calendar.HOUR_OF_DAY, timePicker.getHour());
                calendar.set(Calendar.MINUTE, timePicker.getMinute());
                calendar.set(Calendar.SECOND, 0);
                hour = timePicker.getHour();
                minute = timePicker.getMinute();
            } else {
                calendar.set(Calendar.HOUR_OF_DAY, timePicker.getCurrentHour());
                calendar.set(Calendar.MINUTE, timePicker.getCurrentMinute());
                calendar.set(Calendar.SECOND, 0);
                hour = timePicker.getCurrentHour();
                minute = timePicker.getCurrentMinute();
            }
            hourString = String.valueOf(hour);
            minuteString = String.valueOf(minute);
            if (hour == 0)
                hourString = "0" + hourString;
            if (minute < 10)
                minuteString = "0" + minuteString;
            textView.setText("Next alarm: " + hourString + ":" + minuteString);
            intent.putExtra("extra", "on");
            setAlarm(calendar.getTimeInMillis());
     //       notification();
        }
    });

cancelButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        textView.setText("Alarm off!");
        alarmManager.cancel(pendingIntent);
        intent.putExtra("extra", "off");
        sendBroadcast(intent);
     //   notificationManager.cancel(0);
    }
});
}

private void setAlarm(long timeInMillis) {
    pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    alarmManager.set(AlarmManager.RTC_WAKEUP, timeInMillis, pendingIntent);
}

}

AlarmReceiver.java

public class AlarmReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    Log.e("test","test123");
    String getState = intent.getExtras().getString("extra");
    Log.e("Key is: ", getState);
    Intent intentService = new Intent(context, RingtoneService.class);
    intentService.putExtra("extra", getState);
    context.startService(intentService);
}

}

RingtoneService.java

public class RingtoneService extends Service {
private MediaPlayer mediaPlayer;
boolean isRunning;
int startId;

@Override
public void onDestroy() {
    Toast.makeText(this, "on destroy", Toast.LENGTH_SHORT).show();
    this.isRunning = false;
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}
public int onStartCommand(Intent intent, int flags, int startId) {
    String state = intent.getExtras().getString("extra");
    assert state != null;
    switch (state) {
        case "on":
            startId = 1;
            break;
        case "off":
            startId = 0;
            break;
        default:
            startId = 0;
            break;
    }
    if (!this.isRunning && startId == 1){
        mediaPlayer = MediaPlayer.create(this, Settings.System.DEFAULT_RINGTONE_URI);
        mediaPlayer.start();
        this.isRunning = true;
        this.startId = 0;
    }
    else if (this.isRunning && startId == 0){
        mediaPlayer.stop();
        mediaPlayer.reset();
        this.isRunning = false;
        this.startId = 0;
    }
    else if (!this.isRunning && startId == 0){
        this.isRunning = false;
        this.startId = 0;
    }
    else if (this.isRunning && startId == 1){
        this.isRunning = true;
        this.startId = 1;
    }

    return START_NOT_STICKY;
}

}


Solution

  • Of course it does... It's meant to work so. Android recognizes that the time is past, so it will fire the alarm, even if it's late.

    You can make sure that the time set for the alarm is after the current time. Just calculate this difference:

    int diff = Calendar.getInstance().getTimeInMilis() - targetCal.getTimeInMillis();
    

    If diff is greater than 0, then add a day to your calendar (targetCal) Now, your device's time will be earlier (instead of being later) than the next scheduled alarm time.


    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
    calendar.set(Calendar.MINUTE, minute);
    
    if(calendar.before(Calendar.getInstance())) {
        calendar.add(Calendar.DATE, 1);
    }
    
    alarmManager.set(AlarmManager.RTC_WAKEUP,
        calendar.getTimeInMillis(), pendingDinnerIntent);