Files
android-hairdryer/app/src/main/java/com/example/hairdryer/MainActivity.kt

146 lines
5.1 KiB
Kotlin

package com.example.hairdryer
import android.app.Activity
import android.graphics.Color
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
import android.os.Handler
import android.widget.EditText
import android.widget.ProgressBar
import android.widget.TextView
import kotlin.math.pow
import kotlin.math.max
class MainActivity : Activity() {
private lateinit var soundPool: SoundPool
private var soundId = 0
private var streamId = 0
private val handler = Handler()
private var isPlaying = false
private var fadeEnabled = false
private var totalMillis: Long = 0
private var startTime: Long = 0
private var fadeRunnable: Runnable? = null
private var countdownRunnable: Runnable? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val status = findViewById<TextView>(R.id.statusText)
val input = findViewById<EditText>(R.id.timerInput)
val fadeToggle = findViewById<TextView>(R.id.fadeToggle)
val volumeBar = findViewById<ProgressBar>(R.id.volumeBar)
val attrs = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build()
soundPool = SoundPool.Builder()
.setMaxStreams(1)
.setAudioAttributes(attrs)
.build()
soundId = soundPool.load(this, R.raw.sound, 1)
updateUI(status, volumeBar, "Bereit", Color.LTGRAY, 1f)
fadeToggle.setOnClickListener {
fadeEnabled = !fadeEnabled
fadeToggle.text = "Fade-Out: " + if (fadeEnabled) "ON" else "OFF"
}
status.setOnClickListener {
if (isPlaying) {
stopSound(status, volumeBar)
} else {
val minutes = input.text.toString().toIntOrNull() ?: 0
startSound(minutes, status, volumeBar)
}
}
}
private fun startSound(minutes: Int, status: TextView, volumeBar: ProgressBar) {
stopSound(status, volumeBar)
streamId = soundPool.play(soundId, 1f, 1f, 1, -1, 1f)
isPlaying = true
startTime = System.currentTimeMillis()
if (minutes > 0) {
totalMillis = minutes * 60_000L
updateCountdown(minutes * 60, status)
// Countdown jede Sekunde
countdownRunnable = object : Runnable {
override fun run() {
val elapsedSec = ((System.currentTimeMillis() - startTime) / 1000).toInt()
val remainingSec = max(minutes * 60 - elapsedSec, 0)
updateCountdown(remainingSec, status)
if (remainingSec > 0) {
handler.postDelayed(this, 1000L)
} else {
stopSound(status, volumeBar)
}
}
}
handler.postDelayed(countdownRunnable!!, 1000L)
// Fade-Out (optional)
if (fadeEnabled) {
fadeRunnable = object : Runnable {
override fun run() {
if (!isPlaying) return
val elapsed = System.currentTimeMillis() - startTime
val progress = (elapsed.toFloat() / totalMillis).coerceIn(0f, 1f)
val volume = (1 - progress).pow(2) // exponentielles Fade
soundPool.setVolume(streamId, volume, volume)
volumeBar.progress = (volume * 100).toInt()
if (progress < 1f) {
handler.postDelayed(this, 200L)
}
}
}
handler.postDelayed(fadeRunnable!!, 200L)
} else {
volumeBar.progress = 100
}
} else {
// unendlich
updateUI(status, volumeBar, "Läuft: ∞", Color.GREEN, 1f)
volumeBar.progress = 100
}
}
private fun updateCountdown(remainingSec: Int, status: TextView) {
val minutes = remainingSec / 60
val seconds = remainingSec % 60
status.text = String.format("Läuft: %02d:%02d", minutes, seconds)
status.setBackgroundColor(Color.GREEN)
status.setTextColor(Color.BLACK)
}
private fun stopSound(status: TextView, volumeBar: ProgressBar) {
if (isPlaying) {
soundPool.stop(streamId)
isPlaying = false
}
handler.removeCallbacks(countdownRunnable ?: Runnable {})
handler.removeCallbacks(fadeRunnable ?: Runnable {})
updateUI(status, volumeBar, "Gestoppt", Color.RED, 0f)
volumeBar.progress = 0
}
private fun updateUI(view: TextView, bar: ProgressBar, text: String, color: Int, volume: Float) {
view.text = text
view.setBackgroundColor(color)
view.setTextColor(Color.BLACK)
bar.progress = (volume * 100).toInt()
}
override fun onDestroy() {
super.onDestroy()
soundPool.release()
}
}