From bed843e2c807cb12689e4a3f019f5cefc936d1ac Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 20 May 2018 12:42:49 +0200 Subject: [PATCH] Autorewind + fix condition of search button appearance --- app/build.gradle | 4 +-- .../eu/zderadicka/audioserve/AudioService.kt | 29 +++++++++++++++++++ .../eu/zderadicka/audioserve/MainActivity.kt | 6 ++-- .../zderadicka/audioserve/SettingsActivity.kt | 11 +++++++ .../eu/zderadicka/audioserve/data/Utils.kt | 12 ++++++++ .../eu/zderadicka/audioserve/net/ApiClient.kt | 1 - app/src/main/res/values/strings.xml | 5 ++++ app/src/main/res/xml/settings.xml | 13 ++++++++- .../eu/zderadicka/audioserve/UtilsTest.kt | 7 +++++ 9 files changed, 82 insertions(+), 6 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 9a2cb7d..2cc7d02 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { applicationId "eu.zderadicka.audioserve" minSdkVersion 21 targetSdkVersion 27 - versionCode 12 - versionName "0.6.5" + versionCode 13 + versionName "0.6.6" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { diff --git a/app/src/main/java/eu/zderadicka/audioserve/AudioService.kt b/app/src/main/java/eu/zderadicka/audioserve/AudioService.kt index 8df07f0..cf3b325 100644 --- a/app/src/main/java/eu/zderadicka/audioserve/AudioService.kt +++ b/app/src/main/java/eu/zderadicka/audioserve/AudioService.kt @@ -20,6 +20,8 @@ import android.support.v4.media.session.MediaControllerCompat import android.support.v4.media.session.MediaSessionCompat import android.support.v4.media.session.PlaybackStateCompat import android.support.v4.media.session.PlaybackStateCompat.* +import android.text.format.DateUtils.MINUTE_IN_MILLIS +import android.text.format.DateUtils.YEAR_IN_MILLIS import android.util.Log import com.google.android.exoplayer2.ExoPlayer import com.google.android.exoplayer2.ExoPlayerFactory @@ -88,6 +90,7 @@ class AudioService : MediaBrowserServiceCompat() { private var currentMediaItem: MediaItem? = null private var lastKnownPosition = 0L private var lastPositionUpdateTime = 0L + private var previousPositionUpdateTime = 0L private var playQueue: MutableList = ArrayList() private lateinit var apiClient: ApiClient private var preloadFiles: Int = 2 @@ -95,6 +98,7 @@ class AudioService : MediaBrowserServiceCompat() { private var deletePreviousQueueItem: Int = -1 // delete previous queue Item private var isOffline: Boolean = false private val scheduler = Handler() + private var enableAutoRewind = false private val playerController = object : DefaultPlaybackController(REWIND_MS, FF_MS, MediaSessionConnector.DEFAULT_REPEAT_TOGGLE_MODES) { @@ -128,6 +132,10 @@ class AudioService : MediaBrowserServiceCompat() { override fun onPlay(player: Player) { Log.d(LOG_TAG, "Playback started") + val autoRewind = calcAutoRewind() + if (autoRewind>100) { + super.onSeekTo(player, player.currentPosition - autoRewind) + } if (requestAudioFocus()) { super.onPlay(player) } @@ -170,6 +178,18 @@ class AudioService : MediaBrowserServiceCompat() { } } + private fun calcAutoRewind():Int { + if (!enableAutoRewind) return 0 + val prevPos = if (previousPositionUpdateTime >0) previousPositionUpdateTime else lastPositionUpdateTime + previousPositionUpdateTime = 0 + val updatedBefore = System.currentTimeMillis() - prevPos + Log.d(LOG_TAG,"Determine autorewind for item ${currentMediaItem}, updated before${updatedBefore}") + return if (updatedBefore < 5* MINUTE_IN_MILLIS) 2000 + else if (updatedBefore < 30 * MINUTE_IN_MILLIS) 15_000 + else if (updatedBefore < YEAR_IN_MILLIS) 30_000 + else 0 + } + private fun findIndexInFolder(mediaId: String): Int { return currentFolder.indexOfFirst { it.mediaId == mediaId } } @@ -250,6 +270,8 @@ class AudioService : MediaBrowserServiceCompat() { seekAfterPrepare = seekTo } + previousPositionUpdateTime = extras?.getLong(METADATA_KEY_LAST_LISTENED_TIMESTAMP)?:0 + } else { //source = factory.createMediaSource(apiClient.uriFromMediaId(mediaId)) @@ -454,6 +476,9 @@ class AudioService : MediaBrowserServiceCompat() { isOffline = sharedPreferences.getBoolean("pref_offline", false) preparer.sourceFactory = null } + "pref_autorewind" -> { + enableAutoRewind = sharedPreferences.getBoolean("pref_autorewind", false) + } } } @@ -479,6 +504,7 @@ class AudioService : MediaBrowserServiceCompat() { super.onCreate() preloadFiles = PreferenceManager.getDefaultSharedPreferences(this).getString("pref_preload","2").toInt() isOffline = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("pref_offline",false) + enableAutoRewind = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("pref_autorewind", false) session = MediaSessionCompat(this, LOG_TAG) session.controller.registerCallback(sessionCallback) player = ExoPlayerFactory.newSimpleInstance(this, DefaultTrackSelector()) @@ -793,6 +819,9 @@ mediaSessionConnector.setErrorMessageProvider(messageProvider); extras.putLong(METADATA_KEY_LAST_POSITION, lastItem.description.extras?.getLong(METADATA_KEY_LAST_POSITION) ?: 0L) + extras.putLong(METADATA_KEY_LAST_LISTENED_TIMESTAMP, + lastItem.description.extras?.getLong(METADATA_KEY_LAST_LISTENED_TIMESTAMP) + ?: 0L) preparer.onPrepareFromMediaId(lastItem.mediaId!!, extras) } } diff --git a/app/src/main/java/eu/zderadicka/audioserve/MainActivity.kt b/app/src/main/java/eu/zderadicka/audioserve/MainActivity.kt index 63ab940..bd5dfc3 100644 --- a/app/src/main/java/eu/zderadicka/audioserve/MainActivity.kt +++ b/app/src/main/java/eu/zderadicka/audioserve/MainActivity.kt @@ -160,13 +160,15 @@ class MainActivity : AppCompatActivity(), val extras = Bundle() val startAt: Long = item.description.extras?.getLong(METADATA_KEY_LAST_POSITION) ?: 0 if (startAt > 0) { - ctl.seekTo(startAt) + //ctl.seekTo(startAt) extras.putLong(METADATA_KEY_LAST_POSITION, startAt) } + extras.putLong(METADATA_KEY_LAST_LISTENED_TIMESTAMP, + item.description.extras?.getLong(METADATA_KEY_LAST_LISTENED_TIMESTAMP)?: 0) ctl.prepareFromMediaId(item.mediaId, extras) } - val collection: Int? = collectionFromFolderId(folderId) + val collection: Int? = collectionFromFolderId(folderId)?: collectionFromSearchId(folderId) searchPrefix = if (collection == null || isOffline) null else "${AudioService.SEARCH_PREFIX}${collection}_" this.folderDetails = folderDetails invalidateOptionsMenu() diff --git a/app/src/main/java/eu/zderadicka/audioserve/SettingsActivity.kt b/app/src/main/java/eu/zderadicka/audioserve/SettingsActivity.kt index 1ea4b15..4dc1f05 100644 --- a/app/src/main/java/eu/zderadicka/audioserve/SettingsActivity.kt +++ b/app/src/main/java/eu/zderadicka/audioserve/SettingsActivity.kt @@ -213,6 +213,17 @@ class SettingsFragment: PreferenceFragment(), SharedPreferences.OnSharedPreferen pref.summary = getString(R.string.pref_downloads_summary, p) } + "pref_autorewind" -> { + if (pref !is CheckBoxPreference) return + val checked = sps.getBoolean("pref_autorewind", false) + if (checked) { + pref.summary=getString(R.string.pref_autorewind_selected_title) + + } else { + pref.summary=getString(R.string.pref_autorewind_unselected_title) + } + + } } diff --git a/app/src/main/java/eu/zderadicka/audioserve/data/Utils.kt b/app/src/main/java/eu/zderadicka/audioserve/data/Utils.kt index 603f362..d89ee27 100644 --- a/app/src/main/java/eu/zderadicka/audioserve/data/Utils.kt +++ b/app/src/main/java/eu/zderadicka/audioserve/data/Utils.kt @@ -191,6 +191,18 @@ fun collectionFromFolderId(folderId:String): Int? { return n.toInt() } + +private val BEGIN_NUMBERS_RE = Regex("""^\d+""") +fun collectionFromSearchId(folderId:String): Int? { + if (folderId.startsWith(AudioService.SEARCH_PREFIX)) { + val m = BEGIN_NUMBERS_RE.find(folderId.substring(AudioService.SEARCH_PREFIX.length)) + if (m!=null) { + return m.value.toInt() + } + } + return null +} + fun duplicateMediaItemWithExtrasAssured(item: MediaBrowserCompat.MediaItem):MediaBrowserCompat.MediaItem { val desc = MediaDescriptionCompat.Builder() .setMediaId(item.description.mediaId) diff --git a/app/src/main/java/eu/zderadicka/audioserve/net/ApiClient.kt b/app/src/main/java/eu/zderadicka/audioserve/net/ApiClient.kt index 7071584..13a8554 100644 --- a/app/src/main/java/eu/zderadicka/audioserve/net/ApiClient.kt +++ b/app/src/main/java/eu/zderadicka/audioserve/net/ApiClient.kt @@ -316,7 +316,6 @@ class ApiClient private constructor(val context: Context) { } - fun login(cb: (ApiError?) -> Unit) { fun afterLogin() { synchronized(this@ApiClient) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 24a9b23..d7c0b16 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -80,4 +80,9 @@ %1$s free m Download ended with %1$s errors! + DOWNLOADS + PLAYBACK + Auto Rewind + No auto rewind, playback will start exactly where it was paused + Before continuing playback it\'\'ll be rewind by a small amount (2s-30s), depending how long it was paused diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index a79241f..08bd192 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -63,7 +63,7 @@ + + + + + diff --git a/app/src/test/java/eu/zderadicka/audioserve/UtilsTest.kt b/app/src/test/java/eu/zderadicka/audioserve/UtilsTest.kt index 1873960..a499411 100644 --- a/app/src/test/java/eu/zderadicka/audioserve/UtilsTest.kt +++ b/app/src/test/java/eu/zderadicka/audioserve/UtilsTest.kt @@ -1,6 +1,7 @@ package eu.zderadicka.audioserve import eu.zderadicka.audioserve.data.collectionFromFolderId +import eu.zderadicka.audioserve.data.collectionFromSearchId import eu.zderadicka.audioserve.data.folderIdFromFileId import eu.zderadicka.audioserve.data.pathFromFolderId import eu.zderadicka.audioserve.net.parseContentRange @@ -69,4 +70,10 @@ class UtilsTest { val path2 = pathFromFolderId(fid) assertEquals("Verne, Jules", path2) } + + @Test + fun testCollectionFromSearch() { + val c = collectionFromSearchId("__AUDIOSERVE_SEARCH_5") + assertEquals(5,c) + } } \ No newline at end of file