service: handle non-native start
Restore the state by default when another app starts the service. A simple first step to ensure service independence (no clue if it's enough)
This commit is contained in:
parent
800ebfe77e
commit
3a4ddb43b9
3 changed files with 47 additions and 9 deletions
|
@ -20,6 +20,7 @@ package org.oxycblt.auxio
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.IBinder
|
||||||
import androidx.core.app.ServiceCompat
|
import androidx.core.app.ServiceCompat
|
||||||
import androidx.media3.session.MediaLibraryService
|
import androidx.media3.session.MediaLibraryService
|
||||||
import androidx.media3.session.MediaSession
|
import androidx.media3.session.MediaSession
|
||||||
|
@ -41,6 +42,27 @@ class AuxioService : MediaLibraryService(), ForegroundListener {
|
||||||
indexingFragment.attach(this)
|
indexingFragment.attach(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onBind(intent: Intent?): IBinder? {
|
||||||
|
handleIntent(intent)
|
||||||
|
return super.onBind(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
// TODO: Start command occurring from a foreign service basically implies a detached
|
||||||
|
// service, we might need more handling here.
|
||||||
|
handleIntent(intent)
|
||||||
|
return super.onStartCommand(intent, flags, startId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleIntent(intent: Intent?) {
|
||||||
|
val nativeStart = intent?.getBooleanExtra(INTENT_KEY_NATIVE_START, false) ?: false
|
||||||
|
if (!nativeStart) {
|
||||||
|
// Some foreign code started us, no guarantees about foreground stability. Figure
|
||||||
|
// out what to do.
|
||||||
|
mediaSessionFragment.handleNonNativeStart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onTaskRemoved(rootIntent: Intent?) {
|
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||||
super.onTaskRemoved(rootIntent)
|
super.onTaskRemoved(rootIntent)
|
||||||
mediaSessionFragment.handleTaskRemoved()
|
mediaSessionFragment.handleTaskRemoved()
|
||||||
|
@ -78,6 +100,11 @@ class AuxioService : MediaLibraryService(), ForegroundListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// This is only meant for Auxio to internally ensure that it's state management will work.
|
||||||
|
const val INTENT_KEY_NATIVE_START = BuildConfig.APPLICATION_ID + ".service.NATIVE_START"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ForegroundListener {
|
interface ForegroundListener {
|
||||||
|
|
|
@ -69,7 +69,9 @@ class MainActivity : AppCompatActivity() {
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
startService(Intent(this, AuxioService::class.java))
|
startService(
|
||||||
|
Intent(this, AuxioService::class.java)
|
||||||
|
.putExtra(AuxioService.INTENT_KEY_NATIVE_START, true))
|
||||||
|
|
||||||
if (!startIntentAction(intent)) {
|
if (!startIntentAction(intent)) {
|
||||||
// No intent action to do, just restore the previously saved state.
|
// No intent action to do, just restore the previously saved state.
|
||||||
|
|
|
@ -50,7 +50,9 @@ import org.oxycblt.auxio.IntegerTable
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.image.service.MediaSessionBitmapLoader
|
import org.oxycblt.auxio.image.service.MediaSessionBitmapLoader
|
||||||
import org.oxycblt.auxio.music.service.MediaItemBrowser
|
import org.oxycblt.auxio.music.service.MediaItemBrowser
|
||||||
|
import org.oxycblt.auxio.playback.state.DeferredPlayback
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||||
|
import org.oxycblt.auxio.util.logD
|
||||||
|
|
||||||
class MediaSessionServiceFragment
|
class MediaSessionServiceFragment
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -103,14 +105,11 @@ constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun release() {
|
fun handleNonNativeStart() {
|
||||||
waitJob.cancel()
|
// At minimum we want to ensure an active playback state.
|
||||||
mediaSession.release()
|
// TODO: Possibly also force to go foreground?
|
||||||
actionHandler.release()
|
logD("Handling non-native start.")
|
||||||
exoHolder.release()
|
playbackManager.playDeferred(DeferredPlayback.RestoreState)
|
||||||
playbackManager.removeListener(this)
|
|
||||||
mediaSession.release()
|
|
||||||
foregroundListener = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasNotification(): Boolean = exoHolder.sessionOngoing
|
fun hasNotification(): Boolean = exoHolder.sessionOngoing
|
||||||
|
@ -124,6 +123,16 @@ constructor(
|
||||||
post(wrapMediaNotification(notification))
|
post(wrapMediaNotification(notification))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun release() {
|
||||||
|
waitJob.cancel()
|
||||||
|
mediaSession.release()
|
||||||
|
actionHandler.release()
|
||||||
|
exoHolder.release()
|
||||||
|
playbackManager.removeListener(this)
|
||||||
|
mediaSession.release()
|
||||||
|
foregroundListener = null
|
||||||
|
}
|
||||||
|
|
||||||
private fun wrapMediaNotification(notification: MediaNotification): MediaNotification {
|
private fun wrapMediaNotification(notification: MediaNotification): MediaNotification {
|
||||||
// Pulled from MediaNotificationManager: Need to specify MediaSession token manually
|
// Pulled from MediaNotificationManager: Need to specify MediaSession token manually
|
||||||
// in notification
|
// in notification
|
||||||
|
|
Loading…
Reference in a new issue