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(R.id.statusText) val input = findViewById(R.id.timerInput) val fadeToggle = findViewById(R.id.fadeToggle) val volumeBar = findViewById(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() } }