Buschauffeurswekker v1: CalDAV-dagcheck 12:00, kwartier-afronding, wekkers Opstaan/Wally/Vertrek, fullscreen alarm-UI
This commit is contained in:
parent
97b7d3090e
commit
34505be9b8
31 changed files with 1881 additions and 1 deletions
|
|
@ -0,0 +1,171 @@
|
|||
package nl.eddydevink.buschauffeurswekker
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.PowerManager
|
||||
import android.provider.Settings
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import kotlinx.coroutines.launch
|
||||
import nl.eddydevink.buschauffeurswekker.core.AlarmScheduler
|
||||
import nl.eddydevink.buschauffeurswekker.core.Prefs
|
||||
import nl.eddydevink.buschauffeurswekker.core.ShiftCheck
|
||||
import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var prefs: Prefs
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
prefs = Prefs(this)
|
||||
requestNotificationPermission()
|
||||
|
||||
findViewById<MaterialButton>(R.id.btn_check).setOnClickListener { runCheck() }
|
||||
findViewById<MaterialButton>(R.id.btn_test).setOnClickListener {
|
||||
AlarmScheduler.scheduleTest(this)
|
||||
Toast.makeText(this, "Testwekker gaat over 10 seconden af", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
findViewById<MaterialButton>(R.id.btn_save).setOnClickListener { saveSettings() }
|
||||
|
||||
findViewById<MaterialButton>(R.id.btn_perm_notifications).setOnClickListener {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
|
||||
checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), REQ_NOTIFICATIONS)
|
||||
} else {
|
||||
toast("Meldingen zijn al toegestaan")
|
||||
}
|
||||
}
|
||||
findViewById<MaterialButton>(R.id.btn_perm_exact).setOnClickListener { openExactAlarmSettings() }
|
||||
findViewById<MaterialButton>(R.id.btn_perm_battery).setOnClickListener { openBatterySettings() }
|
||||
findViewById<MaterialButton>(R.id.btn_perm_fullscreen).setOnClickListener { openFullScreenSettings() }
|
||||
|
||||
// Staat altijd zichtbaar in de status-edit: pionnen van de volgende controle alvast zetten.
|
||||
AlarmScheduler.scheduleNoonCheck(this)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
renderStatus()
|
||||
renderSettings()
|
||||
}
|
||||
|
||||
private fun renderStatus() {
|
||||
val p = prefs
|
||||
val last = p.lastCheckedAtMillis.takeIf { it > 0 }?.let {
|
||||
Instant.ofEpochMilli(it)
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.format(DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm"))
|
||||
} ?: "nooit"
|
||||
findViewById<TextView>(R.id.tv_status).text = buildString {
|
||||
append("Dagelijkse controle: elke dag om 12:00\n")
|
||||
append("Laatst gecontroleerd: $last\n\n")
|
||||
append(p.lastStatusTxt ?: "Nog niet gecontroleerd.")
|
||||
val (day, alarms) = p.loadPlan()
|
||||
if (day != null && alarms.isNotEmpty()) {
|
||||
append("\n\nGepland voor $day:")
|
||||
alarms.forEach { append("\n ${it.name} om ${it.time.toLocalTime()}") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderSettings() {
|
||||
findViewById<EditText>(R.id.et_url).setText(prefs.calendarUrl.orEmpty())
|
||||
findViewById<EditText>(R.id.et_user).setText(prefs.username.orEmpty())
|
||||
findViewById<EditText>(R.id.et_pass).setText(prefs.password.orEmpty())
|
||||
}
|
||||
|
||||
private fun saveSettings() {
|
||||
prefs.calendarUrl = findViewById<EditText>(R.id.et_url).text.toString().trim()
|
||||
prefs.username = findViewById<EditText>(R.id.et_user).text.toString().trim()
|
||||
prefs.password = findViewById<EditText>(R.id.et_pass).text.toString()
|
||||
toast("Instellingen opgeslagen")
|
||||
}
|
||||
|
||||
private fun runCheck() {
|
||||
saveSettings()
|
||||
val btn = findViewById<MaterialButton>(R.id.btn_check)
|
||||
btn.isEnabled = false
|
||||
btn.text = "Bezig…"
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val result = ShiftCheck.run(this@MainActivity)
|
||||
renderStatus()
|
||||
toast(result.message)
|
||||
} finally {
|
||||
btn.isEnabled = true
|
||||
btn.text = "Nu controleren"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun openExactAlarmSettings() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
runCatching {
|
||||
startActivity(
|
||||
Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM, Uri.parse("package:$packageName")),
|
||||
)
|
||||
}.onFailure { toast("Niet beschikbaar op dit toestel") }
|
||||
} else {
|
||||
toast("Niet nodig op dit toestel")
|
||||
}
|
||||
}
|
||||
|
||||
private fun openBatterySettings() {
|
||||
val pm = getSystemService(Context.POWER_SERVICE) as PowerManager
|
||||
if (pm.isIgnoringBatteryOptimizations(packageName)) {
|
||||
toast("Deze app is al uitgezonderd van batterijoptimalisatie")
|
||||
return
|
||||
}
|
||||
runCatching {
|
||||
startActivity(
|
||||
Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, Uri.parse("package:$packageName")),
|
||||
)
|
||||
}.onFailure { toast("Niet beschikbaar op dit toestel") }
|
||||
}
|
||||
|
||||
private fun openFullScreenSettings() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
runCatching {
|
||||
startActivity(
|
||||
Intent(
|
||||
Settings.ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT,
|
||||
Uri.parse("package:$packageName"),
|
||||
),
|
||||
)
|
||||
}.onFailure { toast("Niet beschikbaar op dit toestel") }
|
||||
} else {
|
||||
toast("Op dit toestel (Android < 14) is volledig scherm standaard geregeld")
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestNotificationPermission() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
|
||||
ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) !=
|
||||
PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), REQ_NOTIFICATIONS)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toast(msg: String) = Toast.makeText(this, msg, Toast.LENGTH_LONG).show()
|
||||
|
||||
private companion object {
|
||||
const val REQ_NOTIFICATIONS = 42
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue