Add:Android auto show currently reading

This commit is contained in:
advplyr
2021-12-11 19:49:22 -06:00
parent 6faa9b6324
commit a295889a52
4 changed files with 127 additions and 58 deletions
@@ -84,6 +84,7 @@ class Audiobook {
putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, getCover().toString())
putString(MediaMetadataCompat.METADATA_KEY_ART_URI, getCover().toString())
putString(MediaMetadataCompat.METADATA_KEY_AUTHOR, book.authorFL)
// val extras = Bundle()
// if (isDownloaded) {
// extras.putLong(
@@ -10,6 +10,7 @@ import com.getcapacitor.JSArray
import com.getcapacitor.JSObject
import com.jeep.plugin.capacitor.capacitordatastoragesqlite.CapacitorDataStorageSqlite
import okhttp3.*
import org.json.JSONArray
import java.io.IOException
class AudiobookManager {
@@ -29,6 +30,7 @@ class AudiobookManager {
lateinit var localMediaManager:LocalMediaManager
var audiobooks:MutableList<Audiobook> = mutableListOf()
var audiobooksInProgress:MutableList<Audiobook> = mutableListOf()
constructor(_ctx:Context, _client:OkHttpClient) {
ctx = _ctx
@@ -45,19 +47,9 @@ class AudiobookManager {
Log.d(tag, "SHARED PREF TOKEN $token")
}
fun loadAudiobooks(cb: (() -> Unit)) {
Log.d(tag, "LOAD AUDIBOOOSK $serverUrl | $token")
if (serverUrl == "" || token == "") {
Log.d(tag, "No Server or Token set")
cb()
return
} else if (!serverUrl.startsWith("http")) {
Log.e(tag, "Invalid server url $serverUrl")
cb()
return
}
var url = "$serverUrl/api/libraries/main/books/all"
fun loadCategories(cb: (() -> Unit)) {
Log.d(tag, "LOAD Categories $serverUrl | $token")
var url = "$serverUrl/api/libraries/main/categories"
val request = Request.Builder()
.url(url).addHeader("Authorization", "Bearer $token")
.build()
@@ -74,37 +66,108 @@ class AudiobookManager {
if (!response.isSuccessful) throw IOException("Unexpected code $response")
var bodyString = response.body!!.string()
var resJson = JSObject(bodyString)
var results = resJson.getJSONArray("results")
var results = JSONArray(bodyString)
// var results = resJson.getJSONArray("results")
var totalBooks = results.length() - 1
for (i in 0..totalBooks) {
var abobj = results.get(i)
var jsobj = JSObject(abobj.toString())
jsobj.put("isDownloaded", false)
var audiobook = Audiobook(jsobj, serverUrl, token)
if (audiobook.isMissing || audiobook.isInvalid) {
Log.d(tag, "Audiobook ${audiobook.book.title} is missing or invalid")
} else if (audiobook.numTracks <= 0) {
Log.d(tag, "Audiobook ${audiobook.book.title} has audio tracks")
} else {
var audiobookExists = audiobooks.find { it.id == audiobook.id }
if (audiobookExists == null) {
audiobooks.add(audiobook)
} else {
Log.d(tag, "Audiobook already there from downloaded")
var totalShelves = results.length() - 1
Log.d(tag, "Got categories $totalShelves")
for (i in 0..totalShelves) {
var shelfobj = results.get(i)
var jsobj = JSObject(shelfobj.toString())
var shelfId = jsobj.getString("id", "")
Log.d(tag, "Category shelf id $shelfId")
if (shelfId == "continue-reading") {
var entities = jsobj.getJSONArray("entities")
var totalEntities = entities.length() - 1
Log.d(tag, "Shelf total entities $totalEntities")
for (y in 0..totalEntities) {
var abobj = entities.get(y)
Log.d(tag, "Shelf category ab id $y = ${abobj.toString()}")
var abjsobj = JSObject(abobj.toString())
abjsobj.put("isDownloaded", false)
var audiobook = Audiobook(abjsobj, serverUrl, token)
if (audiobook.isMissing || audiobook.isInvalid || audiobook.numTracks <= 0) {
Log.d(tag, "Not an audiobook or invalid/missing")
} else {
var audiobookExists = audiobooksInProgress.find { it.id == audiobook.id }
if (audiobookExists == null) {
audiobooksInProgress.add(audiobook)
}
}
}
}
}
Log.d(tag, "${audiobooks.size} Audiobooks Loaded")
Log.d(tag, "${audiobooksInProgress.size} Audiobooks In Progress Loaded")
cb()
}
}
})
}
fun loadAudiobooks(cb: (() -> Unit)) {
Log.d(tag, "LOAD AUDIBOOOSK $serverUrl | $token")
if (serverUrl == "" || token == "") {
Log.d(tag, "No Server or Token set")
cb()
return
} else if (!serverUrl.startsWith("http")) {
Log.e(tag, "Invalid server url $serverUrl")
cb()
return
}
// First load currently reading
loadCategories() {
// Then load all
var url = "$serverUrl/api/libraries/main/books/all"
val request = Request.Builder()
.url(url).addHeader("Authorization", "Bearer $token")
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.d(tag, "FAILURE TO CONNECT")
e.printStackTrace()
cb()
}
override fun onResponse(call: Call, response: Response) {
response.use {
if (!response.isSuccessful) throw IOException("Unexpected code $response")
var bodyString = response.body!!.string()
var resJson = JSObject(bodyString)
var results = resJson.getJSONArray("results")
var totalBooks = results.length() - 1
for (i in 0..totalBooks) {
var abobj = results.get(i)
var jsobj = JSObject(abobj.toString())
jsobj.put("isDownloaded", false)
var audiobook = Audiobook(jsobj, serverUrl, token)
if (audiobook.isMissing || audiobook.isInvalid) {
Log.d(tag, "Audiobook ${audiobook.book.title} is missing or invalid")
} else if (audiobook.numTracks <= 0) {
Log.d(tag, "Audiobook ${audiobook.book.title} has audio tracks")
} else {
var audiobookExists = audiobooks.find { it.id == audiobook.id }
if (audiobookExists == null) {
audiobooks.add(audiobook)
} else {
Log.d(tag, "Audiobook already there from downloaded")
}
}
}
Log.d(tag, "${audiobooks.size} Audiobooks Loaded")
cb()
}
}
})
}
}
fun load() {
isLoading = true
hasLoaded = true
@@ -10,6 +10,7 @@ import androidx.annotation.AnyRes
class BrowseTree(
val context: Context,
val audiobooksInProgress: List<Audiobook>,
val audiobooks: List<Audiobook>,
val localAudio: List<LocalMediaManager.LocalAudio>,
val recentMediaId: String? = null
@@ -33,6 +34,13 @@ class BrowseTree(
init {
val rootList = mediaIdToChildren[AUTO_BROWSE_ROOT] ?: mutableListOf()
val continueReadingMetadata = MediaMetadataCompat.Builder().apply {
putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, CONTINUE_ROOT)
putString(MediaMetadataCompat.METADATA_KEY_TITLE, "Reading")
putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, getUriToDrawable(context, R.drawable.exo_icon_localaudio).toString())
}.build()
val allMetadata = MediaMetadataCompat.Builder().apply {
putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, ALL_ROOT)
putString(MediaMetadataCompat.METADATA_KEY_TITLE, "Audiobooks")
@@ -42,6 +50,7 @@ class BrowseTree(
putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, resource)
}.build()
val downloadsMetadata = MediaMetadataCompat.Builder().apply {
putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, DOWNLOADS_ROOT)
putString(MediaMetadataCompat.METADATA_KEY_TITLE, "Downloads")
@@ -54,11 +63,20 @@ class BrowseTree(
putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, getUriToDrawable(context, R.drawable.exo_icon_localaudio).toString())
}.build()
if (audiobooksInProgress.isNotEmpty()) {
rootList += continueReadingMetadata
}
rootList += allMetadata
rootList += downloadsMetadata
rootList += localsMetadata
mediaIdToChildren[AUTO_BROWSE_ROOT] = rootList
audiobooksInProgress.forEach { audiobook ->
val children = mediaIdToChildren[CONTINUE_ROOT] ?: mutableListOf()
children += audiobook.toMediaMetadata()
mediaIdToChildren[CONTINUE_ROOT] = children
}
audiobooks.forEach { audiobook ->
if (audiobook.isDownloaded) {
val downloadsChildren = mediaIdToChildren[DOWNLOADS_ROOT] ?: mutableListOf()
@@ -83,5 +101,6 @@ class BrowseTree(
const val AUTO_BROWSE_ROOT = "/"
const val ALL_ROOT = "__ALL__"
const val CONTINUE_ROOT = "__CONTINUE__"
const val DOWNLOADS_ROOT = "__DOWNLOADS__"
const val LOCAL_ROOT = "__LOCAL__"
@@ -31,6 +31,7 @@ import com.bumptech.glide.request.RequestOptions
import com.getcapacitor.JSObject
import com.getcapacitor.PluginCall
import com.google.android.exoplayer2.*
import com.google.android.exoplayer2.MediaMetadata
import com.google.android.exoplayer2.audio.AudioAttributes
import com.google.android.exoplayer2.ext.cast.CastPlayer
import com.google.android.exoplayer2.ext.cast.SessionAvailabilityListener
@@ -42,10 +43,10 @@ import com.google.android.exoplayer2.source.hls.HlsMediaSource
import com.google.android.exoplayer2.ui.PlayerNotificationManager
import com.google.android.exoplayer2.upstream.*
import com.google.android.exoplayer2.util.MimeTypes
import com.google.android.gms.cast.*
import com.google.android.gms.cast.Cast.MessageReceivedCallback
import com.google.android.gms.cast.CastDevice
import com.google.android.gms.cast.CastMediaControlIntent
import com.google.android.gms.cast.framework.*
import com.google.android.gms.cast.framework.media.MediaQueue
import kotlinx.coroutines.*
import okhttp3.OkHttpClient
import org.json.JSONObject
@@ -69,7 +70,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
fun onMetadata(metadata: JSObject)
fun onPrepare(audiobookId: String, playWhenReady: Boolean)
fun onSleepTimerEnded(currentPosition: Long)
fun onSleepTimerSet(sleepTimerEndTime:Long)
fun onSleepTimerSet(sleepTimerEndTime: Long)
}
private val tag = "PlayerService"
@@ -303,7 +304,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
}
Log.d(tag, "Media Session Set")
val mediaController = MediaControllerCompat(ctx, mediaSession.sessionToken)
@@ -916,10 +916,10 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, true)
extras.putInt(
MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE,
MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM)
MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM)
extras.putInt(
MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE,
MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM)
MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM)
BrowserRoot(AUTO_MEDIA_ROOT, extras)
}
@@ -937,7 +937,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
audiobookManager.isLoading = false
Log.d(tag, "LOADED AUDIOBOOKS")
browseTree = BrowseTree(this, audiobookManager.audiobooks, audiobookManager.localMediaManager.localAudioFiles, null)
browseTree = BrowseTree(this, audiobookManager.audiobooksInProgress, audiobookManager.audiobooks, audiobookManager.localMediaManager.localAudioFiles, null)
val children = browseTree[parentMediaId]?.map { item ->
MediaBrowserCompat.MediaItem(item.description, flag)
}
@@ -990,7 +990,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
audiobookManager.isLoading = false
Log.d(tag, "LOADED AUDIOBOOKS")
browseTree = BrowseTree(this, audiobookManager.audiobooks, audiobookManager.localMediaManager.localAudioFiles, null)
browseTree = BrowseTree(this, audiobookManager.audiobooksInProgress, audiobookManager.audiobooks, audiobookManager.localMediaManager.localAudioFiles, null)
val children = browseTree[ALL_ROOT]?.map { item ->
MediaBrowserCompat.MediaItem(item.description, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)
}
@@ -1149,7 +1149,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
if (sleepTimerRunning || sleepTimerFinishedAt > 0L) checkShouldExtendSleepTimer()
}
fun increaseSleepTime(time:Long) {
fun increaseSleepTime(time: Long) {
Log.d(tag, "Increase Sleep time $time")
if (!sleepTimerRunning) return
var newSleepEndTime = sleepTimerEndTime + time
@@ -1162,7 +1162,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
listener?.onSleepTimerSet(sleepTimerEndTime)
}
fun decreaseSleepTime(time:Long) {
fun decreaseSleepTime(time: Long) {
Log.d(tag, "Decrease Sleep time $time")
if (!sleepTimerRunning) return
var newSleepEndTime = sleepTimerEndTime - time
@@ -1488,20 +1488,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
setSessionAvailabilityListener(CastSessionAvailabilityListener())
addListener(getPlayerListener())
}
currentPlayer = castPlayer as CastPlayer
if (currentAudiobookStreamData != null) {
var mimeType = MimeTypes.AUDIO_AAC
val mediaItem: MediaItem = MediaItem.Builder()
.setUri(currentAudiobookStreamData!!.contentUri)
.setMediaId(currentAudiobookStreamData!!.id).setMimeType(mimeType)
// .setTag(metadata)
.build()
castPlayer?.setMediaItem(mediaItem, currentAudiobookStreamData!!.startTime)
}
Log.d(tag, "CAST Cast Player Applied")
} catch (e: Exception) {
// We wouldn't normally catch the generic `Exception` however