mirror of
https://github.com/zoriya/react-native-omni.git
synced 2026-08-16 02:44:51 +00:00
fix(cast): keep cast running after app close
This commit is contained in:
@@ -4,6 +4,8 @@ import android.content.Context
|
||||
import com.google.android.gms.cast.CastMediaControlIntent
|
||||
import com.google.android.gms.cast.framework.CastOptions
|
||||
import com.google.android.gms.cast.framework.media.CastMediaOptions
|
||||
import com.google.android.gms.cast.framework.media.MediaIntentReceiver
|
||||
import com.google.android.gms.cast.framework.media.NotificationOptions
|
||||
import com.google.android.gms.cast.framework.OptionsProvider
|
||||
import com.google.android.gms.cast.framework.SessionProvider
|
||||
|
||||
@@ -12,9 +14,27 @@ class OmniCastOptionsProvider : OptionsProvider {
|
||||
val appId = OmniPlayer.receiverApplicationId
|
||||
?: CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID
|
||||
|
||||
val notificationOptions = NotificationOptions.Builder()
|
||||
.setActions(
|
||||
listOf(
|
||||
MediaIntentReceiver.ACTION_SKIP_PREV,
|
||||
MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK,
|
||||
MediaIntentReceiver.ACTION_SKIP_NEXT,
|
||||
),
|
||||
intArrayOf(0, 1, 2),
|
||||
)
|
||||
.setSmallIconDrawableResId(
|
||||
androidx.media3.session.R.drawable.media3_notification_small_icon
|
||||
)
|
||||
.apply {
|
||||
context.packageManager.getLaunchIntentForPackage(context.packageName)
|
||||
?.component?.className
|
||||
?.let { setTargetActivityClassName(it) }
|
||||
}
|
||||
.build()
|
||||
|
||||
val mediaOptions = CastMediaOptions.Builder()
|
||||
.setMediaSessionEnabled(false)
|
||||
.setNotificationOptions(null)
|
||||
.setNotificationOptions(notificationOptions)
|
||||
.build()
|
||||
|
||||
return CastOptions.Builder()
|
||||
|
||||
@@ -42,7 +42,6 @@ import androidx.media3.common.MediaItem.SubtitleConfiguration
|
||||
import androidx.media3.common.TrackSelectionOverride
|
||||
import androidx.media3.cast.CastPlayer
|
||||
import androidx.media3.cast.RemoteCastPlayer
|
||||
import androidx.media3.session.DefaultMediaNotificationProvider
|
||||
import androidx.media3.session.MediaSession
|
||||
import androidx.media3.session.MediaSessionService
|
||||
import androidx.mediarouter.app.MediaRouteChooserDialog
|
||||
@@ -105,6 +104,7 @@ class OmniPlayer(
|
||||
private val castStateListener = CastStateListener {
|
||||
eventMap.emitCastStatus(computeCastStatus())
|
||||
listenToReceiver()
|
||||
syncNotificationService()
|
||||
}
|
||||
|
||||
// receivers have no queue to skip in (a queue would make them play things on
|
||||
@@ -166,7 +166,8 @@ class OmniPlayer(
|
||||
private var serviceRunning = false
|
||||
|
||||
private fun syncNotificationService() {
|
||||
val shouldShow = showNotification == true && source != null
|
||||
val shouldShow = showNotification == true && source != null &&
|
||||
!runOnMainThreadSync { isCasting }
|
||||
when {
|
||||
shouldShow && !serviceRunning -> {
|
||||
val otherIsPlaying = notificationPlayer?.let { other ->
|
||||
@@ -232,7 +233,7 @@ class OmniPlayer(
|
||||
runOnMainThread {
|
||||
eventMap.dispose()
|
||||
castContext?.removeCastStateListener(castStateListener)
|
||||
player.release()
|
||||
if (!isCasting) player.release()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -681,10 +682,6 @@ class OmniPlayerService : MediaSessionService() {
|
||||
}
|
||||
.build()
|
||||
|
||||
setMediaNotificationProvider(DefaultMediaNotificationProvider.Builder(this).build().apply {
|
||||
setSmallIcon(applicationInfo.icon.takeIf { it != 0 }
|
||||
?: android.R.drawable.ic_media_play)
|
||||
})
|
||||
addSession(mediaSession)
|
||||
setShowNotificationForIdlePlayer(SHOW_NOTIFICATION_FOR_IDLE_PLAYER_ALWAYS)
|
||||
|
||||
@@ -725,8 +722,7 @@ class OmniPlayerService : MediaSessionService() {
|
||||
)
|
||||
|
||||
return NotificationCompat.Builder(this, "omni_playback")
|
||||
.setSmallIcon(applicationInfo.icon.takeIf { it != 0 }
|
||||
?: android.R.drawable.ic_media_play)
|
||||
.setSmallIcon(androidx.media3.session.R.drawable.media3_notification_small_icon)
|
||||
.setContentTitle("Omni Player")
|
||||
.setContentText("Preparing playback...")
|
||||
.setContentIntent(pendingIntent)
|
||||
@@ -737,7 +733,14 @@ class OmniPlayerService : MediaSessionService() {
|
||||
override fun onGetSession(controllerInfo: MediaSession.ControllerInfo) = mediaSession
|
||||
|
||||
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||
pauseAllPlayersAndStopSelf()
|
||||
val casting = try {
|
||||
CastContext.getSharedInstance(this)
|
||||
.sessionManager.currentCastSession?.isConnected == true
|
||||
} catch (_: Throwable) {
|
||||
false
|
||||
}
|
||||
// keep service open if casting
|
||||
if (!casting) pauseAllPlayersAndStopSelf()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
||||
@@ -66,6 +66,7 @@ module.exports = {
|
||||
port: 3000,
|
||||
hot: true,
|
||||
historyApiFallback: true,
|
||||
allowedHosts: "all",
|
||||
// jassub's wasm is multithreaded (pthreads), which needs SharedArrayBuffer
|
||||
// and therefore a cross-origin-isolated page. `credentialless` keeps
|
||||
// cross-origin video/subtitle/font requests working without CORP headers.
|
||||
|
||||
Reference in New Issue
Block a user