Compare commits
7 Commits
4b4405a601
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 82276868c4 | |||
| d14ec42a92 | |||
| 0d5561feaf | |||
| fa671d6fc4 | |||
| a16fd1e995 | |||
| 1ca9f10658 | |||
| 6c3a36efe3 |
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
|
||||
@@ -8,9 +8,10 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@android:style/Theme.Light.NoTitleBar">
|
||||
|
||||
|
||||
<activity android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
android:exported="true"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
|
||||
@@ -1,25 +1,38 @@
|
||||
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.Button
|
||||
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 btn = findViewById<Button>(R.id.startBtn)
|
||||
val fadeToggle = findViewById<TextView>(R.id.fadeToggle)
|
||||
val volumeBar = findViewById<ProgressBar>(R.id.volumeBar)
|
||||
|
||||
val attrs = AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_MEDIA)
|
||||
@@ -33,22 +46,97 @@ class MainActivity : Activity() {
|
||||
|
||||
soundId = soundPool.load(this, R.raw.sound, 1)
|
||||
|
||||
btn.setOnClickListener {
|
||||
val min = input.text.toString().toIntOrNull() ?: 0
|
||||
startLoopingSound(min)
|
||||
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 startLoopingSound(minutes: Int) {
|
||||
// Starte Sound in Schleife
|
||||
streamId = soundPool.play(soundId, 1f, 1f, 1, -1, 1f) // -1 = loop unendlich
|
||||
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) {
|
||||
handler.postDelayed({
|
||||
soundPool.stop(streamId)
|
||||
}, minutes * 60_000L)
|
||||
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()
|
||||
|
||||
@@ -6,17 +6,55 @@
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/parentDeviceTitle"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|center_vertical"
|
||||
android:text="Dunstabzugshaube/Hairdryer"
|
||||
android:textSize="25dp" />
|
||||
|
||||
<Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp" />
|
||||
<TextView
|
||||
android:id="@+id/statusText"
|
||||
android:text="Bereit"
|
||||
android:textSize="26sp"
|
||||
android:gravity="center"
|
||||
android:textColor="#000000"
|
||||
android:padding="24dp"
|
||||
android:background="#CCCCCC"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/timerInput"
|
||||
android:hint="Sleep Timer (Minuten)"
|
||||
android:inputType="number"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/startBtn"
|
||||
android:text="Start"
|
||||
<TextView
|
||||
android:id="@+id/fadeToggle"
|
||||
android:text="Fade-Out: OFF"
|
||||
android:gravity="center"
|
||||
android:padding="12dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:background="#AAAAAA"
|
||||
android:textColor="#000000"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/volumeBar"
|
||||
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:max="100"
|
||||
android:progress="100"/>
|
||||
</LinearLayout>
|
||||
|
||||
Reference in New Issue
Block a user