diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index cbc21bf..11ea536 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -17,6 +17,7 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/de/mlte/soundboard/MainActivity.kt b/app/src/main/java/de/mlte/soundboard/MainActivity.kt
index 096cb37..9a5e58b 100644
--- a/app/src/main/java/de/mlte/soundboard/MainActivity.kt
+++ b/app/src/main/java/de/mlte/soundboard/MainActivity.kt
@@ -1,11 +1,11 @@
package de.mlte.soundboard
+import android.animation.Animator
import android.animation.ValueAnimator
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.res.Configuration.ORIENTATION_LANDSCAPE
-import android.media.MediaPlayer
import android.net.Uri
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
@@ -17,14 +17,35 @@ import android.view.animation.LinearInterpolator
import android.widget.GridLayout
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
+import android.content.ComponentName
+import android.os.IBinder
+import android.content.ServiceConnection
+import android.animation.AnimatorListenerAdapter
+import android.util.Log
class MainActivity : AppCompatActivity() {
private val buttons = ArrayList()
- private var player: MediaPlayer? = null
- private var playing = false
private var playingButton: SoundButton? = null
private var playingAnimator: ValueAnimator? = null
+ private var playerService: PlayerService? = null
+
+ private val playerServiceConnection = object : ServiceConnection {
+
+ override fun onServiceConnected(className: ComponentName,
+ binder: IBinder) {
+ val binder = binder as PlayerService.PlayerServiceBinder
+ val service = binder.service
+ playerService = service
+ playingButton?.let{ button -> startAnimator(service, button) }
+ }
+
+ override fun onServiceDisconnected(className: ComponentName) {
+ playerService = null
+ }
+ }
+
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
@@ -37,36 +58,17 @@ class MainActivity : AppCompatActivity() {
}
override fun onSaveInstanceState(outState: Bundle?) {
- if (playing) {
- player?.let { mp ->
- if (mp.isPlaying) {
- outState?.putBoolean("playing", true)
- outState?.putInt("playingPosition", mp.currentPosition)
- val parent = findViewById(R.id.grid_layout)
- val index = parent.indexOfChild(playingButton)
- outState?.putInt("playingIndex", index)
- }
+ playerService?.let { service ->
+ if (service.playing) {
+ val parent = findViewById(R.id.grid_layout)
+ val index = parent.indexOfChild(playingButton)
+ outState?.putInt("playing", index)
}
}
super.onSaveInstanceState(outState)
}
- override fun onDestroy() {
- if (playing) {
- player?.let { mp ->
- if (mp.isPlaying) {
- mp.stop()
- }
- mp.reset()
- mp.release()
- }
- playingAnimator?.cancel()
- }
-
- super.onDestroy()
- }
-
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
super.onRestoreInstanceState(savedInstanceState)
@@ -75,14 +77,32 @@ class MainActivity : AppCompatActivity() {
}
savedInstanceState?.let { state ->
- if (state.getBoolean("playing")) {
- val button = buttons[state.getInt("playingIndex")]
- val position = state.getInt("playingPosition")
- startPlaying(button, position)
+ val index = state.getInt("playing", -1)
+ if (index > -1) {
+ playingButton = buttons[index]
}
}
}
+ override fun onStart() {
+ super.onStart()
+
+ val intent = Intent(this, PlayerService::class.java)
+ startService(intent)
+ bindService(intent, playerServiceConnection, 0)
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ if (playerService?.playing != true) {
+ val intent = Intent(this, PlayerService::class.java)
+ stopService(intent)
+ }
+
+ unbindService(playerServiceConnection)
+ }
+
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.main, menu)
@@ -108,7 +128,7 @@ class MainActivity : AppCompatActivity() {
private fun saveNumButtons() {
val editor = getPreferences(Context.MODE_PRIVATE).edit()
editor.putInt("numButtons", buttons.size)
- editor.commit()
+ editor.apply()
}
private fun organizeButtons() {
@@ -135,6 +155,35 @@ class MainActivity : AppCompatActivity() {
parent.columnCount = columns
}
+ private fun playButton(soundButton: SoundButton) {
+ playerService?.let{ service ->
+ playingButton = soundButton
+ service.start(soundButton.soundId)
+ startAnimator(service, soundButton)
+ }
+ }
+
+ private fun startAnimator(service: PlayerService, button: SoundButton) {
+ playingAnimator?.cancel()
+ if (service.playing) {
+ val bar = button.progressBar
+ val animator = ValueAnimator.ofInt(bar.max * service.currentPosition / service.duration, bar.max)
+ animator.interpolator = LinearInterpolator()
+ animator.addUpdateListener {
+ bar.progress = animator.animatedValue as Int
+ }
+ animator.addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ bar.progress = 0
+ }
+ })
+
+ animator.duration = service.duration.toLong() - service.currentPosition
+ animator.start()
+ playingAnimator = animator
+ }
+ }
+
private fun addButton(soundButton: SoundButton) {
buttons.add(soundButton)
@@ -142,21 +191,11 @@ class MainActivity : AppCompatActivity() {
parent.addView(soundButton)
soundButton.textView.setOnClickListener {
- if (playing) {
- player?.let { mp ->
- if (mp.isPlaying) {
- mp.stop()
- }
- mp.reset()
- mp.release()
- }
- playingButton?.let { button ->
- button.progressBar.progress = 0
- }
- playing = false
+ if (playerService?.playing == true) {
+ playerService?.stop()
playingAnimator?.cancel()
} else {
- startPlaying(soundButton, 0)
+ playButton(soundButton)
}
}
@@ -166,36 +205,9 @@ class MainActivity : AppCompatActivity() {
}
}
- private fun startPlaying(soundButton: SoundButton, position: Int) {
- val file = getFileStreamPath("audio" + soundButton.soundId)
- if (file.exists()) {
- val mp = MediaPlayer.create(this, Uri.fromFile(file))
- mp.setOnCompletionListener {
- playingAnimator?.cancel()
- soundButton.progressBar.progress = 0
- mp.reset()
- mp.release()
- playing = false
- }
- mp.seekTo(position)
- mp.start()
- player = mp
- playing = true
- playingButton = soundButton
-
- val bar = soundButton.progressBar
- val animator = ValueAnimator.ofInt(bar.max * position / mp.duration, bar.max)
- animator.interpolator = LinearInterpolator()
- animator.addUpdateListener {
- bar.progress = animator.animatedValue as Int
- }
- animator.duration = mp.duration.toLong() - position
- animator.start()
- playingAnimator = animator
- }
- }
-
private fun editButton(soundButton: SoundButton) {
+ playerService?.stop()
+ playingAnimator?.cancel()
val intent = Intent(baseContext, EditActivity::class.java)
val parent = findViewById(R.id.grid_layout)
val index = parent.indexOfChild(soundButton)
@@ -262,23 +274,23 @@ class MainActivity : AppCompatActivity() {
val editor = getPreferences(Context.MODE_PRIVATE).edit()
editor.putString("caption" + index, textView.text.toString())
editor.putString("fileName" + index, buttons[index].fileName)
- editor.commit()
+ editor.apply()
- uri?.let { uri ->
+ uri?.let { u ->
deleteFile("audio" + soundId)
val newSoundId = System.currentTimeMillis()
buttons[index].soundId = newSoundId
editor.putLong("soundId" + index, newSoundId)
editor.commit()
- grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ grantUriPermission(packageName, u, Intent.FLAG_GRANT_READ_URI_PERMISSION)
val output = BufferedOutputStream(openFileOutput("audio" + newSoundId, Context.MODE_PRIVATE))
- val input = BufferedInputStream(contentResolver.openInputStream(uri))
+ val input = BufferedInputStream(contentResolver.openInputStream(u))
try {
val buf = ByteArray(1024)
input.read(buf)
do {
output.write(buf)
- } while (input.read(buf) !== -1)
+ } while (input.read(buf) != -1)
} finally {
input.close()
output.close()
diff --git a/app/src/main/java/de/mlte/soundboard/PlayerService.kt b/app/src/main/java/de/mlte/soundboard/PlayerService.kt
new file mode 100644
index 0000000..4ae4ecd
--- /dev/null
+++ b/app/src/main/java/de/mlte/soundboard/PlayerService.kt
@@ -0,0 +1,59 @@
+package de.mlte.soundboard
+
+import android.app.Service
+import android.content.Intent
+import android.media.MediaPlayer
+import android.net.Uri
+import android.os.Binder
+import android.os.IBinder
+
+class PlayerService : Service() {
+ private val binder = PlayerServiceBinder()
+
+ private var player: MediaPlayer? = null
+
+ val currentPosition: Int
+ get() = player?.currentPosition ?: 0
+
+ val duration: Int
+ get() = player?.duration ?: 0
+
+ val playing: Boolean
+ get() = player?.isPlaying ?: false
+
+ inner class PlayerServiceBinder : Binder() {
+ internal
+ val service: PlayerService
+ get() = this@PlayerService
+ }
+
+ override fun onBind(intent: Intent): IBinder = binder
+
+ fun stop() {
+ player?.let { mp ->
+ mp.stop()
+ mp.reset()
+ mp.release()
+ player = null
+ }
+ }
+
+ fun start(soundId: Long) {
+ stop()
+ val file = getFileStreamPath("audio" + soundId)
+ if (file.exists()) {
+ val mp = MediaPlayer.create(this, Uri.fromFile(file))
+ mp.setOnCompletionListener {
+ mp.reset()
+ mp.release()
+ player = null
+ }
+ mp.start()
+ player = mp
+ }
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ return START_STICKY
+ }
+}