diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index a920a5b0..4aca42b6 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -92,6 +92,16 @@
+
+
+
+
diff --git a/android/app/src/main/java/com/audiobookshelf/app/MediaPlayerWidget.kt b/android/app/src/main/java/com/audiobookshelf/app/MediaPlayerWidget.kt
index dbd98c75..79477aa1 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/MediaPlayerWidget.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/MediaPlayerWidget.kt
@@ -77,7 +77,7 @@ internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManage
views.setOnClickPendingIntent(R.id.widgetBackground, wholeWidgetClickPI)
- val imageUri = playbackSession?.getCoverUri() ?: Uri.parse("android.resource://${BuildConfig.APPLICATION_ID}/" + R.drawable.icon)
+ val imageUri = playbackSession?.getCoverUri(context) ?: Uri.parse("android.resource://${BuildConfig.APPLICATION_ID}/" + R.drawable.icon)
val awt: AppWidgetTarget = object : AppWidgetTarget(context.applicationContext, R.id.widgetAlbumArt, views, appWidgetId) {
override fun onResourceReady(resource: Bitmap, transition: Transition?) {
super.onResourceReady(resource, transition)
diff --git a/android/app/src/main/java/com/audiobookshelf/app/data/DataClasses.kt b/android/app/src/main/java/com/audiobookshelf/app/data/DataClasses.kt
index bbddbf77..f0ed55b4 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/data/DataClasses.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/data/DataClasses.kt
@@ -258,9 +258,9 @@ data class PodcastEpisode(
var localEpisodeId:String? // For Android Auto server episodes with local copy
) {
@JsonIgnore
- fun getMediaDescription(libraryItem:LibraryItemWrapper, progress:MediaProgressWrapper?, ctx: Context?): MediaDescriptionCompat {
+ fun getMediaDescription(libraryItem:LibraryItemWrapper, progress:MediaProgressWrapper?, ctx: Context): MediaDescriptionCompat {
val coverUri = if (libraryItem is LocalLibraryItem) {
- libraryItem.getCoverUri()
+ libraryItem.getCoverUri(ctx)
} else {
(libraryItem as LibraryItem).getCoverUri()
}
diff --git a/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt b/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt
index ffd70c03..b509c65d 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt
@@ -83,7 +83,7 @@ data class LocalFolder(
)
open class LibraryItemWrapper(var id:String) {
@JsonIgnore
- open fun getMediaDescription(progress:MediaProgressWrapper?, ctx: Context?): MediaDescriptionCompat { return MediaDescriptionCompat.Builder().build() }
+ open fun getMediaDescription(progress:MediaProgressWrapper?, ctx: Context): MediaDescriptionCompat { return MediaDescriptionCompat.Builder().build() }
}
@JsonIgnoreProperties(ignoreUnknown = true)
diff --git a/android/app/src/main/java/com/audiobookshelf/app/data/LibraryItem.kt b/android/app/src/main/java/com/audiobookshelf/app/data/LibraryItem.kt
index cc44cc17..9411b62b 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/data/LibraryItem.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/data/LibraryItem.kt
@@ -58,7 +58,7 @@ class LibraryItem(
}
@JsonIgnore
- override fun getMediaDescription(progress:MediaProgressWrapper?, ctx: Context?): MediaDescriptionCompat {
+ override fun getMediaDescription(progress:MediaProgressWrapper?, ctx: Context): MediaDescriptionCompat {
val extras = Bundle()
if (localLibraryItemId != null) {
diff --git a/android/app/src/main/java/com/audiobookshelf/app/data/LocalLibraryItem.kt b/android/app/src/main/java/com/audiobookshelf/app/data/LocalLibraryItem.kt
index f52d45df..d290b4fd 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/data/LocalLibraryItem.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/data/LocalLibraryItem.kt
@@ -9,6 +9,8 @@ import android.os.Bundle
import android.provider.MediaStore
import android.support.v4.media.MediaDescriptionCompat
import android.util.Log
+import androidx.core.content.FileProvider
+import androidx.core.net.toFile
import androidx.media.utils.MediaConstants
import com.audiobookshelf.app.BuildConfig
import com.audiobookshelf.app.R
@@ -46,7 +48,10 @@ class LocalLibraryItem(
val isPodcast get() = mediaType == "podcast"
@JsonIgnore
- fun getCoverUri(): Uri {
+ fun getCoverUri(ctx:Context): Uri {
+ if (coverContentUrl?.startsWith("file:") == true) {
+ return FileProvider.getUriForFile(ctx, "com.audiobookshelf.app.fileprovider", Uri.parse(coverContentUrl).toFile())
+ }
return if (coverContentUrl != null) Uri.parse(coverContentUrl) else Uri.parse("android.resource://${BuildConfig.APPLICATION_ID}/" + R.drawable.icon)
}
@@ -107,18 +112,16 @@ class LocalLibraryItem(
}
@JsonIgnore
- override fun getMediaDescription(progress:MediaProgressWrapper?, ctx:Context?): MediaDescriptionCompat {
- val coverUri = getCoverUri()
+ override fun getMediaDescription(progress:MediaProgressWrapper?, ctx:Context): MediaDescriptionCompat {
+ val coverUri = getCoverUri(ctx)
var bitmap:Bitmap? = null
if (coverContentUrl != null) {
- ctx?.let {
- bitmap = if (Build.VERSION.SDK_INT < 28) {
- MediaStore.Images.Media.getBitmap(it.contentResolver, coverUri)
- } else {
- val source: ImageDecoder.Source = ImageDecoder.createSource(it.contentResolver, coverUri)
- ImageDecoder.decodeBitmap(source)
- }
+ bitmap = if (Build.VERSION.SDK_INT < 28) {
+ MediaStore.Images.Media.getBitmap(ctx.contentResolver, coverUri)
+ } else {
+ val source: ImageDecoder.Source = ImageDecoder.createSource(ctx.contentResolver, coverUri)
+ ImageDecoder.decodeBitmap(source)
}
}
diff --git a/android/app/src/main/java/com/audiobookshelf/app/data/PlaybackSession.kt b/android/app/src/main/java/com/audiobookshelf/app/data/PlaybackSession.kt
index 06a1c923..2a5d4d74 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/data/PlaybackSession.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/data/PlaybackSession.kt
@@ -6,6 +6,8 @@ import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import android.support.v4.media.MediaMetadataCompat
+import androidx.core.content.FileProvider
+import androidx.core.net.toFile
import com.audiobookshelf.app.BuildConfig
import com.audiobookshelf.app.R
import com.audiobookshelf.app.device.DeviceManager
@@ -138,8 +140,15 @@ class PlaybackSession(
}
@JsonIgnore
- fun getCoverUri(): Uri {
- if (localLibraryItem?.coverContentUrl != null) return Uri.parse(localLibraryItem?.coverContentUrl) ?: Uri.parse("android.resource://${BuildConfig.APPLICATION_ID}/" + R.drawable.icon)
+ fun getCoverUri(ctx:Context): Uri {
+ if (localLibraryItem?.coverContentUrl != null) {
+ var coverUri = Uri.parse(localLibraryItem?.coverContentUrl.toString())
+ if (coverUri.toString().startsWith("file:")) {
+ coverUri = FileProvider.getUriForFile(ctx, "com.audiobookshelf.app.fileprovider", coverUri.toFile())
+ }
+
+ return coverUri ?: Uri.parse("android.resource://${BuildConfig.APPLICATION_ID}/" + R.drawable.icon)
+ }
if (coverPath == null) return Uri.parse("android.resource://${BuildConfig.APPLICATION_ID}/" + R.drawable.icon)
return Uri.parse("$serverAddress/api/items/$libraryItemId/cover?token=${DeviceManager.token}")
@@ -153,6 +162,8 @@ class PlaybackSession(
@JsonIgnore
fun getMediaMetadataCompat(ctx: Context): MediaMetadataCompat {
+ val coverUri = getCoverUri(ctx)
+
val metadataBuilder = MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, displayTitle)
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, displayTitle)
@@ -163,16 +174,16 @@ class PlaybackSession(
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ARTIST, displayAuthor)
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_DESCRIPTION, displayAuthor)
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, id)
- .putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, getCoverUri().toString())
- .putString(MediaMetadataCompat.METADATA_KEY_ART_URI, getCoverUri().toString())
- .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI, getCoverUri().toString())
+ .putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, coverUri.toString())
+ .putString(MediaMetadataCompat.METADATA_KEY_ART_URI, coverUri.toString())
+ .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI, coverUri.toString())
// Local covers get bitmap
if (localLibraryItem?.coverContentUrl != null) {
val bitmap = if (Build.VERSION.SDK_INT < 28) {
- MediaStore.Images.Media.getBitmap(ctx.contentResolver, getCoverUri())
+ MediaStore.Images.Media.getBitmap(ctx.contentResolver, coverUri)
} else {
- val source: ImageDecoder.Source = ImageDecoder.createSource(ctx.contentResolver, getCoverUri())
+ val source: ImageDecoder.Source = ImageDecoder.createSource(ctx.contentResolver, coverUri)
ImageDecoder.decodeBitmap(source)
}
metadataBuilder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, bitmap)
@@ -183,7 +194,9 @@ class PlaybackSession(
}
@JsonIgnore
- fun getExoMediaMetadata(): MediaMetadata {
+ fun getExoMediaMetadata(ctx:Context): MediaMetadata {
+ val coverUri = getCoverUri(ctx)
+
val metadataBuilder = MediaMetadata.Builder()
.setTitle(displayTitle)
.setDisplayTitle(displayTitle)
@@ -192,18 +205,18 @@ class PlaybackSession(
.setSubtitle(displayAuthor)
.setAlbumTitle(displayAuthor)
.setDescription(displayAuthor)
- .setArtworkUri(getCoverUri())
+ .setArtworkUri(coverUri)
.setMediaType(MediaMetadata.MEDIA_TYPE_AUDIO_BOOK)
return metadataBuilder.build()
}
@JsonIgnore
- fun getMediaItems():List {
+ fun getMediaItems(ctx:Context):List {
val mediaItems:MutableList = mutableListOf()
for (audioTrack in audioTracks) {
- val mediaMetadata = this.getExoMediaMetadata()
+ val mediaMetadata = this.getExoMediaMetadata(ctx)
val mediaUri = this.getContentUri(audioTrack)
val mimeType = audioTrack.mimeType
diff --git a/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt b/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt
index cabf36dd..3885c5f7 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt
@@ -9,10 +9,7 @@ import android.graphics.Color
import android.graphics.ImageDecoder
import android.hardware.Sensor
import android.hardware.SensorManager
-import android.net.ConnectivityManager
-import android.net.Network
-import android.net.NetworkCapabilities
-import android.net.NetworkRequest
+import android.net.*
import android.os.*
import android.provider.MediaStore
import android.provider.Settings
@@ -292,7 +289,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
return MediaDescriptionCompat.Builder().build()
}
- val coverUri = currentPlaybackSession!!.getCoverUri()
+ val coverUri = currentPlaybackSession!!.getCoverUri(ctx)
var bitmap: Bitmap? = null
// Local covers get bitmap
@@ -398,7 +395,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
val metadata = playbackSession.getMediaMetadataCompat(ctx)
mediaSession.setMetadata(metadata)
- val mediaItems = playbackSession.getMediaItems()
+ val mediaItems = playbackSession.getMediaItems(ctx)
val playbackRateToUse = playbackRate ?: initialPlaybackRate ?: 1f
initialPlaybackRate = playbackRate
@@ -501,7 +498,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
}
private fun setMediaSessionConnectorCustomActions(playbackSession:PlaybackSession) {
- val mediaItems = playbackSession.getMediaItems()
+ val mediaItems = playbackSession.getMediaItems(ctx)
val customActionProviders = mutableListOf(
JumpBackwardCustomActionProvider(),
JumpForwardCustomActionProvider(),
diff --git a/android/app/src/main/res/xml/file_paths.xml b/android/app/src/main/res/xml/file_paths.xml
index 782d63b9..e0098196 100644
--- a/android/app/src/main/res/xml/file_paths.xml
+++ b/android/app/src/main/res/xml/file_paths.xml
@@ -1,5 +1,4 @@
-
-
-
+
+