Merge branch 'fixCrashes' into 'develop'

Fix crashes

Closes #832 and #823

See merge request ultrasonic/ultrasonic!851
This commit is contained in:
birdbird 2022-10-12 11:48:49 +00:00
commit 4b35a4bcbf
4 changed files with 79 additions and 76 deletions

View File

@ -22,7 +22,6 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.ImageView
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat
@ -221,8 +220,6 @@ class NavigationActivity : AppCompatActivity() {
cachedServerCount = count ?: 0
updateNavigationHeaderForServer()
}
onBackPressedDispatcher.addCallback(this, callback)
}
override fun onResume() {
@ -340,16 +337,13 @@ class NavigationActivity : AppCompatActivity() {
setupActionBarWithNavController(navController, appBarConfig)
}
val callback: OnBackPressedCallback = object : OnBackPressedCallback(
true
) {
override fun handleOnBackPressed() {
if (drawerLayout?.isDrawerVisible(GravityCompat.START) == true) {
drawerLayout?.closeDrawer(GravityCompat.START)
} else {
val currentFragment = host!!.childFragmentManager.fragments.last()
if (currentFragment is OnBackPressedHandler) currentFragment.onBackPressed()
}
override fun onBackPressed() {
if (drawerLayout?.isDrawerVisible(GravityCompat.START) == true) {
this.drawerLayout?.closeDrawer(GravityCompat.START)
} else {
val currentFragment = host!!.childFragmentManager.fragments.last()
if (currentFragment is OnBackPressedHandler) currentFragment.onBackPressed()
else super.onBackPressed()
}
}

View File

@ -775,11 +775,12 @@ class PlayerFragment :
Util.toast(context, resources.getString(R.string.download_playlist_saving, playlistName))
mediaPlayerController.suggestedPlaylistName = playlistName
ioScope.launch {
// The playlist can be acquired only from the main thread
val entries = mediaPlayerController.playlist.map {
it.toTrack()
}
val entries = mediaPlayerController.playlist.map {
it.toTrack()
}
ioScope.launch {
val musicService = getMusicService()
musicService.createPlaylist(null, playlistName, entries)
}.invokeOnCompletion {

View File

@ -266,7 +266,7 @@ class DownloadService : Service(), KoinComponent {
return notificationBuilder.build()
}
@Suppress("MagicNumber")
@Suppress("MagicNumber", "NestedBlockDepth")
companion object {
private var startFuture: SettableFuture<DownloadService>? = null
@ -291,7 +291,12 @@ class DownloadService : Service(), KoinComponent {
if (save) {
tracks.filter { Storage.isPathExists(it.getCompleteFile()) }.forEach { track ->
Storage.getFromPath(track.getCompleteFile())?.let {
Storage.rename(it, track.getPinnedFile())
try {
Storage.rename(it, track.getPinnedFile())
} catch (ignored: FileAlreadyExistsException) {
// Play console has revealed a crash when for some reason both files exist
Storage.delete(it.path)
}
postState(track, DownloadState.PINNED)
}
}
@ -299,7 +304,12 @@ class DownloadService : Service(), KoinComponent {
} else {
tracks.filter { Storage.isPathExists(it.getPinnedFile()) }.forEach { track ->
Storage.getFromPath(track.getPinnedFile())?.let {
Storage.rename(it, track.getCompleteFile())
try {
Storage.rename(it, track.getCompleteFile())
} catch (ignored: FileAlreadyExistsException) {
// Play console has revealed a crash when for some reason both files exist
Storage.delete(it.path)
}
postState(track, DownloadState.DONE)
}
}
@ -367,7 +377,12 @@ class DownloadService : Service(), KoinComponent {
val pinnedFile = track.getPinnedFile()
if (!Storage.isPathExists(pinnedFile)) return
val file = Storage.getFromPath(track.getPinnedFile()) ?: return
Storage.rename(file, track.getCompleteFile())
try {
Storage.rename(file, track.getCompleteFile())
} catch (ignored: FileAlreadyExistsException) {
// Play console has revealed a crash when for some reason both files exist
Storage.delete(file.path)
}
postState(track, DownloadState.DONE)
}

View File

@ -81,73 +81,66 @@ class DownloadTask(
stateChangedCallback(item, DownloadState.DOWNLOADING, null)
// Some devices seem to throw error on partial file which doesn't exist
val needsDownloading: Boolean
val duration = item.track.duration
val fileLength = Storage.getFromPath(item.partialFile)?.length ?: 0
needsDownloading = (duration == null || duration == 0 || fileLength == 0L)
// Attempt partial HTTP GET, appending to the file if it exists.
val (inStream, isPartial) = musicService.getDownloadInputStream(
item.track, fileLength,
Settings.maxBitRate,
item.pinned
)
if (needsDownloading) {
// Attempt partial HTTP GET, appending to the file if it exists.
val (inStream, isPartial) = musicService.getDownloadInputStream(
item.track, fileLength,
Settings.maxBitRate,
item.pinned
)
inputStream = inStream
inputStream = inStream
if (isPartial) {
Timber.i("Executed partial HTTP GET, skipping %d bytes", fileLength)
}
if (isPartial) {
Timber.i("Executed partial HTTP GET, skipping %d bytes", fileLength)
}
outputStream = Storage.getOrCreateFileFromPath(item.partialFile)
.getFileOutputStream(isPartial)
outputStream = Storage.getOrCreateFileFromPath(item.partialFile)
.getFileOutputStream(isPartial)
var lastPostTime: Long = 0
val len = inputStream.copyTo(outputStream) { totalBytesCopied ->
// Manual throttling to avoid overloading Rx
if (SystemClock.elapsedRealtime() - lastPostTime > REFRESH_INTERVAL) {
lastPostTime = SystemClock.elapsedRealtime()
var lastPostTime: Long = 0
val len = inputStream.copyTo(outputStream) { totalBytesCopied ->
// Manual throttling to avoid overloading Rx
if (SystemClock.elapsedRealtime() - lastPostTime > REFRESH_INTERVAL) {
lastPostTime = SystemClock.elapsedRealtime()
// If the file size is unknown we can only provide null as the progress
val size = item.track.size ?: 0
val progress = if (size <= 0) {
null
} else {
(totalBytesCopied * 100 / (size)).toInt()
}
stateChangedCallback(
item,
DownloadState.DOWNLOADING,
progress
)
// If the file size is unknown we can only provide null as the progress
val size = item.track.size ?: 0
val progress = if (size <= 0) {
null
} else {
(totalBytesCopied * 100 / (size)).toInt()
}
}
Timber.i("Downloaded %d bytes to %s", len, item.partialFile)
inputStream.close()
outputStream.flush()
outputStream.close()
if (isCancelled) {
stateChangedCallback(item, DownloadState.CANCELLED, null)
throw RuntimeException(
String.format(
Locale.ROOT, "Download of '%s' was cancelled",
item
)
stateChangedCallback(
item,
DownloadState.DOWNLOADING,
progress
)
}
}
try {
item.track.cacheMetadataAndArtwork()
} catch (ignore: Exception) {
Timber.w(ignore)
}
Timber.i("Downloaded %d bytes to %s", len, item.partialFile)
inputStream.close()
outputStream.flush()
outputStream.close()
if (isCancelled) {
stateChangedCallback(item, DownloadState.CANCELLED, null)
throw RuntimeException(
String.format(
Locale.ROOT, "Download of '%s' was cancelled",
item
)
)
}
try {
item.track.cacheMetadataAndArtwork()
} catch (ignore: Exception) {
Timber.w(ignore)
}
if (item.pinned) {