mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-08-28 13:58:23 +02:00
Fixing gradle dependency issues on android, minor warning fixes
This commit is contained in:
parent
379612d874
commit
f65f7b01c3
16 changed files with 94 additions and 131 deletions
|
@ -29,7 +29,7 @@ android {
|
||||||
applicationId "com.audiobookshelf.app"
|
applicationId "com.audiobookshelf.app"
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 61
|
versionCode 69
|
||||||
versionName "0.9.41-beta"
|
versionName "0.9.41-beta"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
aaptOptions {
|
aaptOptions {
|
||||||
|
@ -53,6 +53,20 @@ repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configurations.all {
|
||||||
|
resolutionStrategy {
|
||||||
|
force("com.google.android.gms:play-services-base:18.0.1")
|
||||||
|
force("androidx.appcompat:appcompat:$androidxAppCompatVersion")
|
||||||
|
force("androidx.core:core-ktx:$androidx_core_ktx_version")
|
||||||
|
force("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version")
|
||||||
|
force("androidx.media:media:$androidx_media_version")
|
||||||
|
force("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version")
|
||||||
|
force("org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version")
|
||||||
|
|
||||||
|
// failOnVersionConflict()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
||||||
|
@ -61,13 +75,12 @@ dependencies {
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
|
||||||
|
|
||||||
testImplementation "junit:junit:$junitVersion"
|
// testImplementation "junit:junit:$junitVersion"
|
||||||
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
// androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
||||||
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
// androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
||||||
implementation project(':capacitor-cordova-android-plugins')
|
implementation project(':capacitor-cordova-android-plugins')
|
||||||
|
|
||||||
implementation "androidx.core:core-ktx:$androidx_core_ktx_version"
|
implementation "androidx.core:core-ktx:$androidx_core_ktx_version"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
||||||
|
|
|
@ -12,7 +12,7 @@ class CastOptionsProvider : OptionsProvider {
|
||||||
override fun getCastOptions(context: Context): CastOptions {
|
override fun getCastOptions(context: Context): CastOptions {
|
||||||
Log.d("CastOptionsProvider", "getCastOptions")
|
Log.d("CastOptionsProvider", "getCastOptions")
|
||||||
var appId = "FD1F76C5"
|
var appId = "FD1F76C5"
|
||||||
var defaultId =CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID
|
// var defaultId =CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID
|
||||||
return CastOptions.Builder()
|
return CastOptions.Builder()
|
||||||
.setReceiverApplicationId(appId).setCastMediaOptions(
|
.setReceiverApplicationId(appId).setCastMediaOptions(
|
||||||
CastMediaOptions.Builder()
|
CastMediaOptions.Builder()
|
||||||
|
|
|
@ -5,7 +5,6 @@ import android.app.DownloadManager
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.*
|
import android.os.*
|
||||||
import android.os.StrictMode.VmPolicy
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import com.anggrayudi.storage.SimpleStorage
|
import com.anggrayudi.storage.SimpleStorage
|
||||||
|
@ -132,7 +131,7 @@ class MainActivity : BridgeActivity() {
|
||||||
|
|
||||||
fun stopMyService() {
|
fun stopMyService() {
|
||||||
if (mBounded) {
|
if (mBounded) {
|
||||||
mConnection?.let { unbindService(it) };
|
mConnection.let { unbindService(it) };
|
||||||
mBounded = false;
|
mBounded = false;
|
||||||
}
|
}
|
||||||
val stopIntent = Intent(this, PlayerNotificationService::class.java)
|
val stopIntent = Intent(this, PlayerNotificationService::class.java)
|
||||||
|
|
|
@ -105,7 +105,6 @@ class FolderScanner(var ctx: Context) {
|
||||||
var coverAbsolutePath:String? = null
|
var coverAbsolutePath:String? = null
|
||||||
|
|
||||||
var filesInFolder = itemFolder.search(false, DocumentFileType.FILE, arrayOf("audio/*", "image/*"))
|
var filesInFolder = itemFolder.search(false, DocumentFileType.FILE, arrayOf("audio/*", "image/*"))
|
||||||
var isPodcast = localFolder.mediaType == "podcast"
|
|
||||||
|
|
||||||
var existingLocalFilesRemoved = existingLocalFiles.filter { elf ->
|
var existingLocalFilesRemoved = existingLocalFiles.filter { elf ->
|
||||||
filesInFolder.find { fif -> DeviceManager.getBase64Id(fif.id) == elf.id } == null // File was not found in media item folder
|
filesInFolder.find { fif -> DeviceManager.getBase64Id(fif.id) == elf.id } == null // File was not found in media item folder
|
||||||
|
@ -116,8 +115,8 @@ class FolderScanner(var ctx: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
filesInFolder.forEach { file ->
|
filesInFolder.forEach { file ->
|
||||||
var mimeType = file?.mimeType ?: ""
|
var mimeType = file.mimeType ?: ""
|
||||||
var filename = file?.name ?: ""
|
var filename = file.name ?: ""
|
||||||
var isAudio = mimeType.startsWith("audio")
|
var isAudio = mimeType.startsWith("audio")
|
||||||
Log.d(tag, "Found $mimeType file $filename in folder $itemFolderName")
|
Log.d(tag, "Found $mimeType file $filename in folder $itemFolderName")
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ class CastManager constructor(val mainActivity:Activity) {
|
||||||
builder.setTitle(it.friendlyName)
|
builder.setTitle(it.friendlyName)
|
||||||
}
|
}
|
||||||
builder.setOnDismissListener { callback.onCancel() }
|
builder.setOnDismissListener { callback.onCancel() }
|
||||||
builder.setPositiveButton("Stop Casting") { dialog, which -> endSession(true, null) }
|
builder.setPositiveButton("Stop Casting") { _, _ -> endSession(true, null) }
|
||||||
builder.show()
|
builder.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,14 +286,14 @@ class CastManager constructor(val mainActivity:Activity) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSessionStartFailed(castSession: CastSession, errCode: Int) {
|
override fun onSessionStartFailed(castSession: CastSession, error: Int) {
|
||||||
if (callback.onSessionStartFailed(errCode)) {
|
if (callback.onSessionStartFailed(error)) {
|
||||||
getSessionManager()?.removeSessionManagerListener(this, CastSession::class.java)
|
getSessionManager()?.removeSessionManagerListener(this, CastSession::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSessionEnded(castSession: CastSession, errCode: Int) {
|
override fun onSessionEnded(castSession: CastSession, error: Int) {
|
||||||
if (callback.onSessionEndedBeforeStart(errCode)) {
|
if (callback.onSessionEndedBeforeStart(error)) {
|
||||||
getSessionManager()?.removeSessionManagerListener(this, CastSession::class.java)
|
getSessionManager()?.removeSessionManagerListener(this, CastSession::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ class CastPlayer(var castContext: CastContext) : BasePlayer() {
|
||||||
|
|
||||||
private fun toMediaQueueItem(mediaItem: MediaItem): MediaQueueItem {
|
private fun toMediaQueueItem(mediaItem: MediaItem): MediaQueueItem {
|
||||||
// The MediaQueueItem you build is expected to be in the tag.
|
// The MediaQueueItem you build is expected to be in the tag.
|
||||||
return (mediaItem.playbackProperties!!.tag as MediaQueueItem?)!!
|
return (mediaItem.localConfiguration!!.tag as MediaQueueItem?)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmName("setRemoteMediaClient1")
|
@JvmName("setRemoteMediaClient1")
|
||||||
|
@ -373,7 +373,6 @@ class CastPlayer(var castContext: CastContext) : BasePlayer() {
|
||||||
listeners.queueEvent(
|
listeners.queueEvent(
|
||||||
EVENT_POSITION_DISCONTINUITY
|
EVENT_POSITION_DISCONTINUITY
|
||||||
) { listener: Listener ->
|
) { listener: Listener ->
|
||||||
listener.onPositionDiscontinuity(DISCONTINUITY_REASON_AUTO_TRANSITION)
|
|
||||||
listener.onPositionDiscontinuity(
|
listener.onPositionDiscontinuity(
|
||||||
oldPosition, newPosition, DISCONTINUITY_REASON_AUTO_TRANSITION)
|
oldPosition, newPosition, DISCONTINUITY_REASON_AUTO_TRANSITION)
|
||||||
}
|
}
|
||||||
|
@ -385,9 +384,6 @@ class CastPlayer(var castContext: CastContext) : BasePlayer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (updateTracksAndSelectionsAndNotifyIfChanged()) {
|
if (updateTracksAndSelectionsAndNotifyIfChanged()) {
|
||||||
listeners.queueEvent(
|
|
||||||
EVENT_TRACKS_CHANGED
|
|
||||||
) { listener: Listener -> listener.onTracksChanged(currentTrackGroups, currentTrackSelections) }
|
|
||||||
listeners.queueEvent(
|
listeners.queueEvent(
|
||||||
EVENT_TRACKS_CHANGED) { listener: Listener -> listener.onTracksInfoChanged(currentTracksInfo) }
|
EVENT_TRACKS_CHANGED) { listener: Listener -> listener.onTracksInfoChanged(currentTracksInfo) }
|
||||||
}
|
}
|
||||||
|
@ -640,8 +636,6 @@ class CastPlayer(var castContext: CastContext) : BasePlayer() {
|
||||||
pendingSeekWindowIndex = C.INDEX_UNSET
|
pendingSeekWindowIndex = C.INDEX_UNSET
|
||||||
pendingSeekPositionMs = C.TIME_UNSET
|
pendingSeekPositionMs = C.TIME_UNSET
|
||||||
|
|
||||||
|
|
||||||
listeners.sendEvent( /* eventFlag= */C.INDEX_UNSET) { obj: Player.Listener -> obj.onSeekProcessed() }
|
|
||||||
// Playback state change will send metadata to client and stop seek loading
|
// Playback state change will send metadata to client and stop seek loading
|
||||||
listeners.sendEvent(EVENT_PLAYBACK_STATE_CHANGED) { obj: Player.Listener -> obj.onPlaybackStateChanged(currentPlaybackState) }
|
listeners.sendEvent(EVENT_PLAYBACK_STATE_CHANGED) { obj: Player.Listener -> obj.onPlaybackStateChanged(currentPlaybackState) }
|
||||||
}
|
}
|
||||||
|
@ -651,27 +645,27 @@ class CastPlayer(var castContext: CastContext) : BasePlayer() {
|
||||||
|
|
||||||
// We assume the default position is 0. There is no support for seeking to the default position
|
// We assume the default position is 0. There is no support for seeking to the default position
|
||||||
// in RemoteMediaClient.
|
// in RemoteMediaClient.
|
||||||
var positionMs = if (positionMs != C.TIME_UNSET) positionMs else 0
|
var positionMsFinal = if (positionMs != C.TIME_UNSET) positionMs else 0
|
||||||
if (mediaStatus != null) {
|
if (mediaStatus != null) {
|
||||||
if (currentMediaItemIndex != mediaItemIndex) {
|
if (currentMediaItemIndex != mediaItemIndex) {
|
||||||
Log.d(tag, "seekTo: Changing media item index from $currentMediaItemIndex to $mediaItemIndex")
|
Log.d(tag, "seekTo: Changing media item index from $currentMediaItemIndex to $mediaItemIndex")
|
||||||
remoteMediaClient?.queueJumpToItem(myCurrentTimeline.getPeriod(mediaItemIndex, period).uid as Int, positionMs, JSONObject())?.setResultCallback(resultCb)
|
remoteMediaClient?.queueJumpToItem(myCurrentTimeline.getPeriod(mediaItemIndex, period).uid as Int, positionMsFinal, JSONObject())?.setResultCallback(resultCb)
|
||||||
} else {
|
} else {
|
||||||
Log.d(tag, "seekTo: Same media index seek to position $positionMs")
|
Log.d(tag, "seekTo: Same media index seek to position $positionMsFinal")
|
||||||
var mediaSeekOptions = MediaSeekOptions.Builder().setPosition(positionMs).build()
|
var mediaSeekOptions = MediaSeekOptions.Builder().setPosition(positionMsFinal).build()
|
||||||
remoteMediaClient?.seek(mediaSeekOptions)?.setResultCallback(resultCb)
|
remoteMediaClient?.seek(mediaSeekOptions)?.setResultCallback(resultCb)
|
||||||
}
|
}
|
||||||
val oldPosition = getCurrentPositionInfo()
|
val oldPosition = getCurrentPositionInfo()
|
||||||
pendingSeekCount++
|
pendingSeekCount++
|
||||||
pendingSeekWindowIndex = mediaItemIndex
|
pendingSeekWindowIndex = mediaItemIndex
|
||||||
pendingSeekPositionMs = positionMs
|
pendingSeekPositionMs = positionMsFinal
|
||||||
val newPosition = getCurrentPositionInfo()
|
val newPosition = getCurrentPositionInfo()
|
||||||
listeners.queueEvent(
|
listeners.queueEvent(
|
||||||
EVENT_POSITION_DISCONTINUITY
|
EVENT_POSITION_DISCONTINUITY
|
||||||
) { listener: Player.Listener ->
|
) { listener: Player.Listener ->
|
||||||
listener.onPositionDiscontinuity(oldPosition, newPosition, DISCONTINUITY_REASON_SEEK)
|
listener.onPositionDiscontinuity(oldPosition, newPosition, DISCONTINUITY_REASON_SEEK)
|
||||||
}
|
}
|
||||||
if (oldPosition.windowIndex != newPosition.windowIndex) {
|
if (oldPosition.mediaItemIndex != newPosition.mediaItemIndex) {
|
||||||
val mediaItem = currentTimeline.getWindow(mediaItemIndex, window).mediaItem
|
val mediaItem = currentTimeline.getWindow(mediaItemIndex, window).mediaItem
|
||||||
listeners.queueEvent(
|
listeners.queueEvent(
|
||||||
EVENT_MEDIA_ITEM_TRANSITION
|
EVENT_MEDIA_ITEM_TRANSITION
|
||||||
|
@ -680,7 +674,8 @@ class CastPlayer(var castContext: CastContext) : BasePlayer() {
|
||||||
updateAvailableCommandsAndNotifyIfChanged()
|
updateAvailableCommandsAndNotifyIfChanged()
|
||||||
} else if (pendingSeekCount == 0) {
|
} else if (pendingSeekCount == 0) {
|
||||||
Log.w(tag, "seekTo Media Status is null")
|
Log.w(tag, "seekTo Media Status is null")
|
||||||
listeners.queueEvent( /* eventFlag= */C.INDEX_UNSET) { obj: Player.Listener -> obj.onSeekProcessed() }
|
// Playback state change will send metadata to client and stop seek loading
|
||||||
|
listeners.sendEvent(EVENT_PLAYBACK_STATE_CHANGED) { obj: Player.Listener -> obj.onPlaybackStateChanged(currentPlaybackState) }
|
||||||
}
|
}
|
||||||
listeners.flushEvents()
|
listeners.flushEvents()
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,7 +157,7 @@ class MediaSessionCallback(var playerNotificationService:PlayerNotificationServi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
Log.d(tag, "KeyCode:${keyEvent?.getKeyCode()}")
|
Log.d(tag, "KeyCode:${keyEvent.getKeyCode()}")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,10 +92,10 @@ class PlayerListener(var playerNotificationService:PlayerNotificationService) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calcPauseSeekBackTime() : Long {
|
private fun calcPauseSeekBackTime() : Long {
|
||||||
if (lastPauseTime <= 0) return 0
|
if (lastPauseTime <= 0) return 0
|
||||||
var time: Long = System.currentTimeMillis() - lastPauseTime
|
var time: Long = System.currentTimeMillis() - lastPauseTime
|
||||||
var seekback: Long = 0
|
var seekback: Long
|
||||||
if (time < 60000) seekback = 0
|
if (time < 60000) seekback = 0
|
||||||
else if (time < 120000) seekback = 10000
|
else if (time < 120000) seekback = 10000
|
||||||
else if (time < 300000) seekback = 15000
|
else if (time < 300000) seekback = 15000
|
||||||
|
|
|
@ -70,7 +70,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||||
lateinit var mediaManager: MediaManager
|
lateinit var mediaManager: MediaManager
|
||||||
lateinit var apiHandler: ApiHandler
|
lateinit var apiHandler: ApiHandler
|
||||||
|
|
||||||
lateinit var mPlayer: SimpleExoPlayer
|
lateinit var mPlayer: ExoPlayer
|
||||||
lateinit var currentPlayer:Player
|
lateinit var currentPlayer:Player
|
||||||
var castPlayer:CastPlayer? = null
|
var castPlayer:CastPlayer? = null
|
||||||
|
|
||||||
|
@ -171,11 +171,11 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||||
1000 * 20 // 20s playback rebuffer
|
1000 * 20 // 20s playback rebuffer
|
||||||
).build()
|
).build()
|
||||||
|
|
||||||
var simpleExoPlayerBuilder = SimpleExoPlayer.Builder(this)
|
mPlayer = ExoPlayer.Builder(this)
|
||||||
simpleExoPlayerBuilder.setLoadControl(customLoadControl)
|
.setLoadControl(customLoadControl)
|
||||||
simpleExoPlayerBuilder.setSeekBackIncrementMs(10000)
|
.setSeekBackIncrementMs(10000)
|
||||||
simpleExoPlayerBuilder.setSeekForwardIncrementMs(10000)
|
.setSeekForwardIncrementMs(10000)
|
||||||
mPlayer = simpleExoPlayerBuilder.build()
|
.build()
|
||||||
mPlayer.setHandleAudioBecomingNoisy(true)
|
mPlayer.setHandleAudioBecomingNoisy(true)
|
||||||
mPlayer.addListener(PlayerListener(this))
|
mPlayer.addListener(PlayerListener(this))
|
||||||
var audioAttributes:AudioAttributes = AudioAttributes.Builder().setUsage(C.USAGE_MEDIA).setContentType(C.CONTENT_TYPE_SPEECH).build()
|
var audioAttributes:AudioAttributes = AudioAttributes.Builder().setUsage(C.USAGE_MEDIA).setContentType(C.CONTENT_TYPE_SPEECH).build()
|
||||||
|
@ -246,14 +246,12 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||||
mediaSessionConnector = MediaSessionConnector(mediaSession)
|
mediaSessionConnector = MediaSessionConnector(mediaSession)
|
||||||
val queueNavigator: TimelineQueueNavigator = object : TimelineQueueNavigator(mediaSession) {
|
val queueNavigator: TimelineQueueNavigator = object : TimelineQueueNavigator(mediaSession) {
|
||||||
override fun getMediaDescription(player: Player, windowIndex: Int): MediaDescriptionCompat {
|
override fun getMediaDescription(player: Player, windowIndex: Int): MediaDescriptionCompat {
|
||||||
var builder = MediaDescriptionCompat.Builder()
|
return MediaDescriptionCompat.Builder()
|
||||||
.setMediaId(currentPlaybackSession!!.id)
|
.setMediaId(currentPlaybackSession!!.id)
|
||||||
.setTitle(currentPlaybackSession!!.displayTitle)
|
.setTitle(currentPlaybackSession!!.displayTitle)
|
||||||
.setSubtitle(currentPlaybackSession!!.displayAuthor)
|
.setSubtitle(currentPlaybackSession!!.displayAuthor)
|
||||||
.setIconUri(currentPlaybackSession!!.getCoverUri())
|
.setIconUri(currentPlaybackSession!!.getCoverUri()).build()
|
||||||
return builder.build()
|
|
||||||
}
|
}
|
||||||
// .setMediaUri(currentPlaybackSession!!.getContentUri())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaSessionConnector.setEnabledPlaybackActions(
|
mediaSessionConnector.setEnabledPlaybackActions(
|
||||||
|
@ -311,18 +309,16 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||||
if (mPlayer == currentPlayer) {
|
if (mPlayer == currentPlayer) {
|
||||||
var mediaSource:MediaSource
|
var mediaSource:MediaSource
|
||||||
|
|
||||||
|
var dataSourceFactory = DefaultHttpDataSource.Factory()
|
||||||
|
dataSourceFactory.setUserAgent(channelId)
|
||||||
if (playbackSession.isLocal) {
|
if (playbackSession.isLocal) {
|
||||||
Log.d(tag, "Playing Local Item")
|
Log.d(tag, "Playing Local Item")
|
||||||
var dataSourceFactory = DefaultDataSourceFactory(ctx, channelId)
|
|
||||||
mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItems[0])
|
mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItems[0])
|
||||||
} else if (!playbackSession.isHLS) {
|
} else if (!playbackSession.isHLS) {
|
||||||
Log.d(tag, "Direct Playing Item")
|
Log.d(tag, "Direct Playing Item")
|
||||||
var dataSourceFactory = DefaultDataSourceFactory(ctx, channelId)
|
|
||||||
mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItems[0])
|
mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItems[0])
|
||||||
} else {
|
} else {
|
||||||
Log.d(tag, "Playing HLS Item")
|
Log.d(tag, "Playing HLS Item")
|
||||||
var dataSourceFactory = DefaultHttpDataSource.Factory()
|
|
||||||
dataSourceFactory.setUserAgent(channelId)
|
|
||||||
dataSourceFactory.setDefaultRequestProperties(hashMapOf("Authorization" to "Bearer ${DeviceManager.token}"))
|
dataSourceFactory.setDefaultRequestProperties(hashMapOf("Authorization" to "Bearer ${DeviceManager.token}"))
|
||||||
mediaSource = HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItems[0])
|
mediaSource = HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItems[0])
|
||||||
}
|
}
|
||||||
|
@ -426,12 +422,12 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCurrentTime() : Long {
|
fun getCurrentTime() : Long {
|
||||||
if (currentPlayer.mediaItemCount > 1) {
|
return if (currentPlayer.mediaItemCount > 1) {
|
||||||
var windowIndex = currentPlayer.currentWindowIndex
|
val windowIndex = currentPlayer.currentMediaItemIndex
|
||||||
var currentTrackStartOffset = currentPlaybackSession?.getTrackStartOffsetMs(windowIndex) ?: 0L
|
val currentTrackStartOffset = currentPlaybackSession?.getTrackStartOffsetMs(windowIndex) ?: 0L
|
||||||
return currentPlayer.currentPosition + currentTrackStartOffset
|
currentPlayer.currentPosition + currentTrackStartOffset
|
||||||
} else {
|
} else {
|
||||||
return currentPlayer.currentPosition
|
currentPlayer.currentPosition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,13 +435,13 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||||
return getCurrentTime() / 1000.0
|
return getCurrentTime() / 1000.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBufferedTime() : Long {
|
private fun getBufferedTime() : Long {
|
||||||
if (currentPlayer.mediaItemCount > 1) {
|
return if (currentPlayer.mediaItemCount > 1) {
|
||||||
var windowIndex = currentPlayer.currentWindowIndex
|
val windowIndex = currentPlayer.currentMediaItemIndex
|
||||||
var currentTrackStartOffset = currentPlaybackSession?.getTrackStartOffsetMs(windowIndex) ?: 0L
|
val currentTrackStartOffset = currentPlaybackSession?.getTrackStartOffsetMs(windowIndex) ?: 0L
|
||||||
return currentPlayer.bufferedPosition + currentTrackStartOffset
|
currentPlayer.bufferedPosition + currentTrackStartOffset
|
||||||
} else {
|
} else {
|
||||||
return currentPlayer.bufferedPosition
|
currentPlayer.bufferedPosition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,6 @@ import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
@CapacitorPlugin(name = "AbsDownloader")
|
@CapacitorPlugin(name = "AbsDownloader")
|
||||||
class AbsDownloader : Plugin() {
|
class AbsDownloader : Plugin() {
|
||||||
|
@ -54,7 +52,7 @@ class AbsDownloader : Plugin() {
|
||||||
) {
|
) {
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
fun getDownloadRequest(): DownloadManager.Request {
|
fun getDownloadRequest(): DownloadManager.Request {
|
||||||
var dlRequest = DownloadManager.Request(uri)
|
val dlRequest = DownloadManager.Request(uri)
|
||||||
dlRequest.setTitle(filename)
|
dlRequest.setTitle(filename)
|
||||||
dlRequest.setDescription("Downloading to $localFolderName for book $itemTitle")
|
dlRequest.setDescription("Downloading to $localFolderName for book $itemTitle")
|
||||||
dlRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
dlRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||||
|
@ -86,21 +84,12 @@ class AbsDownloader : Plugin() {
|
||||||
folderScanner = FolderScanner(mainActivity)
|
folderScanner = FolderScanner(mainActivity)
|
||||||
apiHandler = ApiHandler(mainActivity)
|
apiHandler = ApiHandler(mainActivity)
|
||||||
|
|
||||||
var recieverEvent: (evt: String, id: Long) -> Unit = { evt: String, id: Long ->
|
|
||||||
if (evt == "complete") {
|
|
||||||
}
|
|
||||||
if (evt == "clicked") {
|
|
||||||
Log.d(tag, "Clicked $id back in the downloader")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mainActivity.registerBroadcastReceiver(recieverEvent)
|
|
||||||
|
|
||||||
Log.d(tag, "Build SDK ${Build.VERSION.SDK_INT}")
|
Log.d(tag, "Build SDK ${Build.VERSION.SDK_INT}")
|
||||||
}
|
}
|
||||||
|
|
||||||
@PluginMethod
|
@PluginMethod
|
||||||
fun downloadLibraryItem(call: PluginCall) {
|
fun downloadLibraryItem(call: PluginCall) {
|
||||||
var libraryItemId = call.data.getString("libraryItemId").toString()
|
val libraryItemId = call.data.getString("libraryItemId").toString()
|
||||||
var episodeId = call.data.getString("episodeId").toString()
|
var episodeId = call.data.getString("episodeId").toString()
|
||||||
if (episodeId == "null") episodeId = ""
|
if (episodeId == "null") episodeId = ""
|
||||||
var localFolderId = call.data.getString("localFolderId").toString()
|
var localFolderId = call.data.getString("localFolderId").toString()
|
||||||
|
@ -154,17 +143,6 @@ class AbsDownloader : Plugin() {
|
||||||
return if (cleanedRelPath.startsWith("_")) cleanedRelPath.substring(1) else cleanedRelPath
|
return if (cleanedRelPath.startsWith("_")) cleanedRelPath.substring(1) else cleanedRelPath
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAbMetadataText(libraryItem:LibraryItem):String {
|
|
||||||
var bookMedia = libraryItem.media as com.audiobookshelf.app.data.Book
|
|
||||||
var fileString = ";ABMETADATA1\n"
|
|
||||||
// fileString += "#libraryItemId=${libraryItem.id}\n"
|
|
||||||
// fileString += "title=${bookMedia.metadata.title}\n"
|
|
||||||
// fileString += "author=${bookMedia.metadata.authorName}\n"
|
|
||||||
// fileString += "narrator=${bookMedia.metadata.narratorName}\n"
|
|
||||||
// fileString += "series=${bookMedia.metadata.seriesName}\n"
|
|
||||||
return fileString
|
|
||||||
}
|
|
||||||
|
|
||||||
fun startLibraryItemDownload(libraryItem: LibraryItem, localFolder: LocalFolder, episode:PodcastEpisode?) {
|
fun startLibraryItemDownload(libraryItem: LibraryItem, localFolder: LocalFolder, episode:PodcastEpisode?) {
|
||||||
if (libraryItem.mediaType == "book") {
|
if (libraryItem.mediaType == "book") {
|
||||||
var bookTitle = libraryItem.media.metadata.title
|
var bookTitle = libraryItem.media.metadata.title
|
||||||
|
@ -259,21 +237,21 @@ class AbsDownloader : Plugin() {
|
||||||
downloadItemPart.downloadId = downloadId
|
downloadItemPart.downloadId = downloadId
|
||||||
|
|
||||||
if (libraryItem.media.coverPath != null && libraryItem.media.coverPath?.isNotEmpty() == true) {
|
if (libraryItem.media.coverPath != null && libraryItem.media.coverPath?.isNotEmpty() == true) {
|
||||||
var serverPath = "/api/items/${libraryItem.id}/cover?format=jpeg"
|
serverPath = "/api/items/${libraryItem.id}/cover?format=jpeg"
|
||||||
var destinationFilename = "cover.jpg"
|
destinationFilename = "cover.jpg"
|
||||||
var destinationFile = File("$itemFolderPath/$destinationFilename")
|
destinationFile = File("$itemFolderPath/$destinationFilename")
|
||||||
|
|
||||||
if (destinationFile.exists()) {
|
if (destinationFile.exists()) {
|
||||||
Log.d(tag, "Podcast cover already exists - not downloading cover again")
|
Log.d(tag, "Podcast cover already exists - not downloading cover again")
|
||||||
} else {
|
} else {
|
||||||
var destinationUri = Uri.fromFile(destinationFile)
|
destinationUri = Uri.fromFile(destinationFile)
|
||||||
var downloadUri = Uri.parse("${DeviceManager.serverAddress}${serverPath}&token=${DeviceManager.token}")
|
downloadUri = Uri.parse("${DeviceManager.serverAddress}${serverPath}&token=${DeviceManager.token}")
|
||||||
var downloadItemPart = DownloadItemPart(DeviceManager.getBase64Id(destinationFile.absolutePath), destinationFilename, destinationFile.absolutePath, podcastTitle, serverPath, localFolder.name, localFolder.id, null,null, false, downloadUri, destinationUri, null, 0)
|
downloadItemPart = DownloadItemPart(DeviceManager.getBase64Id(destinationFile.absolutePath), destinationFilename, destinationFile.absolutePath, podcastTitle, serverPath, localFolder.name, localFolder.id, null,null, false, downloadUri, destinationUri, null, 0)
|
||||||
|
|
||||||
downloadItem.downloadItemParts.add(downloadItemPart)
|
downloadItem.downloadItemParts.add(downloadItemPart)
|
||||||
|
|
||||||
var dlRequest = downloadItemPart.getDownloadRequest()
|
dlRequest = downloadItemPart.getDownloadRequest()
|
||||||
var downloadId = downloadManager.enqueue(dlRequest)
|
downloadId = downloadManager.enqueue(dlRequest)
|
||||||
downloadItemPart.downloadId = downloadId
|
downloadItemPart.downloadId = downloadId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ class AbsFileSystem : Plugin() {
|
||||||
|
|
||||||
@PluginMethod
|
@PluginMethod
|
||||||
fun checkStoragePermission(call: PluginCall) {
|
fun checkStoragePermission(call: PluginCall) {
|
||||||
var res = false
|
var res: Boolean
|
||||||
if (Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.P) {
|
if (Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.P) {
|
||||||
res = SimpleStorage.hasStoragePermission(context)
|
res = SimpleStorage.hasStoragePermission(context)
|
||||||
Log.d(TAG, "checkStoragePermission: Check Storage Access $res")
|
Log.d(TAG, "checkStoragePermission: Check Storage Access $res")
|
||||||
|
@ -222,32 +222,12 @@ class AbsFileSystem : Plugin() {
|
||||||
var docfile = DocumentFileCompat.fromUri(mainActivity, Uri.parse(contentUrl))
|
var docfile = DocumentFileCompat.fromUri(mainActivity, Uri.parse(contentUrl))
|
||||||
var success = docfile?.delete() == true
|
var success = docfile?.delete() == true
|
||||||
if (success) {
|
if (success) {
|
||||||
localLibraryItem?.media?.removeAudioTrack(trackLocalFileId)
|
localLibraryItem.media.removeAudioTrack(trackLocalFileId)
|
||||||
localLibraryItem?.removeLocalFile(trackLocalFileId)
|
localLibraryItem.removeLocalFile(trackLocalFileId)
|
||||||
DeviceManager.dbManager.saveLocalLibraryItem(localLibraryItem)
|
DeviceManager.dbManager.saveLocalLibraryItem(localLibraryItem)
|
||||||
call.resolve(JSObject(jacksonMapper.writeValueAsString(localLibraryItem)))
|
call.resolve(JSObject(jacksonMapper.writeValueAsString(localLibraryItem)))
|
||||||
} else {
|
} else {
|
||||||
call.resolve(JSObject("{\"success\":false}"))
|
call.resolve(JSObject("{\"success\":false}"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkUriExists(uri: Uri?): Boolean {
|
|
||||||
if (uri == null) return false
|
|
||||||
val resolver = context.contentResolver
|
|
||||||
var cursor: Cursor? = null
|
|
||||||
return try {
|
|
||||||
cursor = resolver.query(uri, null, null, null, null)
|
|
||||||
//cursor null: content Uri was invalid or some other error occurred
|
|
||||||
//cursor.moveToFirst() false: Uri was ok but no entry found.
|
|
||||||
(cursor != null && cursor.moveToFirst())
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
false
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
cursor?.close()
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ class ApiHandler(var ctx:Context) {
|
||||||
getRequest("/api/libraries") {
|
getRequest("/api/libraries") {
|
||||||
val libraries = mutableListOf<Library>()
|
val libraries = mutableListOf<Library>()
|
||||||
if (it.has("value")) {
|
if (it.has("value")) {
|
||||||
var array = it.getJSONArray("value")!!
|
var array = it.getJSONArray("value")
|
||||||
for (i in 0 until array.length()) {
|
for (i in 0 until array.length()) {
|
||||||
val library = mapper.readValue<Library>(array.get(i).toString())
|
val library = mapper.readValue<Library>(array.get(i).toString())
|
||||||
libraries.add(library)
|
libraries.add(library)
|
||||||
|
|
|
@ -8,8 +8,8 @@ buildscript {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.3.0-alpha08'
|
classpath 'com.google.gms:google-services:4.3.5'
|
||||||
classpath 'com.google.gms:google-services:4.3.10'
|
classpath 'com.android.tools.build:gradle:7.2.0-beta04'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
|
|
@ -12,7 +12,6 @@ ext {
|
||||||
androidxJunitVersion = '1.1.2'
|
androidxJunitVersion = '1.1.2'
|
||||||
androidxEspressoCoreVersion = '3.3.0'
|
androidxEspressoCoreVersion = '3.3.0'
|
||||||
cordovaAndroidVersion = '10.1.1'
|
cordovaAndroidVersion = '10.1.1'
|
||||||
androidx_app_compat_version = '1.2.0'
|
|
||||||
androidx_car_version = '1.0.0-alpha7'
|
androidx_car_version = '1.0.0-alpha7'
|
||||||
androidx_core_ktx_version = '1.7.0'
|
androidx_core_ktx_version = '1.7.0'
|
||||||
androidx_media_version = '1.5.0'
|
androidx_media_version = '1.5.0'
|
||||||
|
|
|
@ -131,7 +131,7 @@ export default {
|
||||||
touchStartTime: 0,
|
touchStartTime: 0,
|
||||||
touchEndY: 0,
|
touchEndY: 0,
|
||||||
useChapterTrack: false,
|
useChapterTrack: false,
|
||||||
isLoading: true
|
isLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -548,8 +548,9 @@ export default {
|
||||||
this.$store.commit('setPlayerItem', null)
|
this.$store.commit('setPlayerItem', null)
|
||||||
this.showFullscreen = false
|
this.showFullscreen = false
|
||||||
this.isEnded = false
|
this.isEnded = false
|
||||||
|
this.isLoading = false
|
||||||
this.playbackSession = null
|
this.playbackSession = null
|
||||||
|
|
||||||
AbsAudioPlayer.closePlayback()
|
AbsAudioPlayer.closePlayback()
|
||||||
},
|
},
|
||||||
//
|
//
|
||||||
|
@ -567,16 +568,18 @@ export default {
|
||||||
},
|
},
|
||||||
onMetadata(data) {
|
onMetadata(data) {
|
||||||
console.log('onMetadata', JSON.stringify(data))
|
console.log('onMetadata', JSON.stringify(data))
|
||||||
this.isLoading = false
|
|
||||||
|
|
||||||
this.totalDuration = Number(data.duration.toFixed(2))
|
this.totalDuration = Number(data.duration.toFixed(2))
|
||||||
this.currentTime = Number(data.currentTime.toFixed(2))
|
this.currentTime = Number(data.currentTime.toFixed(2))
|
||||||
// Also includes player state data.playerState
|
|
||||||
|
|
||||||
if (data.playerState == this.$constants.PlayerState.ENDED) {
|
// Done loading
|
||||||
|
if (data.playerState !== 'BUFFERING' && data.playerState !== 'IDLE') {
|
||||||
|
this.isLoading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.playerState === 'ENDED') {
|
||||||
console.log('[AudioPlayer] Playback ended')
|
console.log('[AudioPlayer] Playback ended')
|
||||||
}
|
}
|
||||||
this.isEnded = data.playerState == this.$constants.PlayerState.ENDED
|
this.isEnded = data.playerState === 'ENDED'
|
||||||
|
|
||||||
console.log('received metadata update', data)
|
console.log('received metadata update', data)
|
||||||
|
|
||||||
|
@ -590,6 +593,7 @@ export default {
|
||||||
this.playbackSession = playbackSession
|
this.playbackSession = playbackSession
|
||||||
|
|
||||||
this.isEnded = false
|
this.isEnded = false
|
||||||
|
this.isLoading = true
|
||||||
this.$store.commit('setPlayerItem', this.playbackSession)
|
this.$store.commit('setPlayerItem', this.playbackSession)
|
||||||
|
|
||||||
// Set track width
|
// Set track width
|
||||||
|
|
|
@ -9,13 +9,13 @@ install! 'cocoapods', :disable_input_output_paths => true
|
||||||
def capacitor_pods
|
def capacitor_pods
|
||||||
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
||||||
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
||||||
pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app'
|
pod 'CapacitorApp', :path => '..\..\node_modules\@capacitor\app'
|
||||||
pod 'CapacitorDialog', :path => '../../node_modules/@capacitor/dialog'
|
pod 'CapacitorDialog', :path => '..\..\node_modules\@capacitor\dialog'
|
||||||
pod 'CapacitorHaptics', :path => '../../node_modules/@capacitor/haptics'
|
pod 'CapacitorHaptics', :path => '..\..\node_modules\@capacitor\haptics'
|
||||||
pod 'CapacitorNetwork', :path => '../../node_modules/@capacitor/network'
|
pod 'CapacitorNetwork', :path => '..\..\node_modules\@capacitor\network'
|
||||||
pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar'
|
pod 'CapacitorStatusBar', :path => '..\..\node_modules\@capacitor\status-bar'
|
||||||
pod 'CapacitorStorage', :path => '../../node_modules/@capacitor/storage'
|
pod 'CapacitorStorage', :path => '..\..\node_modules\@capacitor\storage'
|
||||||
pod 'RobingenzCapacitorAppUpdate', :path => '../../node_modules/@robingenz/capacitor-app-update'
|
pod 'RobingenzCapacitorAppUpdate', :path => '..\..\node_modules\@robingenz\capacitor-app-update'
|
||||||
end
|
end
|
||||||
|
|
||||||
target 'App' do
|
target 'App' do
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue