From e4dd783a6a684b714233184f24e0b95571a8d01e Mon Sep 17 00:00:00 2001 From: Ivan <ivan.zderadicka@gmail.com> Date: Thu, 26 Apr 2018 07:54:39 +0200 Subject: [PATCH] Fixed lost connection - must close input stream of the connection and proper handling of play when not connected --- README.md | 16 +++++++---- .../eu/zderadicka/audioserve/AudioService.kt | 7 +++-- .../audioserve/fragments/FolderFragment.kt | 9 +++++- .../zderadicka/audioserve/net/CacheManager.kt | 7 ++++- .../eu/zderadicka/audioserve/net/FileCache.kt | 28 +++++++++++++++---- app/src/main/res/values/strings.xml | 1 + 6 files changed, 52 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index a9cd224..2d9c20a 100644 --- a/README.md +++ b/README.md @@ -58,14 +58,18 @@ but it's not priority now. How to install -------------- -For now you have build yourself with Android SDK or Android Studio +I provide built .apk file signed with dummy certificate on +[github releases page](https://github.com/izderadicka/audioserve-android/releases). + +You can download to Android device and install it there +(provided you have allowed Unknown Sources in Security settings). + +Supported platforms are from 5.0 Lollipop on ( but I'm testing mostly on 7.0 Nougat). + +You can also build yourself with Android Studio - just checkout the project from github and +open in Android Studio. -This is how to build debug apk from commandline (when you have studio or SDK+tools installed): -```bash -./gradlew assembleDebug -ls app/build/outputs/apk/debug/ -``` License ------- diff --git a/app/src/main/java/eu/zderadicka/audioserve/AudioService.kt b/app/src/main/java/eu/zderadicka/audioserve/AudioService.kt index 57c34e9..7b869a0 100644 --- a/app/src/main/java/eu/zderadicka/audioserve/AudioService.kt +++ b/app/src/main/java/eu/zderadicka/audioserve/AudioService.kt @@ -50,6 +50,7 @@ private const val FF_MS = 30 * 1000L private const val REWIND_MS = 15 * 1000L const val MEDIA_FULLY_CACHED = "eu.zderadicka.audioserve.FULLY_CACHED" const val MEDIA_CACHE_DELETED = "eu.zderadicka.audioserve.CACHE_DELETED" +const val PLAYER_NOT_READY = "eu.zderadicka.audioserve.PLAYER_NOT_READY" private class ResultWrapper(val result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>) { @@ -208,7 +209,7 @@ class AudioService : MediaBrowserServiceCompat() { deletePreviousQueueItem = -1 - if (folderPosition >= 0) { + if (folderPosition >= 0 && sourceFactory!=null) { val factory = sourceFactory?: throw IllegalStateException("Session not ready") var source: MediaSource playQueue = currentFolder.slice(folderPosition until currentFolder.size).toMutableList() @@ -235,9 +236,11 @@ class AudioService : MediaBrowserServiceCompat() { } else { //source = factory.createMediaSource(apiClient.uriFromMediaId(mediaId)) - Log.e(LOG_TAG, "Folder is not synched - cannot played") + Log.e(LOG_TAG, "Folder is not synched or offline- cannot played") playQueue.clear() currentSourcesList = null + + session.sendSessionEvent(PLAYER_NOT_READY, null) } } diff --git a/app/src/main/java/eu/zderadicka/audioserve/fragments/FolderFragment.kt b/app/src/main/java/eu/zderadicka/audioserve/fragments/FolderFragment.kt index 5be7d83..f1f226f 100644 --- a/app/src/main/java/eu/zderadicka/audioserve/fragments/FolderFragment.kt +++ b/app/src/main/java/eu/zderadicka/audioserve/fragments/FolderFragment.kt @@ -20,6 +20,7 @@ import android.support.v4.content.ContextCompat import android.widget.* import eu.zderadicka.audioserve.MEDIA_CACHE_DELETED import eu.zderadicka.audioserve.MEDIA_FULLY_CACHED +import eu.zderadicka.audioserve.PLAYER_NOT_READY import eu.zderadicka.audioserve.R import eu.zderadicka.audioserve.data.* import eu.zderadicka.audioserve.ui.SwipeRevealLayout @@ -285,13 +286,19 @@ class FolderFragment : MediaFragment() { override fun onSessionEvent(event: String?, extras: Bundle?) { super.onSessionEvent(event, extras) - if (event == MEDIA_FULLY_CACHED || event == MEDIA_CACHE_DELETED) { + when (event) { + MEDIA_FULLY_CACHED, MEDIA_CACHE_DELETED -> { val cached = event == MEDIA_FULLY_CACHED val mediaId = extras?.getString(METADATA_KEY_MEDIA_ID) if (mediaId != null) { adapter.updatedCached(mediaId, cached) } } + PLAYER_NOT_READY -> { + Toast.makeText(context,getString(R.string.player_not_ready), + Toast.LENGTH_LONG).show() + } + } } } diff --git a/app/src/main/java/eu/zderadicka/audioserve/net/CacheManager.kt b/app/src/main/java/eu/zderadicka/audioserve/net/CacheManager.kt index af4808b..ae98443 100644 --- a/app/src/main/java/eu/zderadicka/audioserve/net/CacheManager.kt +++ b/app/src/main/java/eu/zderadicka/audioserve/net/CacheManager.kt @@ -78,7 +78,7 @@ class CachedFileDataSource(val cache: FileCache) : DataSource, CacheItem.Listene if (item.state == CacheItem.State.Empty) { cacheReadyCondition.block(TIME_TO_WAIT_FOR_CACHE) if (item.state == CacheItem.State.Empty) { - throw IOException("Empty cache") + throw IOException("Cache not filling - status of FileLoader - online = ${cache.loaderOnline}") } } @@ -292,6 +292,11 @@ class CacheManager private constructor(val context: Context) { return false } + internal val loaderOnline: Boolean + get(){ + return cache.loaderOnline + } + companion object { @Volatile private var instance: CacheManager? = null diff --git a/app/src/main/java/eu/zderadicka/audioserve/net/FileCache.kt b/app/src/main/java/eu/zderadicka/audioserve/net/FileCache.kt index 2ec3b1a..e62e7bb 100644 --- a/app/src/main/java/eu/zderadicka/audioserve/net/FileCache.kt +++ b/app/src/main/java/eu/zderadicka/audioserve/net/FileCache.kt @@ -14,7 +14,9 @@ import eu.zderadicka.audioserve.utils.defPrefs import eu.zderadicka.audioserve.utils.isNetworkConnected import java.io.File import java.io.IOException +import java.io.InputStream import java.net.HttpURLConnection +import java.net.SocketException import java.net.URL import java.util.concurrent.BlockingDeque import java.util.concurrent.LinkedBlockingDeque @@ -324,6 +326,9 @@ class FileCache(val cacheDir: File, item } + internal val loaderOnline: Boolean + get() = loader?.isConnected?:false + fun stopAllLoading(vararg keepLoading: String) = synchronized(this) { queue.clear() val shouldInterrupt: Boolean = if (keepLoading.size == 0) { @@ -391,7 +396,7 @@ class FileLoader(private val queue: BlockingDeque<CacheItem>, private var putBack = false private var myThread: Thread? = null - private var isConnected = true + internal var isConnected = true set(v) { field = v if (field) { @@ -403,6 +408,7 @@ class FileLoader(private val queue: BlockingDeque<CacheItem>, myThread?.let { putBack = true Log.d(LOG_TAG, "Trying to interrupt thread ${it.name}") + Thread{ stream?.close()}.start() it.interrupt() } } @@ -419,6 +425,8 @@ class FileLoader(private val queue: BlockingDeque<CacheItem>, } + private var stream: InputStream? = null + init { context.registerReceiver(connectivityStateReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)) @@ -442,8 +450,8 @@ class FileLoader(private val queue: BlockingDeque<CacheItem>, } } - private fun retry(item: CacheItem) { - item.retries++ + private fun retry(item: CacheItem, dontCount: Boolean = false) { + if (! dontCount) item.retries++ if (item.retries <= MAX_DOWNLOAD_RETRIES) { returnToQueue(item) } else { @@ -512,7 +520,8 @@ class FileLoader(private val queue: BlockingDeque<CacheItem>, break } val buf = ByteArray(LOADER_BUFFER_SIZE) - conn.inputStream.use { + stream = conn.inputStream + stream?.use { while (true) { val read = it.read(buf) if (read < 0) { @@ -533,6 +542,7 @@ class FileLoader(private val queue: BlockingDeque<CacheItem>, } finally { Log.d(LOG_TAG, "Finished download of $url complete $complete") + stream = null item.closeForAppend(complete) } @@ -546,8 +556,14 @@ class FileLoader(private val queue: BlockingDeque<CacheItem>, putItemBack(item) Log.d(LOG_TAG, "Load interrupted in wait") } catch (e: IOException) { - Log.e(LOG_TAG, "Network error for url $url", e) - item?.let { retry(it) } + val dontCount: Boolean = if (e is SocketException && e.message == "Socket closed") { + Log.w(LOG_TAG, "Socket closed probaly due to drop in connection") + true + } else { + Log.e(LOG_TAG, "Network error for url $url", e) + false + } + item?.let { retry(it, dontCount) } } catch (e: Exception) { Log.e(LOG_TAG, "Other error for url $url", e) item?.hasError = true diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 58c4ad3..6c47c83 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -66,4 +66,5 @@ <string name="note_image">Note image</string> <string name="folder_image">Folder Image</string> <string name="image_about_current_folder">Image about current folder</string> + <string name="player_not_ready">Player not ready - probably not connected to server</string> </resources>