Fixing gradle dependency issues on android, minor warning fixes

This commit is contained in:
advplyr 2022-04-19 19:25:16 -05:00
parent 379612d874
commit f65f7b01c3
16 changed files with 94 additions and 131 deletions

View file

@ -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"

View file

@ -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()

View file

@ -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)

View file

@ -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")

View file

@ -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)
} }
} }

View file

@ -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()
} }

View file

@ -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
} }
} }

View file

@ -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

View file

@ -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
} }
} }

View file

@ -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
} }
} }

View file

@ -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
}
}
} }

View file

@ -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)

View file

@ -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

View file

@ -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'

View file

@ -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,6 +548,7 @@ 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

View file

@ -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