mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2026-08-28 06:14:00 +02:00
Fix:Check local library item is linked to a server item before sending playback session progress sync to server
This commit is contained in:
@@ -2,13 +2,11 @@ package com.audiobookshelf.app.data
|
|||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.support.v4.media.MediaMetadataCompat
|
import android.support.v4.media.MediaMetadataCompat
|
||||||
import androidx.core.app.NotificationCompat
|
|
||||||
import com.audiobookshelf.app.R
|
import com.audiobookshelf.app.R
|
||||||
import com.audiobookshelf.app.device.DeviceManager
|
import com.audiobookshelf.app.device.DeviceManager
|
||||||
import com.audiobookshelf.app.player.MediaProgressSyncData
|
import com.audiobookshelf.app.player.MediaProgressSyncData
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore
|
import com.fasterxml.jackson.annotation.JsonIgnore
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
|
||||||
import com.google.android.exoplayer2.C
|
|
||||||
import com.google.android.exoplayer2.MediaItem
|
import com.google.android.exoplayer2.MediaItem
|
||||||
import com.google.android.exoplayer2.MediaMetadata
|
import com.google.android.exoplayer2.MediaMetadata
|
||||||
import com.google.android.gms.cast.MediaInfo
|
import com.google.android.gms.cast.MediaInfo
|
||||||
@@ -68,7 +66,7 @@ class PlaybackSession(
|
|||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
fun getCurrentTrackIndex():Int {
|
fun getCurrentTrackIndex():Int {
|
||||||
for (i in 0..(audioTracks.size - 1)) {
|
for (i in 0..(audioTracks.size - 1)) {
|
||||||
var track = audioTracks[i]
|
val track = audioTracks[i]
|
||||||
if (currentTimeMs >= track.startOffsetMs && (track.endOffsetMs) > currentTimeMs) {
|
if (currentTimeMs >= track.startOffsetMs && (track.endOffsetMs) > currentTimeMs) {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
@@ -78,14 +76,14 @@ class PlaybackSession(
|
|||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
fun getCurrentTrackTimeMs():Long {
|
fun getCurrentTrackTimeMs():Long {
|
||||||
var currentTrack = audioTracks[this.getCurrentTrackIndex()]
|
val currentTrack = audioTracks[this.getCurrentTrackIndex()]
|
||||||
var time = currentTime - currentTrack.startOffset
|
val time = currentTime - currentTrack.startOffset
|
||||||
return (time * 1000L).toLong()
|
return (time * 1000L).toLong()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
fun getTrackStartOffsetMs(index:Int):Long {
|
fun getTrackStartOffsetMs(index:Int):Long {
|
||||||
var currentTrack = audioTracks[index]
|
val currentTrack = audioTracks[index]
|
||||||
return (currentTrack.startOffset * 1000L).toLong()
|
return (currentTrack.startOffset * 1000L).toLong()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +110,7 @@ class PlaybackSession(
|
|||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
fun getMediaMetadataCompat(): MediaMetadataCompat {
|
fun getMediaMetadataCompat(): MediaMetadataCompat {
|
||||||
var metadataBuilder = MediaMetadataCompat.Builder()
|
val metadataBuilder = MediaMetadataCompat.Builder()
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, displayTitle)
|
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, displayTitle)
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, displayTitle)
|
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, displayTitle)
|
||||||
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, displayAuthor)
|
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, displayAuthor)
|
||||||
@@ -125,14 +123,14 @@ class PlaybackSession(
|
|||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
fun getExoMediaMetadata(audioTrack:AudioTrack): MediaMetadata {
|
fun getExoMediaMetadata(audioTrack:AudioTrack): MediaMetadata {
|
||||||
var metadataBuilder = MediaMetadata.Builder()
|
val metadataBuilder = MediaMetadata.Builder()
|
||||||
.setTitle(displayTitle)
|
.setTitle(displayTitle)
|
||||||
.setDisplayTitle(displayTitle)
|
.setDisplayTitle(displayTitle)
|
||||||
.setArtist(displayAuthor)
|
.setArtist(displayAuthor)
|
||||||
.setAlbumArtist(displayAuthor)
|
.setAlbumArtist(displayAuthor)
|
||||||
.setSubtitle(displayAuthor)
|
.setSubtitle(displayAuthor)
|
||||||
|
|
||||||
var contentUri = this.getContentUri(audioTrack)
|
val contentUri = this.getContentUri(audioTrack)
|
||||||
metadataBuilder.setMediaUri(contentUri)
|
metadataBuilder.setMediaUri(contentUri)
|
||||||
|
|
||||||
return metadataBuilder.build()
|
return metadataBuilder.build()
|
||||||
@@ -140,15 +138,15 @@ class PlaybackSession(
|
|||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
fun getMediaItems():List<MediaItem> {
|
fun getMediaItems():List<MediaItem> {
|
||||||
var mediaItems:MutableList<MediaItem> = mutableListOf()
|
val mediaItems:MutableList<MediaItem> = mutableListOf()
|
||||||
|
|
||||||
for (audioTrack in audioTracks) {
|
for (audioTrack in audioTracks) {
|
||||||
var mediaMetadata = this.getExoMediaMetadata(audioTrack)
|
val mediaMetadata = this.getExoMediaMetadata(audioTrack)
|
||||||
var mediaUri = this.getContentUri(audioTrack)
|
val mediaUri = this.getContentUri(audioTrack)
|
||||||
var mimeType = audioTrack.mimeType
|
val mimeType = audioTrack.mimeType
|
||||||
|
|
||||||
var queueItem = getQueueItem(audioTrack) // Queue item used in exo player CastManager
|
val queueItem = getQueueItem(audioTrack) // Queue item used in exo player CastManager
|
||||||
var mediaItem = MediaItem.Builder().setUri(mediaUri).setTag(queueItem).setMediaMetadata(mediaMetadata).setMimeType(mimeType).build()
|
val mediaItem = MediaItem.Builder().setUri(mediaUri).setTag(queueItem).setMediaMetadata(mediaMetadata).setMimeType(mimeType).build()
|
||||||
mediaItems.add(mediaItem)
|
mediaItems.add(mediaItem)
|
||||||
}
|
}
|
||||||
return mediaItems
|
return mediaItems
|
||||||
@@ -156,7 +154,7 @@ class PlaybackSession(
|
|||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
fun getCastMediaMetadata(audioTrack:AudioTrack):com.google.android.gms.cast.MediaMetadata {
|
fun getCastMediaMetadata(audioTrack:AudioTrack):com.google.android.gms.cast.MediaMetadata {
|
||||||
var castMetadata = com.google.android.gms.cast.MediaMetadata(com.google.android.gms.cast.MediaMetadata.MEDIA_TYPE_AUDIOBOOK_CHAPTER)
|
val castMetadata = com.google.android.gms.cast.MediaMetadata(com.google.android.gms.cast.MediaMetadata.MEDIA_TYPE_AUDIOBOOK_CHAPTER)
|
||||||
|
|
||||||
coverPath?.let {
|
coverPath?.let {
|
||||||
castMetadata.addImage(WebImage(Uri.parse("$serverAddress/api/items/$libraryItemId/cover?token=${DeviceManager.token}")))
|
castMetadata.addImage(WebImage(Uri.parse("$serverAddress/api/items/$libraryItemId/cover?token=${DeviceManager.token}")))
|
||||||
@@ -171,11 +169,11 @@ class PlaybackSession(
|
|||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
fun getQueueItem(audioTrack:AudioTrack):MediaQueueItem {
|
fun getQueueItem(audioTrack:AudioTrack):MediaQueueItem {
|
||||||
var castMetadata = getCastMediaMetadata(audioTrack)
|
val castMetadata = getCastMediaMetadata(audioTrack)
|
||||||
|
|
||||||
var mediaUri = getContentUri(audioTrack)
|
val mediaUri = getContentUri(audioTrack)
|
||||||
|
|
||||||
var mediaInfo = MediaInfo.Builder(mediaUri.toString()).apply {
|
val mediaInfo = MediaInfo.Builder(mediaUri.toString()).apply {
|
||||||
setContentUrl(mediaUri.toString())
|
setContentUrl(mediaUri.toString())
|
||||||
setContentType(audioTrack.mimeType)
|
setContentType(audioTrack.mimeType)
|
||||||
setMetadata(castMetadata)
|
setMetadata(castMetadata)
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class MediaProgressSyncer(val playerNotificationService:PlayerNotificationServic
|
|||||||
listeningTimerTask = Timer("ListeningTimer", false).schedule(0L, 5000L) {
|
listeningTimerTask = Timer("ListeningTimer", false).schedule(0L, 5000L) {
|
||||||
Handler(Looper.getMainLooper()).post() {
|
Handler(Looper.getMainLooper()).post() {
|
||||||
if (playerNotificationService.currentPlayer.isPlaying) {
|
if (playerNotificationService.currentPlayer.isPlaying) {
|
||||||
var currentTime = playerNotificationService.getCurrentTimeSeconds()
|
val currentTime = playerNotificationService.getCurrentTimeSeconds()
|
||||||
sync(currentTime)
|
sync(currentTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,20 +63,20 @@ class MediaProgressSyncer(val playerNotificationService:PlayerNotificationServic
|
|||||||
if (!listeningTimerRunning) return
|
if (!listeningTimerRunning) return
|
||||||
Log.d(tag, "stop: Stopping listening for $currentDisplayTitle")
|
Log.d(tag, "stop: Stopping listening for $currentDisplayTitle")
|
||||||
|
|
||||||
var currentTime = playerNotificationService.getCurrentTimeSeconds()
|
val currentTime = playerNotificationService.getCurrentTimeSeconds()
|
||||||
sync(currentTime)
|
sync(currentTime)
|
||||||
reset()
|
reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sync(currentTime:Double) {
|
fun sync(currentTime:Double) {
|
||||||
var diffSinceLastSync = System.currentTimeMillis() - lastSyncTime
|
val diffSinceLastSync = System.currentTimeMillis() - lastSyncTime
|
||||||
if (diffSinceLastSync < 1000L) {
|
if (diffSinceLastSync < 1000L) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var listeningTimeToAdd = diffSinceLastSync / 1000L
|
val listeningTimeToAdd = diffSinceLastSync / 1000L
|
||||||
lastSyncTime = System.currentTimeMillis()
|
lastSyncTime = System.currentTimeMillis()
|
||||||
|
|
||||||
var syncData = MediaProgressSyncData(listeningTimeToAdd,currentPlaybackDuration,currentTime)
|
val syncData = MediaProgressSyncData(listeningTimeToAdd,currentPlaybackDuration,currentTime)
|
||||||
|
|
||||||
currentPlaybackSession?.syncData(syncData)
|
currentPlaybackSession?.syncData(syncData)
|
||||||
if (currentIsLocal) {
|
if (currentIsLocal) {
|
||||||
@@ -85,10 +85,16 @@ class MediaProgressSyncer(val playerNotificationService:PlayerNotificationServic
|
|||||||
DeviceManager.dbManager.saveLocalPlaybackSession(it)
|
DeviceManager.dbManager.saveLocalPlaybackSession(it)
|
||||||
saveLocalProgress(it)
|
saveLocalProgress(it)
|
||||||
|
|
||||||
// Send sync to server also if connected to this server and local item belongs to this server
|
// Local library item is linked to a server library item
|
||||||
if (it.serverConnectionConfigId != null && DeviceManager.serverConnectionConfig?.id == it.serverConnectionConfigId) {
|
if (!it.libraryItemId.isNullOrEmpty()) {
|
||||||
apiHandler.sendLocalProgressSync(it) {
|
// Send sync to server also if connected to this server and local item belongs to this server
|
||||||
Log.d(tag, "Local progress sync data sent to server $currentDisplayTitle for time $currentTime")
|
if (it.serverConnectionConfigId != null && DeviceManager.serverConnectionConfig?.id == it.serverConnectionConfigId) {
|
||||||
|
apiHandler.sendLocalProgressSync(it) {
|
||||||
|
Log.d(
|
||||||
|
tag,
|
||||||
|
"Local progress sync data sent to server $currentDisplayTitle for time $currentTime"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +107,7 @@ class MediaProgressSyncer(val playerNotificationService:PlayerNotificationServic
|
|||||||
|
|
||||||
private fun saveLocalProgress(playbackSession:PlaybackSession) {
|
private fun saveLocalProgress(playbackSession:PlaybackSession) {
|
||||||
if (currentLocalMediaProgress == null) {
|
if (currentLocalMediaProgress == null) {
|
||||||
var mediaProgress = DeviceManager.dbManager.getLocalMediaProgress(playbackSession.localMediaProgressId)
|
val mediaProgress = DeviceManager.dbManager.getLocalMediaProgress(playbackSession.localMediaProgressId)
|
||||||
if (mediaProgress == null) {
|
if (mediaProgress == null) {
|
||||||
currentLocalMediaProgress = playbackSession.getNewLocalMediaProgress()
|
currentLocalMediaProgress = playbackSession.getNewLocalMediaProgress()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user