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 package com.simplemobiletools.clock.extensions
import android.annotation.SuppressLint
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent
import android.media.RingtoneManager import android.media.RingtoneManager
import android.net.Uri import android.net.Uri
import android.widget.Toast
import com.simplemobiletools.clock.R import com.simplemobiletools.clock.R
import com.simplemobiletools.clock.helpers.* import com.simplemobiletools.clock.helpers.*
import com.simplemobiletools.clock.models.Alarm import com.simplemobiletools.clock.models.Alarm
import com.simplemobiletools.clock.models.AlarmSound import com.simplemobiletools.clock.models.AlarmSound
import com.simplemobiletools.clock.models.MyTimeZone 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 java.util.*
import kotlin.math.pow
val Context.config: Config get() = Config.newInstance(applicationContext) 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) 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.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 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.os.Bundle
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast
import com.simplemobiletools.clock.R import com.simplemobiletools.clock.R
import com.simplemobiletools.clock.activities.SimpleActivity import com.simplemobiletools.clock.activities.SimpleActivity
import com.simplemobiletools.clock.adapters.AlarmsAdapter import com.simplemobiletools.clock.adapters.AlarmsAdapter
import com.simplemobiletools.clock.dialogs.EditAlarmDialog import com.simplemobiletools.clock.dialogs.EditAlarmDialog
import com.simplemobiletools.clock.extensions.cancelAlarmClock
import com.simplemobiletools.clock.extensions.createNewAlarm import com.simplemobiletools.clock.extensions.createNewAlarm
import com.simplemobiletools.clock.extensions.dbHelper 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.interfaces.ToggleAlarmInterface
import com.simplemobiletools.clock.models.Alarm import com.simplemobiletools.clock.models.Alarm
import com.simplemobiletools.clock.receivers.AlarmReceiver
import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.extensions.updateTextColors import com.simplemobiletools.commons.extensions.updateTextColors
import com.simplemobiletools.commons.helpers.isLollipopPlus
import kotlinx.android.synthetic.main.fragment_alarm.view.* import kotlinx.android.synthetic.main.fragment_alarm.view.*
import java.util.* import java.util.*
import kotlin.math.pow
class AlarmFragment : Fragment(), ToggleAlarmInterface { class AlarmFragment : Fragment(), ToggleAlarmInterface {
private val DEFAULT_ALARM_MINUTES = 480
private val DAY_MINUTES = 1440
private var alarms = ArrayList<Alarm>() private var alarms = ArrayList<Alarm>()
lateinit var view: ViewGroup lateinit var view: ViewGroup
@ -89,74 +79,9 @@ class AlarmFragment : Fragment(), ToggleAlarmInterface {
private fun checkAlarmState(alarm: Alarm) { private fun checkAlarmState(alarm: Alarm) {
if (alarm.isEnabled) { if (alarm.isEnabled) {
getClosestTriggerTimestamp(alarm) context!!.scheduleNextAlarm(alarm, true)
} else { } 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 TABS_COUNT = 3
const val EDITED_TIME_ZONE_SEPARATOR = ":" const val EDITED_TIME_ZONE_SEPARATOR = ":"
const val ALARM_ID = "alarm_id" 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 ?: "" 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.config
import com.simplemobiletools.clock.extensions.dbHelper import com.simplemobiletools.clock.extensions.dbHelper
import com.simplemobiletools.clock.extensions.formatAlarmTime import com.simplemobiletools.clock.extensions.formatAlarmTime
import com.simplemobiletools.clock.extensions.scheduleNextAlarm
import com.simplemobiletools.clock.helpers.ALARM_ID import com.simplemobiletools.clock.helpers.ALARM_ID
import com.simplemobiletools.clock.models.Alarm import com.simplemobiletools.clock.models.Alarm
import com.simplemobiletools.clock.services.SnoozeService import com.simplemobiletools.clock.services.SnoozeService
@ -33,6 +34,8 @@ class AlarmReceiver : BroadcastReceiver() {
val notification = getNotification(context, pendingIntent, alarm) val notification = getNotification(context, pendingIntent, alarm)
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(alarm.id, notification) notificationManager.notify(alarm.id, notification)
context.scheduleNextAlarm(alarm, false)
} }
@SuppressLint("NewApi") @SuppressLint("NewApi")