diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6d504cc1..bfc756f2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -33,6 +33,19 @@
+
+
+
+
+
+
+
+
= Build.VERSION_CODES.O) {
+ context?.startForegroundService(Intent(context, VideoDownloadKeepAliveService::class.java).putExtra(START_VALUE_KEY, RESTART_ALL_DOWNLOADS_AND_QUEUE))
+ } else {
+ context?.startService(Intent(context, VideoDownloadKeepAliveService::class.java).putExtra(START_VALUE_KEY, RESTART_ALL_DOWNLOADS_AND_QUEUE))
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lagradost/cloudstream3/services/VideoDownloadKeepAliveService.kt b/app/src/main/java/com/lagradost/cloudstream3/services/VideoDownloadKeepAliveService.kt
new file mode 100644
index 00000000..f43f02e2
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/services/VideoDownloadKeepAliveService.kt
@@ -0,0 +1,51 @@
+package com.lagradost.cloudstream3.services
+
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+import com.lagradost.cloudstream3.recivers.VideoDownloadRestartReceiver
+import com.lagradost.cloudstream3.utils.DataStore.getKey
+import com.lagradost.cloudstream3.utils.DataStore.getKeys
+import com.lagradost.cloudstream3.utils.VideoDownloadManager
+
+const val RESTART_ALL_DOWNLOADS_AND_QUEUE = 1
+const val RESTART_NONE = 0
+const val START_VALUE_KEY = "start_value"
+
+class VideoDownloadKeepAliveService : Service() {
+ override fun onBind(p0: Intent?): IBinder? {
+ return null
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ val startValue = intent?.getIntExtra(START_VALUE_KEY, RESTART_NONE) ?: RESTART_NONE
+ if (startValue == RESTART_ALL_DOWNLOADS_AND_QUEUE) {
+ val keys = this.getKeys(VideoDownloadManager.KEY_RESUME_PACKAGES)
+ val resumePkg = keys.mapNotNull { k -> this.getKey(k) }
+
+ for (pkg in resumePkg) { // ADD ALL CURRENT DOWNLOADS
+ VideoDownloadManager.downloadFromResume(this, pkg)
+ }
+
+ // ADD QUEUE
+ val resumeQueue =
+ this.getKey>(VideoDownloadManager.KEY_RESUME_QUEUE_PACKAGES)
+ if (resumeQueue != null && resumeQueue.isNotEmpty()) {
+ val sorted = resumeQueue.sortedBy { item -> item.index }
+ for (queueItem in sorted) {
+ VideoDownloadManager.downloadFromResume(this, queueItem.pkg)
+ }
+ }
+ }
+
+ return START_STICKY//super.onStartCommand(intent, flags, startId)
+ }
+
+ override fun onDestroy() {
+ val broadcastIntent = Intent()
+ broadcastIntent.action = "restart_service"
+ broadcastIntent.setClass(this, VideoDownloadRestartReceiver::class.java)
+ this.sendBroadcast(broadcastIntent)
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt
index 8961183e..17e58aa7 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt
@@ -1,5 +1,6 @@
package com.lagradost.cloudstream3.utils
+import android.app.ActivityManager
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
@@ -20,6 +21,9 @@ import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.UIHelper.colorFromAttribute
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
+import com.lagradost.cloudstream3.services.RESTART_NONE
+import com.lagradost.cloudstream3.services.START_VALUE_KEY
+import com.lagradost.cloudstream3.services.VideoDownloadKeepAliveService
import com.lagradost.cloudstream3.services.VideoDownloadService
import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.cloudstream3.utils.DataStore.getKey
@@ -33,8 +37,7 @@ import java.lang.Thread.sleep
import java.net.URL
import java.net.URLConnection
import java.util.*
-import kotlin.collections.ArrayList
-import kotlin.collections.HashMap
+
const val DOWNLOAD_CHANNEL_ID = "cloudstream3.general"
const val DOWNLOAD_CHANNEL_NAME = "Downloads"
@@ -119,6 +122,11 @@ object VideoDownloadManager {
val path: Uri,
)
+ data class DownloadQueueResumePackage(
+ val index: Int,
+ val pkg: DownloadResumePackage,
+ )
+
private const val SUCCESS_DOWNLOAD_DONE = 1
private const val SUCCESS_STOPPED = 2
private const val ERROR_DELETING_FILE = -1
@@ -131,8 +139,9 @@ object VideoDownloadManager {
private const val ERROR_CONTENT_RESOLVER_CANT_OPEN_STREAM = -8
private const val ERROR_CONTENT_RESOLVER_NOT_FOUND = -9
- private const val KEY_RESUME_PACKAGES = "download_resume"
- private const val KEY_DOWNLOAD_INFO = "download_info"
+ const val KEY_RESUME_PACKAGES = "download_resume"
+ const val KEY_DOWNLOAD_INFO = "download_info"
+ const val KEY_RESUME_QUEUE_PACKAGES = "download_q_resume"
val downloadStatus = HashMap()
val downloadStatusEvent = Event>()
@@ -249,7 +258,7 @@ object VideoDownloadManager {
} else if (state == DownloadType.IsDone) {
"Download Done - $rowTwo"
} else {
- "Download Stopped - $rowTwo"
+ "Download Canceled - $rowTwo"
}
val bodyStyle = NotificationCompat.BigTextStyle()
@@ -263,7 +272,7 @@ object VideoDownloadManager {
} else if (state == DownloadType.IsDone) {
"Download Done - $rowTwo"
} else {
- "Download Stopped - $rowTwo"
+ "Download Canceled - $rowTwo"
}
builder.setContentText(txt)
@@ -312,7 +321,7 @@ object VideoDownloadManager {
}, when (i) {
DownloadActionType.Resume -> "Resume"
DownloadActionType.Pause -> "Pause"
- DownloadActionType.Stop -> "Stop"
+ DownloadActionType.Stop -> "Cancel"
}, pending
)
)
@@ -628,6 +637,9 @@ object VideoDownloadManager {
downloadEvent.invoke(Pair(id, DownloadActionType.Resume))
return
}
+
+ val dQueue = downloadQueue.toList().mapIndexed { index, any -> DownloadQueueResumePackage(index, any) }
+ context.setKey(KEY_RESUME_QUEUE_PACKAGES, dQueue)
currentDownloads.add(id)
main {
@@ -722,6 +734,16 @@ object VideoDownloadManager {
downloadCheck(context)
}
+ fun isMyServiceRunning(context: Context, serviceClass: Class<*>): Boolean {
+ val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager?
+ for (service in manager!!.getRunningServices(Int.MAX_VALUE)) {
+ if (serviceClass.name == service.service.className) {
+ return true
+ }
+ }
+ return false
+ }
+
fun downloadEpisode(
context: Context,
source: String?,