download resume and stuff

This commit is contained in:
LagradOst 2021-07-08 19:46:47 +02:00
parent 3ef14b93fb
commit 576377e4bb
5 changed files with 136 additions and 24 deletions

View file

@ -33,6 +33,19 @@
</intent-filter> </intent-filter>
</activity> </activity>
<receiver
android:name=".recivers.VideoDownloadRestartReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="restart_service" />
</intent-filter>
</receiver>
<service
android:name=".services.VideoDownloadKeepAliveService"
android:enabled="true" >
</service>
<service <service
android:name=".services.VideoDownloadService" android:name=".services.VideoDownloadService"
android:enabled="true" android:enabled="true"

View file

@ -1,39 +1,28 @@
package com.lagradost.cloudstream3 package com.lagradost.cloudstream3
import android.Manifest
import android.app.PictureInPictureParams import android.app.PictureInPictureParams
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.documentfile.provider.DocumentFile
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.anggrayudi.storage.SimpleStorage import com.anggrayudi.storage.SimpleStorage
import com.anggrayudi.storage.callback.StorageAccessCallback
import com.anggrayudi.storage.file.StorageId import com.anggrayudi.storage.file.StorageId
import com.anggrayudi.storage.file.StorageType
import com.anggrayudi.storage.file.getStorageId
import com.google.android.gms.cast.ApplicationMetadata
import com.google.android.gms.cast.Cast
import com.google.android.gms.cast.LaunchOptions
import com.google.android.gms.cast.framework.CastButtonFactory import com.google.android.gms.cast.framework.CastButtonFactory
import com.google.android.gms.cast.framework.CastContext
import com.google.android.gms.cast.framework.CastSession
import com.google.android.gms.cast.framework.SessionManagerListener
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import com.karumi.dexter.Dexter
import com.karumi.dexter.MultiplePermissionsReport
import com.karumi.dexter.listener.multi.BaseMultiplePermissionsListener
import com.lagradost.cloudstream3.UIHelper.checkWrite import com.lagradost.cloudstream3.UIHelper.checkWrite
import com.lagradost.cloudstream3.UIHelper.hasPIPPermission import com.lagradost.cloudstream3.UIHelper.hasPIPPermission
import com.lagradost.cloudstream3.UIHelper.requestRW import com.lagradost.cloudstream3.UIHelper.requestRW
import com.lagradost.cloudstream3.UIHelper.shouldShowPIPMode import com.lagradost.cloudstream3.UIHelper.shouldShowPIPMode
import com.lagradost.cloudstream3.recivers.VideoDownloadRestartReceiver
import com.lagradost.cloudstream3.services.RESTART_ALL_DOWNLOADS_AND_QUEUE
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.utils.VideoDownloadManager
import kotlinx.android.synthetic.main.fragment_result.* import kotlinx.android.synthetic.main.fragment_result.*
@ -125,6 +114,14 @@ class MainActivity : AppCompatActivity() {
storage.onRestoreInstanceState(savedInstanceState) storage.onRestoreInstanceState(savedInstanceState)
} }
override fun onDestroy() {
val broadcastIntent = Intent()
broadcastIntent.action = "restart_service"
broadcastIntent.setClass(this, VideoDownloadRestartReceiver::class.java)
this.sendBroadcast(broadcastIntent)
super.onDestroy()
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
mainContext = this mainContext = this
@ -161,6 +158,12 @@ class MainActivity : AppCompatActivity() {
} }
CastButtonFactory.setUpMediaRouteButton(this, media_route_button) CastButtonFactory.setUpMediaRouteButton(this, media_route_button)
if (!VideoDownloadManager.isMyServiceRunning(this, VideoDownloadKeepAliveService::class.java)) {
val mYourService = VideoDownloadKeepAliveService()
val mServiceIntent = Intent(this, mYourService::class.java).putExtra(START_VALUE_KEY, RESTART_ALL_DOWNLOADS_AND_QUEUE)
this.startService(mServiceIntent)
}
/* /*
val castContext = CastContext.getSharedInstance(applicationContext) val castContext = CastContext.getSharedInstance(applicationContext)
fun buildMediaQueueItem(video: String): MediaQueueItem { fun buildMediaQueueItem(video: String): MediaQueueItem {

View file

@ -0,0 +1,23 @@
package com.lagradost.cloudstream3.recivers
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import com.lagradost.cloudstream3.services.RESTART_ALL_DOWNLOADS_AND_QUEUE
import com.lagradost.cloudstream3.services.START_VALUE_KEY
import com.lagradost.cloudstream3.services.VideoDownloadKeepAliveService
class VideoDownloadRestartReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Log.i("Broadcast Listened", "Service tried to stop")
if (Build.VERSION.SDK_INT >= 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))
}
}
}

View file

@ -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<VideoDownloadManager.DownloadResumePackage>(k) }
for (pkg in resumePkg) { // ADD ALL CURRENT DOWNLOADS
VideoDownloadManager.downloadFromResume(this, pkg)
}
// ADD QUEUE
val resumeQueue =
this.getKey<List<VideoDownloadManager.DownloadQueueResumePackage>>(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()
}
}

View file

@ -1,5 +1,6 @@
package com.lagradost.cloudstream3.utils package com.lagradost.cloudstream3.utils
import android.app.ActivityManager
import android.app.NotificationChannel import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
import android.app.PendingIntent import android.app.PendingIntent
@ -20,6 +21,9 @@ import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.UIHelper.colorFromAttribute import com.lagradost.cloudstream3.UIHelper.colorFromAttribute
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall 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.services.VideoDownloadService
import com.lagradost.cloudstream3.utils.Coroutines.main import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.cloudstream3.utils.DataStore.getKey import com.lagradost.cloudstream3.utils.DataStore.getKey
@ -33,8 +37,7 @@ import java.lang.Thread.sleep
import java.net.URL import java.net.URL
import java.net.URLConnection import java.net.URLConnection
import java.util.* import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
const val DOWNLOAD_CHANNEL_ID = "cloudstream3.general" const val DOWNLOAD_CHANNEL_ID = "cloudstream3.general"
const val DOWNLOAD_CHANNEL_NAME = "Downloads" const val DOWNLOAD_CHANNEL_NAME = "Downloads"
@ -119,6 +122,11 @@ object VideoDownloadManager {
val path: Uri, val path: Uri,
) )
data class DownloadQueueResumePackage(
val index: Int,
val pkg: DownloadResumePackage,
)
private const val SUCCESS_DOWNLOAD_DONE = 1 private const val SUCCESS_DOWNLOAD_DONE = 1
private const val SUCCESS_STOPPED = 2 private const val SUCCESS_STOPPED = 2
private const val ERROR_DELETING_FILE = -1 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_CANT_OPEN_STREAM = -8
private const val ERROR_CONTENT_RESOLVER_NOT_FOUND = -9 private const val ERROR_CONTENT_RESOLVER_NOT_FOUND = -9
private const val KEY_RESUME_PACKAGES = "download_resume" const val KEY_RESUME_PACKAGES = "download_resume"
private const val KEY_DOWNLOAD_INFO = "download_info" const val KEY_DOWNLOAD_INFO = "download_info"
const val KEY_RESUME_QUEUE_PACKAGES = "download_q_resume"
val downloadStatus = HashMap<Int, DownloadType>() val downloadStatus = HashMap<Int, DownloadType>()
val downloadStatusEvent = Event<Pair<Int, DownloadType>>() val downloadStatusEvent = Event<Pair<Int, DownloadType>>()
@ -249,7 +258,7 @@ object VideoDownloadManager {
} else if (state == DownloadType.IsDone) { } else if (state == DownloadType.IsDone) {
"Download Done - $rowTwo" "Download Done - $rowTwo"
} else { } else {
"Download Stopped - $rowTwo" "Download Canceled - $rowTwo"
} }
val bodyStyle = NotificationCompat.BigTextStyle() val bodyStyle = NotificationCompat.BigTextStyle()
@ -263,7 +272,7 @@ object VideoDownloadManager {
} else if (state == DownloadType.IsDone) { } else if (state == DownloadType.IsDone) {
"Download Done - $rowTwo" "Download Done - $rowTwo"
} else { } else {
"Download Stopped - $rowTwo" "Download Canceled - $rowTwo"
} }
builder.setContentText(txt) builder.setContentText(txt)
@ -312,7 +321,7 @@ object VideoDownloadManager {
}, when (i) { }, when (i) {
DownloadActionType.Resume -> "Resume" DownloadActionType.Resume -> "Resume"
DownloadActionType.Pause -> "Pause" DownloadActionType.Pause -> "Pause"
DownloadActionType.Stop -> "Stop" DownloadActionType.Stop -> "Cancel"
}, pending }, pending
) )
) )
@ -628,6 +637,9 @@ object VideoDownloadManager {
downloadEvent.invoke(Pair(id, DownloadActionType.Resume)) downloadEvent.invoke(Pair(id, DownloadActionType.Resume))
return return
} }
val dQueue = downloadQueue.toList().mapIndexed { index, any -> DownloadQueueResumePackage(index, any) }
context.setKey(KEY_RESUME_QUEUE_PACKAGES, dQueue)
currentDownloads.add(id) currentDownloads.add(id)
main { main {
@ -722,6 +734,16 @@ object VideoDownloadManager {
downloadCheck(context) 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( fun downloadEpisode(
context: Context, context: Context,
source: String?, source: String?,