schedule the next alarm at triggering

This commit is contained in:
tibbi 2018-03-06 21:35:44 +01:00
parent b54cf59c3e
commit 539be21489
4 changed files with 87 additions and 80 deletions

View File

@ -1,14 +1,23 @@
package com.simplemobiletools.clock.extensions
import android.annotation.SuppressLint
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.media.RingtoneManager
import android.net.Uri
import android.widget.Toast
import com.simplemobiletools.clock.R
import com.simplemobiletools.clock.helpers.*
import com.simplemobiletools.clock.models.Alarm
import com.simplemobiletools.clock.models.AlarmSound
import com.simplemobiletools.clock.models.MyTimeZone
import com.simplemobiletools.clock.receivers.AlarmReceiver
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.helpers.isLollipopPlus
import java.util.*
import kotlin.math.pow
val Context.config: Config get() = Config.newInstance(applicationContext)
@ -74,3 +83,71 @@ private fun getDefaultAlarmUri() = RingtoneManager.getDefaultUri(RingtoneManager
private fun getDefaultAlarmTitle(context: Context) = RingtoneManager.getRingtone(context, getDefaultAlarmUri()).getTitle(context)
fun Context.createNewAlarm(timeInMinutes: Int, weekDays: Int) = Alarm(0, timeInMinutes, weekDays, false, false, getDefaultAlarmTitle(this), getDefaultAlarmUri().toString(), "")
fun Context.scheduleNextAlarm(alarm: Alarm, showToast: Boolean) {
val calendar = Calendar.getInstance()
calendar.firstDayOfWeek = Calendar.MONDAY
for (i in 0..7) {
val currentDay = (calendar.get(Calendar.DAY_OF_WEEK) + 5) % 7
val isCorrectDay = alarm.days and 2.0.pow(currentDay).toInt() != 0
val currentTimeInMinutes = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE)
if (isCorrectDay && (alarm.timeInMinutes > currentTimeInMinutes || i > 0)) {
val triggerInMinutes = alarm.timeInMinutes - currentTimeInMinutes + (i * DAY_MINUTES)
setupAlarmClock(alarm, triggerInMinutes * 60 - calendar.get(Calendar.SECOND))
if (showToast) {
showRemainingTimeMessage(triggerInMinutes)
}
break
} else {
calendar.add(Calendar.DAY_OF_MONTH, 1)
}
}
}
fun Context.showRemainingTimeMessage(triggerInMinutes: Int) {
val days = triggerInMinutes / DAY_MINUTES
val hours = (triggerInMinutes % DAY_MINUTES) / 60
val minutes = triggerInMinutes % 60
val timesString = StringBuilder()
if (days > 0) {
val daysString = String.format(resources.getQuantityString(R.plurals.days, days, days))
timesString.append("$daysString, ")
}
if (hours > 0) {
val hoursString = String.format(resources.getQuantityString(R.plurals.hours, hours, hours))
timesString.append("$hoursString, ")
}
if (minutes > 0) {
val minutesString = String.format(resources.getQuantityString(R.plurals.minutes, minutes, minutes))
timesString.append(minutesString)
}
val fullString = String.format(getString(R.string.alarm_goes_off_in), timesString.toString().trim().trimEnd(','))
toast(fullString, Toast.LENGTH_LONG)
}
@SuppressLint("NewApi")
fun Context.setupAlarmClock(alarm: Alarm, triggerInSeconds: Int) {
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val targetMS = System.currentTimeMillis() + triggerInSeconds * 1000
val pendingIntent = getPendingIntent(alarm)
if (isLollipopPlus()) {
val info = AlarmManager.AlarmClockInfo(targetMS, pendingIntent)
alarmManager.setAlarmClock(info, pendingIntent)
}
}
fun Context.getPendingIntent(alarm: Alarm): PendingIntent {
val intent = Intent(this, AlarmReceiver::class.java)
intent.putExtra(ALARM_ID, alarm.id)
return PendingIntent.getBroadcast(this, alarm.id, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
fun Context.cancelAlarmClock(alarm: Alarm) {
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.cancel(getPendingIntent(alarm))
}

View File

@ -1,37 +1,27 @@
package com.simplemobiletools.clock.fragments
import android.annotation.SuppressLint
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import com.simplemobiletools.clock.R
import com.simplemobiletools.clock.activities.SimpleActivity
import com.simplemobiletools.clock.adapters.AlarmsAdapter
import com.simplemobiletools.clock.dialogs.EditAlarmDialog
import com.simplemobiletools.clock.extensions.cancelAlarmClock
import com.simplemobiletools.clock.extensions.createNewAlarm
import com.simplemobiletools.clock.extensions.dbHelper
import com.simplemobiletools.clock.helpers.ALARM_ID
import com.simplemobiletools.clock.extensions.scheduleNextAlarm
import com.simplemobiletools.clock.helpers.DEFAULT_ALARM_MINUTES
import com.simplemobiletools.clock.interfaces.ToggleAlarmInterface
import com.simplemobiletools.clock.models.Alarm
import com.simplemobiletools.clock.receivers.AlarmReceiver
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.extensions.updateTextColors
import com.simplemobiletools.commons.helpers.isLollipopPlus
import kotlinx.android.synthetic.main.fragment_alarm.view.*
import java.util.*
import kotlin.math.pow
class AlarmFragment : Fragment(), ToggleAlarmInterface {
private val DEFAULT_ALARM_MINUTES = 480
private val DAY_MINUTES = 1440
private var alarms = ArrayList<Alarm>()
lateinit var view: ViewGroup
@ -89,74 +79,9 @@ class AlarmFragment : Fragment(), ToggleAlarmInterface {
private fun checkAlarmState(alarm: Alarm) {
if (alarm.isEnabled) {
getClosestTriggerTimestamp(alarm)
context!!.scheduleNextAlarm(alarm, true)
} else {
cancelAlarmClock(alarm)
context!!.cancelAlarmClock(alarm)
}
}
private fun getClosestTriggerTimestamp(alarm: Alarm) {
val calendar = Calendar.getInstance()
calendar.firstDayOfWeek = Calendar.MONDAY
for (i in 0..7) {
val currentDay = (calendar.get(Calendar.DAY_OF_WEEK) + 5) % 7
val isCorrectDay = alarm.days and 2.0.pow(currentDay).toInt() != 0
val currentTimeInMinutes = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE)
if (isCorrectDay && (alarm.timeInMinutes > currentTimeInMinutes || i > 0)) {
val triggerInMinutes = alarm.timeInMinutes - currentTimeInMinutes + (i * DAY_MINUTES)
showRemainingTimeMessage(triggerInMinutes)
setupAlarmClock(alarm, triggerInMinutes * 60 - calendar.get(Calendar.SECOND))
break
} else {
calendar.add(Calendar.DAY_OF_MONTH, 1)
}
}
}
private fun showRemainingTimeMessage(triggerInMinutes: Int) {
val days = triggerInMinutes / DAY_MINUTES
val hours = (triggerInMinutes % DAY_MINUTES) / 60
val minutes = triggerInMinutes % 60
val timesString = StringBuilder()
if (days > 0) {
val daysString = String.format(activity!!.resources.getQuantityString(R.plurals.days, days, days))
timesString.append("$daysString, ")
}
if (hours > 0) {
val hoursString = String.format(activity!!.resources.getQuantityString(R.plurals.hours, hours, hours))
timesString.append("$hoursString, ")
}
if (minutes > 0) {
val minutesString = String.format(activity!!.resources.getQuantityString(R.plurals.minutes, minutes, minutes))
timesString.append(minutesString)
}
val fullString = String.format(activity!!.getString(R.string.alarm_goes_off_in), timesString.toString().trim().trimEnd(','))
activity!!.toast(fullString, Toast.LENGTH_LONG)
}
@SuppressLint("NewApi")
private fun setupAlarmClock(alarm: Alarm, triggerInSeconds: Int) {
val alarmManager = context!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val targetMS = System.currentTimeMillis() + triggerInSeconds * 1000
val pendingIntent = getPendingIntent(alarm)
if (isLollipopPlus()) {
val info = AlarmManager.AlarmClockInfo(targetMS, pendingIntent)
alarmManager.setAlarmClock(info, pendingIntent)
}
}
private fun getPendingIntent(alarm: Alarm): PendingIntent {
val intent = Intent(context, AlarmReceiver::class.java)
intent.putExtra(ALARM_ID, alarm.id)
return PendingIntent.getBroadcast(context, alarm.id, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
private fun cancelAlarmClock(alarm: Alarm) {
val alarmManager = context!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.cancel(getPendingIntent(alarm))
}
}

View File

@ -11,6 +11,8 @@ const val EDITED_TIME_ZONE_TITLES = "edited_time_zone_titles"
const val TABS_COUNT = 3
const val EDITED_TIME_ZONE_SEPARATOR = ":"
const val ALARM_ID = "alarm_id"
const val DEFAULT_ALARM_MINUTES = 480
const val DAY_MINUTES = 1440
fun getDefaultTimeZoneTitle(id: Int) = getAllTimeZones().firstOrNull { it.id == id }?.title ?: ""

View File

@ -17,6 +17,7 @@ import com.simplemobiletools.clock.activities.SnoozeReminderActivity
import com.simplemobiletools.clock.extensions.config
import com.simplemobiletools.clock.extensions.dbHelper
import com.simplemobiletools.clock.extensions.formatAlarmTime
import com.simplemobiletools.clock.extensions.scheduleNextAlarm
import com.simplemobiletools.clock.helpers.ALARM_ID
import com.simplemobiletools.clock.models.Alarm
import com.simplemobiletools.clock.services.SnoozeService
@ -33,6 +34,8 @@ class AlarmReceiver : BroadcastReceiver() {
val notification = getNotification(context, pendingIntent, alarm)
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(alarm.id, notification)
context.scheduleNextAlarm(alarm, false)
}
@SuppressLint("NewApi")