Run download task inside service
This commit is contained in:
parent
8ab903c7d2
commit
ba745a5f9a
|
@ -119,7 +119,7 @@ class Downloader(
|
||||||
while (activelyDownloading.size < PARALLEL_DOWNLOADS && downloadQueue.size > 0) {
|
while (activelyDownloading.size < PARALLEL_DOWNLOADS && downloadQueue.size > 0) {
|
||||||
val task = downloadQueue.remove()
|
val task = downloadQueue.remove()
|
||||||
activelyDownloading.add(task)
|
activelyDownloading.add(task)
|
||||||
task.download()
|
startDownloadOnService(task)
|
||||||
|
|
||||||
// The next file on the playlist is currently downloading
|
// The next file on the playlist is currently downloading
|
||||||
if (playlist.indexOf(task) == 1) {
|
if (playlist.indexOf(task) == 1) {
|
||||||
|
@ -128,6 +128,12 @@ class Downloader(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun startDownloadOnService(task: DownloadFile) {
|
||||||
|
MediaPlayerService.executeOnStartedMediaPlayerService {
|
||||||
|
task.download()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun cleanupActiveDownloads() {
|
private fun cleanupActiveDownloads() {
|
||||||
activelyDownloading.retainAll {
|
activelyDownloading.retainAll {
|
||||||
when {
|
when {
|
||||||
|
|
|
@ -18,11 +18,11 @@
|
||||||
*/
|
*/
|
||||||
package org.moire.ultrasonic.util;
|
package org.moire.ultrasonic.util;
|
||||||
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
|
@ -93,7 +93,7 @@ public abstract class CancellableTask
|
||||||
thread.get().start();
|
thread.get().start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface OnCancelListener
|
public interface OnCancelListener
|
||||||
{
|
{
|
||||||
void onCancel();
|
void onCancel();
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,6 @@ public final class Constants
|
||||||
public static final String PREFERENCES_KEY_PRELOAD_COUNT = "preloadCount";
|
public static final String PREFERENCES_KEY_PRELOAD_COUNT = "preloadCount";
|
||||||
public static final String PREFERENCES_KEY_HIDE_MEDIA = "hideMedia";
|
public static final String PREFERENCES_KEY_HIDE_MEDIA = "hideMedia";
|
||||||
public static final String PREFERENCES_KEY_MEDIA_BUTTONS = "mediaButtons";
|
public static final String PREFERENCES_KEY_MEDIA_BUTTONS = "mediaButtons";
|
||||||
public static final String PREFERENCES_KEY_SCREEN_LIT_ON_DOWNLOAD = "screenLitOnDownload";
|
|
||||||
public static final String PREFERENCES_KEY_SCROBBLE = "scrobble";
|
public static final String PREFERENCES_KEY_SCROBBLE = "scrobble";
|
||||||
public static final String PREFERENCES_KEY_SERVER_SCALING = "serverScaling";
|
public static final String PREFERENCES_KEY_SERVER_SCALING = "serverScaling";
|
||||||
public static final String PREFERENCES_KEY_REPEAT_MODE = "repeatMode";
|
public static final String PREFERENCES_KEY_REPEAT_MODE = "repeatMode";
|
||||||
|
|
|
@ -162,8 +162,7 @@ class ImageLoader(
|
||||||
var inputStream: InputStream? = null
|
var inputStream: InputStream? = null
|
||||||
try {
|
try {
|
||||||
inputStream = response.stream
|
inputStream = response.stream
|
||||||
val bytes = Util.toByteArray(inputStream)
|
val bytes = inputStream!!.readBytes()
|
||||||
|
|
||||||
var outputStream: OutputStream? = null
|
var outputStream: OutputStream? = null
|
||||||
try {
|
try {
|
||||||
outputStream = FileOutputStream(file)
|
outputStream = FileOutputStream(file)
|
||||||
|
|
|
@ -7,21 +7,11 @@
|
||||||
|
|
||||||
package org.moire.ultrasonic.service
|
package org.moire.ultrasonic.service
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.net.wifi.WifiManager.WifiLock
|
import android.net.wifi.WifiManager.WifiLock
|
||||||
import android.os.PowerManager
|
|
||||||
import android.os.PowerManager.WakeLock
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import java.io.File
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.io.IOException
|
|
||||||
import java.io.InputStream
|
|
||||||
import java.io.OutputStream
|
|
||||||
import java.io.RandomAccessFile
|
|
||||||
import org.koin.core.component.KoinComponent
|
import org.koin.core.component.KoinComponent
|
||||||
import org.koin.core.component.inject
|
import org.koin.core.component.inject
|
||||||
import org.moire.ultrasonic.app.UApp
|
|
||||||
import org.moire.ultrasonic.domain.MusicDirectory
|
import org.moire.ultrasonic.domain.MusicDirectory
|
||||||
import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService
|
import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService
|
||||||
import org.moire.ultrasonic.subsonic.ImageLoaderProvider
|
import org.moire.ultrasonic.subsonic.ImageLoaderProvider
|
||||||
|
@ -30,6 +20,12 @@ import org.moire.ultrasonic.util.CancellableTask
|
||||||
import org.moire.ultrasonic.util.FileUtil
|
import org.moire.ultrasonic.util.FileUtil
|
||||||
import org.moire.ultrasonic.util.Util
|
import org.moire.ultrasonic.util.Util
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.io.OutputStream
|
||||||
|
import java.io.RandomAccessFile
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents a singe Song or Video that can be downloaded.
|
* This class represents a singe Song or Video that can be downloaded.
|
||||||
|
@ -208,10 +204,8 @@ class DownloadFile(
|
||||||
override fun execute() {
|
override fun execute() {
|
||||||
var inputStream: InputStream? = null
|
var inputStream: InputStream? = null
|
||||||
var outputStream: FileOutputStream? = null
|
var outputStream: FileOutputStream? = null
|
||||||
var wakeLock: WakeLock? = null
|
|
||||||
var wifiLock: WifiLock? = null
|
var wifiLock: WifiLock? = null
|
||||||
try {
|
try {
|
||||||
wakeLock = acquireWakeLock(wakeLock)
|
|
||||||
wifiLock = Util.createWifiLock(toString())
|
wifiLock = Util.createWifiLock(toString())
|
||||||
wifiLock.acquire()
|
wifiLock.acquire()
|
||||||
|
|
||||||
|
@ -306,29 +300,12 @@ class DownloadFile(
|
||||||
} finally {
|
} finally {
|
||||||
Util.close(inputStream)
|
Util.close(inputStream)
|
||||||
Util.close(outputStream)
|
Util.close(outputStream)
|
||||||
if (wakeLock != null) {
|
|
||||||
wakeLock.release()
|
|
||||||
Timber.i("Released wake lock %s", wakeLock)
|
|
||||||
}
|
|
||||||
wifiLock?.release()
|
wifiLock?.release()
|
||||||
CacheCleaner().cleanSpace()
|
CacheCleaner().cleanSpace()
|
||||||
downloader.checkDownloads()
|
downloader.checkDownloads()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun acquireWakeLock(wakeLock: WakeLock?): WakeLock? {
|
|
||||||
var wakeLock1 = wakeLock
|
|
||||||
if (Util.isScreenLitOnDownload()) {
|
|
||||||
val context = UApp.applicationContext()
|
|
||||||
val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager
|
|
||||||
val flags = PowerManager.SCREEN_DIM_WAKE_LOCK or PowerManager.ON_AFTER_RELEASE
|
|
||||||
wakeLock1 = pm.newWakeLock(flags, toString())
|
|
||||||
wakeLock1.acquire(10 * 60 * 1000L /*10 minutes*/)
|
|
||||||
Timber.i("Acquired wake lock %s", wakeLock1)
|
|
||||||
}
|
|
||||||
return wakeLock1
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return String.format("DownloadTask (%s)", song)
|
return String.format("DownloadTask (%s)", song)
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,9 @@ import timber.log.Timber
|
||||||
/**
|
/**
|
||||||
* Android Foreground Service for playing music
|
* Android Foreground Service for playing music
|
||||||
* while the rest of the Ultrasonic App is in the background.
|
* while the rest of the Ultrasonic App is in the background.
|
||||||
|
*
|
||||||
|
* "A foreground service is a service that the user is
|
||||||
|
* actively aware of and isn’t a candidate for the system to kill when low on memory."
|
||||||
*/
|
*/
|
||||||
@Suppress("LargeClass")
|
@Suppress("LargeClass")
|
||||||
class MediaPlayerService : Service() {
|
class MediaPlayerService : Service() {
|
||||||
|
|
|
@ -102,14 +102,6 @@ object Util {
|
||||||
return applicationContext()
|
return applicationContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isScreenLitOnDownload(): Boolean {
|
|
||||||
val preferences = getPreferences()
|
|
||||||
return preferences.getBoolean(
|
|
||||||
Constants.PREFERENCES_KEY_SCREEN_LIT_ON_DOWNLOAD,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
var repeatMode: RepeatMode
|
var repeatMode: RepeatMode
|
||||||
get() {
|
get() {
|
||||||
val preferences = getPreferences()
|
val preferences = getPreferences()
|
||||||
|
@ -221,38 +213,6 @@ object Util {
|
||||||
fun getPreferences(): SharedPreferences =
|
fun getPreferences(): SharedPreferences =
|
||||||
PreferenceManager.getDefaultSharedPreferences(appContext())
|
PreferenceManager.getDefaultSharedPreferences(appContext())
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the contents of an `InputStream` as a `byte[]`.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This method buffers the input internally, so there is no need to use a
|
|
||||||
* `BufferedInputStream`.
|
|
||||||
*
|
|
||||||
* @param input the `InputStream` to read from
|
|
||||||
* @return the requested byte array
|
|
||||||
* @throws NullPointerException if the input is null
|
|
||||||
* @throws java.io.IOException if an I/O error occurs
|
|
||||||
*/
|
|
||||||
@Throws(IOException::class)
|
|
||||||
fun toByteArray(input: InputStream?): ByteArray {
|
|
||||||
val output = ByteArrayOutputStream()
|
|
||||||
copy(input!!, output)
|
|
||||||
return output.toByteArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(IOException::class)
|
|
||||||
@Suppress("MagicNumber")
|
|
||||||
fun copy(input: InputStream, output: OutputStream): Long {
|
|
||||||
val buffer = ByteArray(KBYTE * 4)
|
|
||||||
var count: Long = 0
|
|
||||||
var n: Int
|
|
||||||
while (-1 != input.read(buffer).also { n = it }) {
|
|
||||||
output.write(buffer, 0, n)
|
|
||||||
count += n.toLong()
|
|
||||||
}
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
fun atomicCopy(from: File, to: File) {
|
fun atomicCopy(from: File, to: File) {
|
||||||
val tmp = File(String.format(Locale.ROOT, "%s.tmp", to.path))
|
val tmp = File(String.format(Locale.ROOT, "%s.tmp", to.path))
|
||||||
|
|
|
@ -343,12 +343,6 @@
|
||||||
a:summary="@string/settings.hide_media_summary"
|
a:summary="@string/settings.hide_media_summary"
|
||||||
a:title="@string/settings.hide_media_title"
|
a:title="@string/settings.hide_media_title"
|
||||||
app:iconSpaceReserved="false"/>
|
app:iconSpaceReserved="false"/>
|
||||||
<CheckBoxPreference
|
|
||||||
a:defaultValue="true"
|
|
||||||
a:key="screenLitOnDownload"
|
|
||||||
a:summary="@string/settings.screen_lit_summary"
|
|
||||||
a:title="@string/settings.screen_lit_title"
|
|
||||||
app:iconSpaceReserved="false"/>
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
a:title="@string/feature_flags_category_title"
|
a:title="@string/feature_flags_category_title"
|
||||||
|
|
Loading…
Reference in New Issue