Skip to content

Commit 845154a

Browse files
committed
Fix artwork loading via server image proxy (e.g. Youtube plugin)
The default HTTP data source doesn't follow redirects. While at it, also unify OkHttpClient construction.
1 parent d82d40d commit 845154a

File tree

8 files changed

+51
-11
lines changed

8 files changed

+51
-11
lines changed

app/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ dependencies {
121121
implementation(libs.androidx.lifecycle.runtime.ktx)
122122
implementation(libs.androidx.lifecycle.service)
123123
implementation(libs.androidx.media3.session)
124+
implementation(libs.androidx.media3.datasource)
125+
implementation(libs.androidx.media3.datasource.okhttp)
124126
implementation(libs.androidx.paging.runtime.ktx)
125127
implementation(libs.androidx.preference.ktx)
126128
implementation(libs.androidx.recyclerview)

app/src/main/java/de/maniac103/squeezeclient/SqueezeClientApplication.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,30 @@ import com.google.android.material.color.DynamicColors
2525
import com.markodevcic.peko.PermissionRequester
2626
import de.maniac103.squeezeclient.cometd.ConnectionHelper
2727
import de.maniac103.squeezeclient.extfuncs.prefs
28+
import de.maniac103.squeezeclient.extfuncs.serverConfig
2829
import kotlinx.serialization.json.Json
30+
import okhttp3.OkHttpClient
2931

3032
class SqueezeClientApplication : Application(), SharedPreferences.OnSharedPreferenceChangeListener {
3133
val json = Json {
3234
coerceInputValues = true
3335
ignoreUnknownKeys = true
3436
}
37+
val httpClient = OkHttpClient.Builder()
38+
.addInterceptor { chain ->
39+
val request = chain.request()
40+
val serverConfig = prefs.serverConfig
41+
val authHeader = serverConfig?.credentialsAsAuthorizationHeader
42+
val actualRequest = when {
43+
request.url.host == serverConfig?.url?.host && authHeader != null ->
44+
request.newBuilder().addHeader("Authorization", authHeader).build()
45+
46+
else -> request
47+
}
48+
chain.proceed(actualRequest)
49+
}
50+
.followRedirects(true)
51+
.build()
3552
val connectionHelper = ConnectionHelper(this)
3653

3754
override fun onCreate() {

app/src/main/java/de/maniac103/squeezeclient/cometd/CometdClient.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,12 @@ import okhttp3.RequestBody.Companion.toRequestBody
6161
import okhttp3.ResponseBody
6262
import okhttp3.logging.HttpLoggingInterceptor
6363

64-
class CometdClient(private val json: Json, private val serverConfig: ServerConfiguration) {
65-
private val requestClient = OkHttpClient.Builder()
64+
class CometdClient(
65+
private val httpClient: OkHttpClient,
66+
private val json: Json,
67+
private val serverConfig: ServerConfiguration
68+
) {
69+
private val requestClient = httpClient.newBuilder()
6670
.apply {
6771
if (HTTP_LOGGING_LEVEL != HttpLoggingInterceptor.Level.NONE) {
6872
val logger = HttpLoggingInterceptor.Logger { message -> Log.d(TAG, message) }
@@ -177,7 +181,7 @@ class CometdClient(private val json: Json, private val serverConfig: ServerConfi
177181
put("id", nextId++)
178182
}
179183
val request = buildRequest(connectMessage, metaSubscribeMessage)
180-
val subscriptionClient = OkHttpClient.Builder()
184+
val subscriptionClient = httpClient.newBuilder()
181185
.readTimeout(listenTimeout.inWholeMilliseconds, TimeUnit.MILLISECONDS)
182186
.build()
183187
val body = withContext(Dispatchers.IO) {

app/src/main/java/de/maniac103/squeezeclient/cometd/ConnectionHelper.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ class ConnectionHelper(private val appContext: SqueezeClientApplication) {
123123
return
124124
}
125125
val prefs = appContext.prefs
126-
val client = prefs.serverConfig?.let { CometdClient(json, it) }
126+
val client = prefs.serverConfig?.let { CometdClient(appContext.httpClient, json, it) }
127127
?: return
128128

129129
this.client = client

app/src/main/java/de/maniac103/squeezeclient/extfuncs/ContextExtensions.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,7 @@ val Context.connectionHelper get() =
2626
(applicationContext as SqueezeClientApplication).connectionHelper
2727
val Context.jsonParser get() =
2828
(applicationContext as SqueezeClientApplication).json
29+
val Context.httpClient get() =
30+
(applicationContext as SqueezeClientApplication).httpClient
2931
val Context.prefs: SharedPreferences get() =
3032
PreferenceManager.getDefaultSharedPreferences(this)

app/src/main/java/de/maniac103/squeezeclient/service/DownloadWorker.kt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import androidx.work.workDataOf
4040
import de.maniac103.squeezeclient.R
4141
import de.maniac103.squeezeclient.extfuncs.DownloadFolderStructure
4242
import de.maniac103.squeezeclient.extfuncs.downloadFolderStructure
43+
import de.maniac103.squeezeclient.extfuncs.httpClient
4344
import de.maniac103.squeezeclient.extfuncs.jsonParser
4445
import de.maniac103.squeezeclient.extfuncs.prefs
4546
import de.maniac103.squeezeclient.extfuncs.serverConfig
@@ -52,7 +53,6 @@ import kotlinx.coroutines.launch
5253
import kotlinx.coroutines.withContext
5354
import kotlinx.datetime.Clock
5455
import kotlinx.serialization.encodeToString
55-
import okhttp3.OkHttpClient
5656
import okhttp3.Request
5757
import okhttp3.ResponseBody
5858
import okio.Buffer
@@ -73,8 +73,7 @@ class DownloadWorker(
7373
val serverConfig = applicationContext.prefs.serverConfig
7474
?: return Result.failure()
7575
val baseUrl = serverConfig.url
76-
val authorizationHeader = serverConfig.credentialsAsAuthorizationHeader
77-
val client = OkHttpClient.Builder().build()
76+
val client = applicationContext.httpClient
7877
val resolver = applicationContext.contentResolver
7978
val folderStructure = applicationContext.prefs.downloadFolderStructure
8079

@@ -91,10 +90,9 @@ class DownloadWorker(
9190
.addPathSegment(item.trackId.toString())
9291
.addPathSegment("download")
9392
.build()
94-
val request = Request.Builder().apply {
95-
url(songUrl)
96-
authorizationHeader?.let { addHeader("Authorization", it) }
97-
}.build()
93+
val request = Request.Builder()
94+
.url(songUrl)
95+
.build()
9896

9997
withContext(Dispatchers.IO) {
10098
val response = client.newCall(request).execute()

app/src/main/java/de/maniac103/squeezeclient/service/MediaService.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ import androidx.media3.common.MediaMetadata
4040
import androidx.media3.common.Player
4141
import androidx.media3.common.SimpleBasePlayer
4242
import androidx.media3.common.util.UnstableApi
43+
import androidx.media3.datasource.DataSourceBitmapLoader
44+
import androidx.media3.datasource.DefaultDataSource
45+
import androidx.media3.datasource.okhttp.OkHttpDataSource
46+
import androidx.media3.session.CacheBitmapLoader
4347
import androidx.media3.session.CommandButton
4448
import androidx.media3.session.MediaSession
4549
import androidx.media3.session.MediaSession.ConnectionResult
@@ -52,6 +56,7 @@ import de.maniac103.squeezeclient.cometd.ConnectionHelper
5256
import de.maniac103.squeezeclient.cometd.ConnectionState
5357
import de.maniac103.squeezeclient.cometd.request.PlaybackButtonRequest
5458
import de.maniac103.squeezeclient.extfuncs.connectionHelper
59+
import de.maniac103.squeezeclient.extfuncs.httpClient
5560
import de.maniac103.squeezeclient.extfuncs.lastSelectedPlayer
5661
import de.maniac103.squeezeclient.extfuncs.prefs
5762
import de.maniac103.squeezeclient.model.PagingParams
@@ -122,10 +127,20 @@ class MediaService : MediaSessionService(), LifecycleOwner, MediaSession.Callbac
122127
Intent(this, MainActivity::class.java).setAction(Intent.ACTION_MAIN),
123128
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
124129
)
130+
131+
val dataSourceFactory = DefaultDataSource.Factory(
132+
this,
133+
OkHttpDataSource.Factory(httpClient)
134+
)
135+
val bitmapLoader = DataSourceBitmapLoader(
136+
DataSourceBitmapLoader.DEFAULT_EXECUTOR_SERVICE.get(),
137+
dataSourceFactory
138+
)
125139
mediaSession = MediaSession.Builder(this, player)
126140
.setCallback(this)
127141
.setCustomLayout(listOf(powerButton, disconnectButton))
128142
.setSessionActivity(activityIntent)
143+
.setBitmapLoader(CacheBitmapLoader(bitmapLoader))
129144
.build()
130145
addSession(mediaSession)
131146
}

gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ androidx-lifecycle-service = { module = "androidx.lifecycle:lifecycle-service",
4949
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" }
5050
androidx-material-icons-extended-android = { module = "androidx.compose.material:material-icons-extended-android", version.ref = "androidx-compose-material" }
5151
androidx-media3-session = { module = "androidx.media3:media3-session", version.ref = "androidx-media3" }
52+
androidx-media3-datasource = { module = "androidx.media3:media3-datasource", version.ref = "androidx-media3" }
53+
androidx-media3-datasource-okhttp = { module = "androidx.media3:media3-datasource-okhttp", version.ref = "androidx-media3" }
5254
androidx-paging-runtime-ktx = { module = "androidx.paging:paging-runtime-ktx", version.ref = "androidx-paging" }
5355
androidx-preference-ktx = { module = "androidx.preference:preference-ktx", version.ref = "androidx-preference" }
5456
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "androidx-recyclerview" }

0 commit comments

Comments
 (0)