Fix "A resource failed to call close." warnings.

This commit is contained in:
Ryan Harg 2022-06-12 12:48:32 +00:00
parent 3f6e010ace
commit 70d9ba241b
20 changed files with 98 additions and 79 deletions

View File

@ -83,7 +83,7 @@ class FFA : Application() {
builder.appendLine(e.toString()) builder.appendLine(e.toString())
FFACache.set(this@FFA, "crashdump", builder.toString().toByteArray()) FFACache.set(this@FFA, "crashdump", builder.toString())
} }
} }

View File

@ -160,17 +160,17 @@ class MainActivity : AppCompatActivity() {
} }
binding.nowPlayingContainer?.nowPlayingDetailsProgress?.setOnSeekBarChangeListener(object : binding.nowPlayingContainer?.nowPlayingDetailsProgress?.setOnSeekBarChangeListener(object :
SeekBar.OnSeekBarChangeListener { SeekBar.OnSeekBarChangeListener {
override fun onStopTrackingTouch(view: SeekBar?) {} override fun onStopTrackingTouch(view: SeekBar?) {}
override fun onStartTrackingTouch(view: SeekBar?) {} override fun onStartTrackingTouch(view: SeekBar?) {}
override fun onProgressChanged(view: SeekBar?, progress: Int, fromUser: Boolean) { override fun onProgressChanged(view: SeekBar?, progress: Int, fromUser: Boolean) {
if (fromUser) { if (fromUser) {
CommandBus.send(Command.Seek(progress)) CommandBus.send(Command.Seek(progress))
}
} }
}) }
})
landscapeQueue?.let { landscapeQueue?.let {
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
@ -379,7 +379,8 @@ class MainActivity : AppCompatActivity() {
when (message.playing) { when (message.playing) {
true -> { true -> {
binding.nowPlayingContainer?.nowPlayingToggle?.icon = getDrawable(R.drawable.pause) binding.nowPlayingContainer?.nowPlayingToggle?.icon = getDrawable(R.drawable.pause)
binding.nowPlayingContainer?.nowPlayingDetailsToggle?.icon = getDrawable(R.drawable.pause) binding.nowPlayingContainer?.nowPlayingDetailsToggle?.icon =
getDrawable(R.drawable.pause)
} }
false -> { false -> {
@ -529,10 +530,10 @@ class MainActivity : AppCompatActivity() {
} }
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.let { now_playing_details_repeat -> binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.let { now_playing_details_repeat ->
changeRepeatMode(FFACache.get(this@MainActivity, "repeat")?.readLine()?.toInt() ?: 0) changeRepeatMode(FFACache.getLine(this@MainActivity, "repeat")?.toInt() ?: 0)
now_playing_details_repeat.setOnClickListener { now_playing_details_repeat.setOnClickListener {
val current = FFACache.get(this@MainActivity, "repeat")?.readLine()?.toInt() ?: 0 val current = FFACache.getLine(this@MainActivity, "repeat")?.toInt() ?: 0
changeRepeatMode((current + 1) % 3) changeRepeatMode((current + 1) % 3)
} }
@ -612,7 +613,7 @@ class MainActivity : AppCompatActivity() {
when (index) { when (index) {
// From no repeat to repeat all // From no repeat to repeat all
0 -> { 0 -> {
FFACache.set(this@MainActivity, "repeat", "0".toByteArray()) FFACache.set(this@MainActivity, "repeat", "0")
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setImageResource(R.drawable.repeat) binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setImageResource(R.drawable.repeat)
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setColorFilter( binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setColorFilter(
@ -628,7 +629,7 @@ class MainActivity : AppCompatActivity() {
// From repeat all to repeat one // From repeat all to repeat one
1 -> { 1 -> {
FFACache.set(this@MainActivity, "repeat", "1".toByteArray()) FFACache.set(this@MainActivity, "repeat", "1")
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setImageResource(R.drawable.repeat) binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setImageResource(R.drawable.repeat)
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setColorFilter( binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setColorFilter(
@ -644,7 +645,7 @@ class MainActivity : AppCompatActivity() {
// From repeat one to no repeat // From repeat one to no repeat
2 -> { 2 -> {
FFACache.set(this@MainActivity, "repeat", "2".toByteArray()) FFACache.set(this@MainActivity, "repeat", "2")
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setImageResource(R.drawable.repeat_one) binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setImageResource(R.drawable.repeat_one)
binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setColorFilter( binding.nowPlayingContainer?.nowPlayingDetailsRepeat?.setColorFilter(
ContextCompat.getColor( ContextCompat.getColor(

View File

@ -66,7 +66,7 @@ class SettingsFragment :
"crash" -> { "crash" -> {
activity?.let { activity -> activity?.let { activity ->
(activity.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager)?.also { clip -> (activity.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager)?.also { clip ->
FFACache.get(activity, "crashdump")?.readLines()?.joinToString("\n").also { FFACache.getLines(activity, "crashdump")?.joinToString("\n").also {
clip.setPrimaryClip(ClipData.newPlainText("Funkwhale logs", it)) clip.setPrimaryClip(ClipData.newPlainText("Funkwhale logs", it))
Toast.makeText( Toast.makeText(

View File

@ -124,7 +124,7 @@ object AddToPlaylistDialog {
FFACache.set( FFACache.set(
context, context,
cacheId, cacheId,
Gson().toJson(cache(adapter.data)).toByteArray() Gson().toJson(cache(adapter.data)).toString()
) )
} catch (e: ConcurrentModificationException) { } catch (e: ConcurrentModificationException) {
} }

View File

@ -150,7 +150,7 @@ abstract class FFAFragment<D : Any, A : FFAAdapter<D, *>>() : Fragment() {
FFACache.set( FFACache.set(
context, context,
cacheId, cacheId,
Gson().toJson(repository.cache(adapter.data)).toByteArray() Gson().toJson(repository.cache(adapter.data)).toString()
) )
} }
} catch (e: ConcurrentModificationException) { } catch (e: ConcurrentModificationException) {

View File

@ -153,8 +153,8 @@ class PlayerService : Service() {
if (queue.current > -1) { if (queue.current > -1) {
player.prepare(queue.dataSources) player.prepare(queue.dataSources)
FFACache.get(this, "progress")?.let { progress -> FFACache.getLine(this, "progress")?.let {
player.seekTo(queue.current, progress.readLine().toLong()) player.seekTo(queue.current, it.toLong())
val (current, duration, percent) = getProgress(true) val (current, duration, percent) = getProgress(true)
@ -303,7 +303,7 @@ class PlayerService : Service() {
if (!state) { if (!state) {
val (progress, _, _) = getProgress() val (progress, _, _) = getProgress()
FFACache.set(this@PlayerService, "progress", progress.toString().toByteArray()) FFACache.set(this@PlayerService, "progress", progress.toString())
} }
if (state && player.playbackState == Player.STATE_IDLE) { if (state && player.playbackState == Player.STATE_IDLE) {
@ -332,7 +332,7 @@ class PlayerService : Service() {
private fun skipToNextTrack() { private fun skipToNextTrack() {
player.next() player.next()
FFACache.set(this@PlayerService, "progress", "0".toByteArray()) FFACache.set(this@PlayerService, "progress", "0")
ProgressBus.send(0, 0, 0) ProgressBus.send(0, 0, 0)
} }
@ -481,7 +481,7 @@ class PlayerService : Service() {
} }
if (queue.get().isNotEmpty() && queue.current() == queue.get() if (queue.get().isNotEmpty() && queue.current() == queue.get()
.last() && radioPlayer.isActive() .last() && radioPlayer.isActive()
) { ) {
scope.launch(IO) { scope.launch(IO) {
if (radioPlayer.lock.tryAcquire()) { if (radioPlayer.lock.tryAcquire()) {
@ -491,7 +491,7 @@ class PlayerService : Service() {
} }
} }
FFACache.set(this@PlayerService, "current", queue.current.toString().toByteArray()) FFACache.set(this@PlayerService, "current", queue.current.toString())
CommandBus.send(Command.RefreshTrack(queue.current())) CommandBus.send(Command.RefreshTrack(queue.current()))
} }

View File

@ -28,7 +28,7 @@ class QueueManager(val context: Context) {
var current = -1 var current = -1
init { init {
FFACache.get(context, "queue")?.let { json -> FFACache.getLine(context, "queue")?.let { json ->
gsonDeserializerOf(QueueCache::class.java).deserialize(json)?.let { cache -> gsonDeserializerOf(QueueCache::class.java).deserialize(json)?.let { cache ->
metadata = cache.data.toMutableList() metadata = cache.data.toMutableList()
@ -45,8 +45,8 @@ class QueueManager(val context: Context) {
} }
} }
FFACache.get(context, "current")?.let { string -> FFACache.getLine(context, "current")?.let {
current = string.readLine().toInt() current = it.toInt()
} }
} }
@ -54,7 +54,7 @@ class QueueManager(val context: Context) {
FFACache.set( FFACache.set(
context, context,
"queue", "queue",
Gson().toJson(QueueCache(metadata)).toByteArray() Gson().toJson(QueueCache(metadata)).toString()
) )
} }

View File

@ -53,10 +53,10 @@ class RadioPlayer(val context: Context, val scope: CoroutineScope) {
private val favoritedRepository = FavoritedRepository(context) private val favoritedRepository = FavoritedRepository(context)
init { init {
FFACache.get(context, "radio_type")?.readLine()?.let { radio_type -> FFACache.getLine(context, "radio_type")?.let { radio_type ->
FFACache.get(context, "radio_id")?.readLine()?.toInt()?.let { radio_id -> FFACache.getLine(context, "radio_id")?.toInt()?.let { radio_id ->
FFACache.get(context, "radio_session")?.readLine()?.toInt()?.let { radio_session -> FFACache.getLine(context, "radio_session")?.toInt()?.let { radio_session ->
val cachedCookie = FFACache.get(context, "radio_cookie")?.readLine() val cachedCookie = FFACache.getLine(context, "radio_cookie")
currentRadio = Radio(radio_id, radio_type, "", "") currentRadio = Radio(radio_id, radio_type, "", "")
session = radio_session session = radio_session
@ -107,10 +107,10 @@ class RadioPlayer(val context: Context, val scope: CoroutineScope) {
session = result.get().id session = result.get().id
cookie = response.header("set-cookie").joinToString(";") cookie = response.header("set-cookie").joinToString(";")
FFACache.set(context, "radio_type", radio.radio_type.toByteArray()) FFACache.set(context, "radio_type", radio.radio_type)
FFACache.set(context, "radio_id", radio.id.toString().toByteArray()) FFACache.set(context, "radio_id", radio.id.toString())
FFACache.set(context, "radio_session", session.toString().toByteArray()) FFACache.set(context, "radio_session", session.toString())
FFACache.set(context, "radio_cookie", cookie.toString().toByteArray()) FFACache.set(context, "radio_cookie", cookie.toString())
prepareNextTrack(true) prepareNextTrack(true)
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -8,7 +8,6 @@ import audio.funkwhale.ffa.utils.OAuth
import com.github.kittinunf.fuel.gson.gsonDeserializerOf import com.github.kittinunf.fuel.gson.gsonDeserializerOf
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import org.koin.java.KoinJavaComponent.inject import org.koin.java.KoinJavaComponent.inject
import java.io.BufferedReader
class AlbumsRepository(override val context: Context?, artistId: Int? = null) : class AlbumsRepository(override val context: Context?, artistId: Int? = null) :
Repository<Album, AlbumsCache>() { Repository<Album, AlbumsCache>() {
@ -35,6 +34,6 @@ class AlbumsRepository(override val context: Context?, artistId: Int? = null) :
} }
override fun cache(data: List<Album>) = AlbumsCache(data) override fun cache(data: List<Album>) = AlbumsCache(data)
override fun uncache(reader: BufferedReader) = override fun uncache(json: String) =
gsonDeserializerOf(AlbumsCache::class.java).deserialize(reader) gsonDeserializerOf(AlbumsCache::class.java).deserialize(json)
} }

View File

@ -9,7 +9,6 @@ import audio.funkwhale.ffa.utils.OAuth
import com.github.kittinunf.fuel.gson.gsonDeserializerOf import com.github.kittinunf.fuel.gson.gsonDeserializerOf
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import org.koin.java.KoinJavaComponent.inject import org.koin.java.KoinJavaComponent.inject
import java.io.BufferedReader
class ArtistTracksRepository(override val context: Context?, private val artistId: Int) : class ArtistTracksRepository(override val context: Context?, private val artistId: Int) :
Repository<Track, TracksCache>() { Repository<Track, TracksCache>() {
@ -27,6 +26,6 @@ class ArtistTracksRepository(override val context: Context?, private val artistI
) )
override fun cache(data: List<Track>) = TracksCache(data) override fun cache(data: List<Track>) = TracksCache(data)
override fun uncache(reader: BufferedReader) = override fun uncache(json: String) =
gsonDeserializerOf(TracksCache::class.java).deserialize(reader) gsonDeserializerOf(TracksCache::class.java).deserialize(json)
} }

View File

@ -26,6 +26,6 @@ class ArtistsRepository(override val context: Context?) : Repository<Artist, Art
) )
override fun cache(data: List<Artist>) = ArtistsCache(data) override fun cache(data: List<Artist>) = ArtistsCache(data)
override fun uncache(reader: BufferedReader) = override fun uncache(json: String) =
gsonDeserializerOf(ArtistsCache::class.java).deserialize(reader) gsonDeserializerOf(ArtistsCache::class.java).deserialize(json)
} }

View File

@ -46,8 +46,8 @@ class FavoritesRepository(override val context: Context?) : Repository<Track, Tr
) )
override fun cache(data: List<Track>) = TracksCache(data) override fun cache(data: List<Track>) = TracksCache(data)
override fun uncache(reader: BufferedReader) = override fun uncache(json: String) =
gsonDeserializerOf(TracksCache::class.java).deserialize(reader) gsonDeserializerOf(TracksCache::class.java).deserialize(json)
private val favoritedRepository = FavoritedRepository(context!!) private val favoritedRepository = FavoritedRepository(context!!)
@ -127,12 +127,12 @@ class FavoritedRepository(override val context: Context?) : Repository<Int, Favo
) )
override fun cache(data: List<Int>) = FavoritedCache(data) override fun cache(data: List<Int>) = FavoritedCache(data)
override fun uncache(reader: BufferedReader) = override fun uncache(json: String) =
gsonDeserializerOf(FavoritedCache::class.java).deserialize(reader) gsonDeserializerOf(FavoritedCache::class.java).deserialize(json)
fun update(context: Context?, scope: CoroutineScope) { fun update(context: Context?, scope: CoroutineScope) {
fetch(Origin.Network.origin).untilNetwork(scope, IO) { favorites, _, _, _ -> fetch(Origin.Network.origin).untilNetwork(scope, IO) { favorites, _, _, _ ->
FFACache.set(context, cacheId, Gson().toJson(cache(favorites)).toByteArray()) FFACache.set(context, cacheId, Gson().toJson(cache(favorites)).toString())
} }
} }
} }

View File

@ -30,8 +30,8 @@ class PlaylistTracksRepository(override val context: Context?, playlistId: Int)
) )
override fun cache(data: List<PlaylistTrack>) = PlaylistTracksCache(data) override fun cache(data: List<PlaylistTrack>) = PlaylistTracksCache(data)
override fun uncache(reader: BufferedReader) = override fun uncache(json: String) =
gsonDeserializerOf(PlaylistTracksCache::class.java).deserialize(reader) gsonDeserializerOf(PlaylistTracksCache::class.java).deserialize(json)
override fun onDataFetched(data: List<PlaylistTrack>): List<PlaylistTrack> = runBlocking { override fun onDataFetched(data: List<PlaylistTrack>): List<PlaylistTrack> = runBlocking {
val favorites = FavoritedRepository(context).fetch(Origin.Network.origin) val favorites = FavoritedRepository(context).fetch(Origin.Network.origin)

View File

@ -38,8 +38,8 @@ class PlaylistsRepository(override val context: Context?) : Repository<Playlist,
) )
override fun cache(data: List<Playlist>) = PlaylistsCache(data) override fun cache(data: List<Playlist>) = PlaylistsCache(data)
override fun uncache(reader: BufferedReader) = override fun uncache(json: String) =
gsonDeserializerOf(PlaylistsCache::class.java).deserialize(reader) gsonDeserializerOf(PlaylistsCache::class.java).deserialize(json)
} }
class ManagementPlaylistsRepository(override val context: Context?) : class ManagementPlaylistsRepository(override val context: Context?) :
@ -58,8 +58,8 @@ class ManagementPlaylistsRepository(override val context: Context?) :
) )
override fun cache(data: List<Playlist>) = PlaylistsCache(data) override fun cache(data: List<Playlist>) = PlaylistsCache(data)
override fun uncache(reader: BufferedReader) = override fun uncache(json: String) =
gsonDeserializerOf(PlaylistsCache::class.java).deserialize(reader) gsonDeserializerOf(PlaylistsCache::class.java).deserialize(json)
suspend fun new(name: String): Int? { suspend fun new(name: String): Int? {
context?.let { context?.let {

View File

@ -26,8 +26,8 @@ class RadiosRepository(override val context: Context?) : Repository<Radio, Radio
) )
override fun cache(data: List<Radio>) = RadiosCache(data) override fun cache(data: List<Radio>) = RadiosCache(data)
override fun uncache(reader: BufferedReader) = override fun uncache(json: String) =
gsonDeserializerOf(RadiosCache::class.java).deserialize(reader) gsonDeserializerOf(RadiosCache::class.java).deserialize(json)
override fun onDataFetched(data: List<Radio>): List<Radio> { override fun onDataFetched(data: List<Radio>): List<Radio> {
return data return data

View File

@ -34,7 +34,7 @@ abstract class Repository<D : Any, C : CacheItem<D>> {
abstract val upstream: Upstream<D> abstract val upstream: Upstream<D>
open fun cache(data: List<D>): C? = null open fun cache(data: List<D>): C? = null
protected open fun uncache(reader: BufferedReader): C? = null protected open fun uncache(json: String): C? = null
fun fetch( fun fetch(
upstreams: Int = Origin.Cache.origin and Origin.Network.origin, upstreams: Int = Origin.Cache.origin and Origin.Network.origin,
@ -46,8 +46,8 @@ abstract class Repository<D : Any, C : CacheItem<D>> {
private fun fromCache() = flow { private fun fromCache() = flow {
cacheId?.let { cacheId -> cacheId?.let { cacheId ->
FFACache.get(context, cacheId)?.let { reader -> FFACache.getLine(context, cacheId)?.let { line ->
uncache(reader)?.let { cache -> uncache(line)?.let { cache ->
return@flow emit( return@flow emit(
Response( Response(
Origin.Cache, Origin.Cache,

View File

@ -42,8 +42,8 @@ class TracksSearchRepository(override val context: Context?, var query: String)
) )
override fun cache(data: List<Track>) = TracksCache(data) override fun cache(data: List<Track>) = TracksCache(data)
override fun uncache(reader: BufferedReader) = override fun uncache(json: String) =
gsonDeserializerOf(TracksCache::class.java).deserialize(reader) gsonDeserializerOf(TracksCache::class.java).deserialize(json)
override fun onDataFetched(data: List<Track>): List<Track> = runBlocking { override fun onDataFetched(data: List<Track>): List<Track> = runBlocking {
val favorites = FavoritedRepository(context).fetch(Origin.Cache.origin) val favorites = FavoritedRepository(context).fetch(Origin.Cache.origin)
@ -84,8 +84,8 @@ class ArtistsSearchRepository(override val context: Context?, var query: String)
) )
override fun cache(data: List<Artist>) = ArtistsCache(data) override fun cache(data: List<Artist>) = ArtistsCache(data)
override fun uncache(reader: BufferedReader) = override fun uncache(json: String) =
gsonDeserializerOf(ArtistsCache::class.java).deserialize(reader) gsonDeserializerOf(ArtistsCache::class.java).deserialize(json)
} }
class AlbumsSearchRepository(override val context: Context?, var query: String) : class AlbumsSearchRepository(override val context: Context?, var query: String) :
@ -104,6 +104,6 @@ class AlbumsSearchRepository(override val context: Context?, var query: String)
) )
override fun cache(data: List<Album>) = AlbumsCache(data) override fun cache(data: List<Album>) = AlbumsCache(data)
override fun uncache(reader: BufferedReader) = override fun uncache(json: String) =
gsonDeserializerOf(AlbumsCache::class.java).deserialize(reader) gsonDeserializerOf(AlbumsCache::class.java).deserialize(json)
} }

View File

@ -38,8 +38,8 @@ class TracksRepository(override val context: Context?, albumId: Int) :
) )
override fun cache(data: List<Track>) = TracksCache(data) override fun cache(data: List<Track>) = TracksCache(data)
override fun uncache(reader: BufferedReader) = override fun uncache(json: String) =
gsonDeserializerOf(TracksCache::class.java).deserialize(reader) gsonDeserializerOf(TracksCache::class.java).deserialize(json)
companion object { companion object {
fun getDownloadedIds(exoDownloadManager: DownloadManager): List<Int>? { fun getDownloadedIds(exoDownloadManager: DownloadManager): List<Int>? {

View File

@ -12,16 +12,41 @@ object FFACache {
val md = MessageDigest.getInstance("SHA-1") val md = MessageDigest.getInstance("SHA-1")
val digest = md.digest(key.toByteArray(Charset.defaultCharset())) val digest = md.digest(key.toByteArray(Charset.defaultCharset()))
return digest.fold("", { acc, it -> acc + "%02x".format(it) }) return digest.fold("") { acc, it -> acc + "%02x".format(it) }
} }
fun set(context: Context?, key: String, value: ByteArray) = context?.let { fun set(context: Context?, key:String, value: String){
with(File(it.cacheDir, key(key))) { set(context, key, value.toByteArray())
writeBytes(value) }
fun set(context: Context?, key: String, value: ByteArray) {
context?.let {
with(File(it.cacheDir, key(key))) {
writeBytes(value)
}
} }
} }
fun get(context: Context?, key: String): BufferedReader? = context?.let { fun getLine(context: Context?, key: String): String? = get(context, key)?.let {
val line = it.readLine()
it.close()
line
}
fun getLines(context: Context?, key: String): List<String>? = get(context, key)
?.let { reader ->
val lines = reader.readLines()
reader.close()
lines
}
fun delete(context: Context?, key: String) = context?.let {
with(File(it.cacheDir, key(key))) {
delete()
}
}
private fun get(context: Context?, key: String): BufferedReader? = context?.let {
try { try {
with(File(it.cacheDir, key(key))) { with(File(it.cacheDir, key(key))) {
bufferedReader() bufferedReader()
@ -30,10 +55,4 @@ object FFACache {
return null return null
} }
} }
fun delete(context: Context?, key: String) = context?.let {
with(File(it.cacheDir, key(key))) {
delete()
}
}
} }

View File

@ -0,0 +1 @@
Fix warnings in log output due to leaked BufferedReader resource (thanks @hdash)