Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@
android:name="com.google.android.gms.car.notification.SmallIcon"
android:resource="@drawable/ic_icon" />

<!-- Cast -->
<meta-data
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="me.echeung.moemoekyun.service.CastOptionsProvider" />
<receiver android:name="androidx.mediarouter.media.MediaTransferReceiver" />

<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/kotlin/me/echeung/moemoekyun/di/MediaModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package me.echeung.moemoekyun.di
import android.content.Context
import android.media.AudioManager
import androidx.annotation.OptIn
import androidx.media3.cast.CastPlayer
import androidx.media3.common.AudioAttributes
import androidx.media3.common.C
import androidx.media3.common.MediaItem
Expand Down Expand Up @@ -65,4 +66,9 @@ object MediaModule {
.setAudioAttributes(audioAttributes, true)
.setWakeMode(C.WAKE_MODE_NETWORK)
.build()

@Provides
fun castPlayer(@ApplicationContext context: Context, exoPlayer: ExoPlayer): CastPlayer = CastPlayer.Builder(context)
.setLocalPlayer(exoPlayer)
.build()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package me.echeung.moemoekyun.service

import android.content.Context
import androidx.media3.common.util.UnstableApi
import com.google.android.gms.cast.framework.CastOptions
import com.google.android.gms.cast.framework.OptionsProvider
import com.google.android.gms.cast.framework.SessionProvider

// https://cast.google.com/publish/#/applications/edit/6E4C737C
private const val CAST_RECEIVER_ID: String = "6E4C737C"

@UnstableApi
class CastOptionsProvider : OptionsProvider {

override fun getCastOptions(context: Context): CastOptions = CastOptions.Builder()
.setResumeSavedSession(false)
.setEnableReconnectionService(false)
.setReceiverApplicationId(CAST_RECEIVER_ID)
.setStopReceiverApplicationWhenEndingSession(true)
.setRemoteToLocalEnabled(true)
.build()

override fun getAdditionalSessionProviders(context: Context): List<SessionProvider?> = emptyList()
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
package me.echeung.moemoekyun.service

import androidx.annotation.OptIn
import androidx.media3.cast.CastPlayer
import androidx.media3.common.C
import androidx.media3.common.ForwardingPlayer
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.collectLatest
import logcat.logcat
Expand All @@ -22,7 +22,7 @@ import kotlin.time.toDuration

@OptIn(UnstableApi::class)
class PlaybackPlayer @Inject constructor(
val player: ExoPlayer,
val player: CastPlayer,
val currentSong: CurrentSong,
val scope: CoroutineScope,
) : ForwardingPlayer(player) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.media3.cast.MediaRouteButton
import androidx.media3.common.Player
import androidx.media3.common.listen
import androidx.media3.common.util.UnstableApi
Expand Down Expand Up @@ -371,18 +372,21 @@ private fun LandscapeExpandedPlayerContent(

@Composable
private fun CollapseIcon(onClickCollapse: () -> Unit) {
Box(
Row(
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = onClickCollapse)
.padding(vertical = 16.dp),
contentAlignment = Alignment.Center,
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
modifier = Modifier.alpha(0.5f),
imageVector = Icons.Outlined.ExpandMore,
contentDescription = null,
)

MediaRouteButton()
}
}

Expand Down
3 changes: 2 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ aboutLibraries-compose = { module = "com.mikepenz:aboutlibraries-compose-m3", ve

androidx-appcompat = "androidx.appcompat:appcompat:1.7.1"
androidx-lifecycle = "androidx.lifecycle:lifecycle-process:2.10.0"
androidx-media3-cast = { module = "androidx.media3:media3-cast", version.ref = "media3" }
androidx-media3-common = { module = "androidx.media3:media3-common-ktx", version.ref = "media3" }
androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "media3" }
androidx-media3-session = { module = "androidx.media3:media3-session", version.ref = "media3" }
Expand Down Expand Up @@ -89,7 +90,7 @@ coil = ["coil-core", "coil-compose", "coil-gif", "coil-network-okhttp"]
compose = ["compose-activity", "compose-material", "compose-material-icons-extended", "compose-material3", "compose-ui", "compose-ui-tooling", "compose-ui-util"]
coroutines = ["coroutines-core", "coroutines-android"]
junit-runtime = ["junit-platform-launcher", "junit-jupiter-engine"]
media = ["androidx-media3-common", "androidx-media3-exoplayer", "androidx-media3-session"]
media = ["androidx-media3-cast", "androidx-media3-common", "androidx-media3-exoplayer", "androidx-media3-session"]
okhttp = ["okhttp-core", "okhttp-logging"]
preferences = ["preferences-androidx", "preferences-flow"]
voyager = ["voyager-bottom-sheet", "voyager-navigator", "voyager-hilt"]