diff --git a/app/src/main/java/eu/zderadicka/audioserve/AudioService.kt b/app/src/main/java/eu/zderadicka/audioserve/AudioService.kt index b9f95b5..e89e359 100644 --- a/app/src/main/java/eu/zderadicka/audioserve/AudioService.kt +++ b/app/src/main/java/eu/zderadicka/audioserve/AudioService.kt @@ -666,7 +666,7 @@ mediaSessionConnector.setErrorMessageProvider(messageProvider); else -> { result.detach() val t = Thread({ - val res = cacheManager.cacheBrowser.listFolder(parentId) + val res = cacheManager.cacheBrowser.listFolder(parentId, options.getBoolean(AUDIOSERVICE_FORCE_RELOAD)) currentFolder = res.filter{it.isPlayable} result.sendResult(res) prepareLatestItem(folderIdFromOfflinePath(parentId), options) diff --git a/app/src/main/java/eu/zderadicka/audioserve/SettingsActivity.kt b/app/src/main/java/eu/zderadicka/audioserve/SettingsActivity.kt index 157b636..d7351ac 100644 --- a/app/src/main/java/eu/zderadicka/audioserve/SettingsActivity.kt +++ b/app/src/main/java/eu/zderadicka/audioserve/SettingsActivity.kt @@ -101,7 +101,7 @@ class SettingsFragment: PreferenceFragment(), SharedPreferences.OnSharedPreferen Thread({ ApiClient.clearCache(activity) - CacheManager.clearCache(activity) + CacheManager.clearCache() activity.runOnUiThread({ Toast.makeText(activity, "Cache cleared", Toast.LENGTH_LONG).show() }) diff --git a/app/src/main/java/eu/zderadicka/audioserve/net/CacheBrowser.kt b/app/src/main/java/eu/zderadicka/audioserve/net/CacheBrowser.kt index 8a6b302..169ade6 100644 --- a/app/src/main/java/eu/zderadicka/audioserve/net/CacheBrowser.kt +++ b/app/src/main/java/eu/zderadicka/audioserve/net/CacheBrowser.kt @@ -3,7 +3,9 @@ import android.media.MediaMetadataRetriever import android.os.Bundle import android.support.v4.media.MediaBrowserCompat import android.support.v4.media.MediaDescriptionCompat +import android.text.format.DateUtils import android.util.Log +import android.util.LruCache import eu.zderadicka.audioserve.data.* import eu.zderadicka.audioserve.utils.splitExtension import java.io.File @@ -40,8 +42,6 @@ private fun fileToItem(mediaId: String, cacheDir: File): MediaBrowserCompat.Medi try { val duration = metaExtractor.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() extras.putLong(METADATA_KEY_DURATION, duration!!) // in miliseconds - val bitrate = metaExtractor.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE)?.toInt() - } catch (e: NumberFormatException) { Log.e(LOG_TAG, "Wrong duration value") } @@ -71,7 +71,10 @@ private fun fileToItem(mediaId: String, cacheDir: File): MediaBrowserCompat.Medi return item } +private const val MAX_CACHE_LIVE = 24 * DateUtils.HOUR_IN_MILLIS class CacheBrowser(val ids: List, val cacheDir:File) { + private val cache = LruCache(16) + val rootFolder :List by lazy() { listRootFolder() } @@ -80,8 +83,8 @@ class CacheBrowser(val ids: List, val cacheDir:File) { val rootFolders = HashSet() for (id in ids) { val segments = id.split(SEP) - val name_idx = if (segments[0] == "audio") 1 else if (segments[1] == "audio") 2 else continue - rootFolders.add(segments.take(name_idx+1).joinToString(SEP)) + val nameIdx = if (segments[0] == "audio") 1 else if (segments[1] == "audio") 2 else continue + rootFolders.add(segments.take(nameIdx+1).joinToString(SEP)) } return rootFolders.toList().sorted().map{ subfolderToItem(it)} @@ -90,7 +93,7 @@ class CacheBrowser(val ids: List, val cacheDir:File) { } val FOLDER_RE = Regex("""^(\d+/)?folder/""") - fun listFolder(folderId: String):List { + fun listFolder(folderId: String, noCache:Boolean = false):List { val folderMatch = FOLDER_RE.find(folderId) @Suppress("NAME_SHADOWING") val folderId = if (folderMatch!= null) { @@ -99,6 +102,14 @@ class CacheBrowser(val ids: List, val cacheDir:File) { } else { folderId } + + if (!noCache) { + val cachedEntry = cache.get(folderId) + if (cachedEntry != null && System.currentTimeMillis() - cachedEntry.timestamp < MAX_CACHE_LIVE) { + return cachedEntry.data + } + } + val folders = HashSet() val files = ArrayList() val items = ArrayList() @@ -123,6 +134,13 @@ class CacheBrowser(val ids: List, val cacheDir:File) { if (item == null) continue items.add(item) } + cache.put(folderId, CacheItem(System.currentTimeMillis(), items)) return items } -} \ No newline at end of file + + fun clearCache() { + cache.evictAll() + } + private data class CacheItem(val timestamp: Long, val data: List) +} + 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 ae98443..028d9f5 100644 --- a/app/src/main/java/eu/zderadicka/audioserve/net/CacheManager.kt +++ b/app/src/main/java/eu/zderadicka/audioserve/net/CacheManager.kt @@ -1,5 +1,6 @@ package eu.zderadicka.audioserve.net +import android.annotation.SuppressLint import android.content.Context import android.content.SharedPreferences import android.net.Uri @@ -200,7 +201,6 @@ class CacheManager private constructor(val context: Context) { cacheDir = File(File(cacheBase), MEDIA_CACHE_DIR) val cacheSize: Long = PreferenceManager.getDefaultSharedPreferences(context).getString("pref_cache_size", DEFAULT_CACHE_SIZE_MB.toString()).toLong() * 1024 * 1024 - val baseUrl:String = PreferenceManager.getDefaultSharedPreferences(context).getString("pref_server_url","") cache = FileCache(cacheDir,cacheSize, context) transcode = transcodingFromPrefs(context) PreferenceManager.getDefaultSharedPreferences(context).registerOnSharedPreferenceChangeListener(prefsListener) @@ -217,7 +217,7 @@ class CacheManager private constructor(val context: Context) { cache.stopLoader() } - + @Suppress("UNCHECKED_CAST") private fun reset() { cache.stopLoader() val cacheBase = PreferenceManager.getDefaultSharedPreferences(context).getString("pref_cache_location", @@ -225,7 +225,6 @@ class CacheManager private constructor(val context: Context) { cacheDir = File(File(cacheBase), MEDIA_CACHE_DIR) val cacheSize: Long = PreferenceManager.getDefaultSharedPreferences(context).getString("pref_cache_size", DEFAULT_CACHE_SIZE_MB.toString()).toLong() * 1024 * 1024 - val baseUrl:String = PreferenceManager.getDefaultSharedPreferences(context).getString("pref_server_url","") val oldListeners: HashSet = cache.listeners.clone() as HashSet cache.removeAllListeners() cache = FileCache(cacheDir, cacheSize, context) @@ -242,6 +241,7 @@ class CacheManager private constructor(val context: Context) { private fun clearCache() { cache.resetIndex(true) + cacheBrowser.clearCache() } fun isCached(mediaId: String): Boolean { @@ -298,6 +298,7 @@ class CacheManager private constructor(val context: Context) { } companion object { + @SuppressLint("StaticFieldLeak") // should be OK as we save only app context @Volatile private var instance: CacheManager? = null @@ -310,7 +311,7 @@ class CacheManager private constructor(val context: Context) { } @Synchronized - fun clearCache(context: Context) { + fun clearCache() { try { instance?.clearCache() } catch (e: Exception) {