fixed download cancelling and title and author not renaming

This commit is contained in:
Denis Çerri 2023-01-31 19:02:16 +01:00
parent c653edb387
commit 144e8e9bc5
No known key found for this signature in database
GPG key ID: 95C43D517D830350
11 changed files with 159 additions and 113 deletions

View file

@ -2,7 +2,7 @@
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 1, "version": 1,
"identityHash": "d658de0453c49534c5971583f41854db", "identityHash": "e53569dbe0c02d62eda598075d73d5b1",
"entities": [ "entities": [
{ {
"tableName": "results", "tableName": "results",
@ -160,7 +160,7 @@
}, },
{ {
"tableName": "downloads", "tableName": "downloads",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `thumb` TEXT NOT NULL, `duration` TEXT NOT NULL, `type` TEXT NOT NULL, `format` TEXT NOT NULL, `removeAudio` INTEGER NOT NULL DEFAULT 0, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `downloadSize` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `embedSubs` INTEGER NOT NULL, `addChapters` INTEGER NOT NULL, `SaveThumb` INTEGER NOT NULL, `status` TEXT NOT NULL DEFAULT 'Queued', `workID` INTEGER NOT NULL)", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `thumb` TEXT NOT NULL, `duration` TEXT NOT NULL, `type` TEXT NOT NULL, `format` TEXT NOT NULL, `removeAudio` INTEGER NOT NULL DEFAULT 0, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `downloadSize` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `embedSubs` INTEGER NOT NULL, `addChapters` INTEGER NOT NULL, `SaveThumb` INTEGER NOT NULL, `status` TEXT NOT NULL DEFAULT 'Queued')",
"fields": [ "fields": [
{ {
"fieldPath": "id", "fieldPath": "id",
@ -265,12 +265,6 @@
"affinity": "TEXT", "affinity": "TEXT",
"notNull": true, "notNull": true,
"defaultValue": "'Queued'" "defaultValue": "'Queued'"
},
{
"fieldPath": "workID",
"columnName": "workID",
"affinity": "INTEGER",
"notNull": true
} }
], ],
"primaryKey": { "primaryKey": {
@ -318,7 +312,7 @@
"views": [], "views": [],
"setupQueries": [ "setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd658de0453c49534c5971583f41854db')" "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'e53569dbe0c02d62eda598075d73d5b1')"
] ]
} }
} }

View file

@ -3,8 +3,6 @@ package com.deniscerri.ytdlnis.database.dao
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.room.* import androidx.room.*
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.HistoryItem
import com.deniscerri.ytdlnis.util.FileUtil
@Dao @Dao
interface DownloadDao { interface DownloadDao {
@ -21,9 +19,6 @@ interface DownloadDao {
@Query("SELECT * FROM downloads WHERE status='Processing'") @Query("SELECT * FROM downloads WHERE status='Processing'")
fun getProcessingDownloads() : LiveData<List<DownloadItem>> fun getProcessingDownloads() : LiveData<List<DownloadItem>>
@Query("SELECT * FROM downloads WHERE workID=:workID")
fun getDownloadByWorkId(workID: Long) : DownloadItem
@Query("SELECT * FROM downloads WHERE id=:id LIMIT 1") @Query("SELECT * FROM downloads WHERE id=:id LIMIT 1")
fun getDownloadById(id: Long) : DownloadItem fun getDownloadById(id: Long) : DownloadItem
@ -50,4 +45,8 @@ interface DownloadDao {
@Query("UPDATE downloads SET status='Queued' WHERE status='Processing'") @Query("UPDATE downloads SET status='Queued' WHERE status='Processing'")
suspend fun queueAllProcessing() suspend fun queueAllProcessing()
@Query("SELECT * FROM downloads WHERE url=:url AND (status='Error' OR status='Cancelled') LIMIT 1")
fun checkIfErrorOrCancelled(url: String) : DownloadItem
} }

View file

@ -25,6 +25,5 @@ data class DownloadItem(
val addChapters: Boolean, val addChapters: Boolean,
val SaveThumb: Boolean, val SaveThumb: Boolean,
@ColumnInfo(defaultValue = "Queued") @ColumnInfo(defaultValue = "Queued")
var status: String, var status: String
var workID: Long
) )

View file

@ -1,9 +1,9 @@
package com.deniscerri.ytdlnis.database.repository package com.deniscerri.ytdlnis.database.repository
import android.util.Log
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import com.deniscerri.ytdlnis.database.dao.DownloadDao import com.deniscerri.ytdlnis.database.dao.DownloadDao
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.ResultItem
class DownloadRepository(private val downloadDao: DownloadDao) { class DownloadRepository(private val downloadDao: DownloadDao) {
val allDownloads : LiveData<List<DownloadItem>> = downloadDao.getAllDownloads() val allDownloads : LiveData<List<DownloadItem>> = downloadDao.getAllDownloads()
@ -11,8 +11,8 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
val queuedDownloads : LiveData<List<DownloadItem>> = downloadDao.getQueuedDownloads() val queuedDownloads : LiveData<List<DownloadItem>> = downloadDao.getQueuedDownloads()
val processingDownloads : LiveData<List<DownloadItem>> = downloadDao.getProcessingDownloads() val processingDownloads : LiveData<List<DownloadItem>> = downloadDao.getProcessingDownloads()
enum class status { enum class Status {
Active, Queued, Errored, Processing Active, Queued, Error, Processing, Cancelled
} }
suspend fun insert(item: DownloadItem) : Long { suspend fun insert(item: DownloadItem) : Long {
@ -27,12 +27,8 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
downloadDao.update(item) downloadDao.update(item)
} }
fun getDownloadByWorkID(workID: Long) : DownloadItem{
return downloadDao.getDownloadByWorkId(workID)
}
suspend fun setDownloadStatus(item: DownloadItem, status: Status){
suspend fun setDownloadStatus(item: DownloadItem, status: status){
item.status = status.toString() item.status = status.toString()
update(item); update(item);
} }
@ -52,4 +48,8 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
suspend fun queueAllProcessing(){ suspend fun queueAllProcessing(){
downloadDao.queueAllProcessing() downloadDao.queueAllProcessing()
} }
fun checkIfPresent(item: ResultItem): DownloadItem{
return downloadDao.checkIfErrorOrCancelled(item.url)
}
} }

View file

@ -3,10 +3,15 @@ package com.deniscerri.ytdlnis.database.viewmodel
import android.app.Activity import android.app.Activity
import android.app.Application import android.app.Application
import android.content.SharedPreferences import android.content.SharedPreferences
import android.util.Log
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.deniscerri.ytdlnis.App import com.deniscerri.ytdlnis.App
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdlnis.database.DBManager
@ -14,6 +19,7 @@ import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.Format import com.deniscerri.ytdlnis.database.models.Format
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdlnis.database.models.ResultItem
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdlnis.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.work.DownloadWorker
import com.google.gson.Gson import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -90,8 +96,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
resultItem.duration, resultItem.duration,
type, type,
getFormat(resultItem, type), false, getFormat(resultItem, type), false,
"", resultItem.website, "", resultItem.playlistTitle, embedSubs, addChapters, saveThumb, DownloadRepository.status.Processing.toString(), "", resultItem.website, "", resultItem.playlistTitle, embedSubs, addChapters, saveThumb, DownloadRepository.Status.Processing.toString()
0
) )
} }
@ -126,14 +131,23 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
return list return list
} }
fun putDownloadsForProcessing(items: List<ResultItem?>) : LiveData<List<Long>> { fun putDownloadsForProcessing(items: List<ResultItem?>, downloadItems: List<DownloadItem>) : LiveData<List<Long>> {
val result = MutableLiveData<List<Long>>() val result = MutableLiveData<List<Long>>()
viewModelScope.launch(Dispatchers.IO){ viewModelScope.launch(Dispatchers.IO){
val list : MutableList<Long> = mutableListOf() val list : MutableList<Long> = mutableListOf()
items.forEachIndexed { i, it -> items.forEachIndexed { i, it ->
val tmpDownloadItem = createDownloadItemFromResult(it!!, "video") val tmpDownloadItem = downloadItems[i]
val id = repository.insert(tmpDownloadItem) try {
list.add(id) val item = repository.checkIfPresent(it!!)
tmpDownloadItem.id = item.id
tmpDownloadItem.status = DownloadRepository.Status.Processing.toString()
repository.update(tmpDownloadItem)
list.add(tmpDownloadItem.id)
}catch (e: Exception){
val id = repository.insert(tmpDownloadItem)
list.add(id)
}
} }
result.postValue(list) result.postValue(list)
} }
@ -153,7 +167,22 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
return Gson().fromJson(string, DownloadItem::class.java) return Gson().fromJson(string, DownloadItem::class.java)
} }
fun queueAllProcessing()= viewModelScope.launch(Dispatchers.IO) { fun queueDownloads(items: List<DownloadItem>)= viewModelScope.launch(Dispatchers.IO) {
repository.queueAllProcessing(); val context = getApplication<App>().applicationContext
items.forEach {
it.status = DownloadRepository.Status.Queued.toString()
repository.update(it)
val workRequest = OneTimeWorkRequestBuilder<DownloadWorker>()
.setInputData(Data.Builder().putLong("id", it.id).build())
.addTag("download")
.build()
WorkManager.getInstance(context).beginUniqueWork(
it.id.toString(),
ExistingWorkPolicy.KEEP,
workRequest
).enqueue()
}
} }
} }

View file

@ -1,14 +1,27 @@
package com.deniscerri.ytdlnis.receiver package com.deniscerri.ytdlnis.receiver
import android.content.* import android.content.*
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.work.WorkManager import androidx.work.WorkManager
import com.deniscerri.ytdlnis.database.DBManager
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.util.NotificationUtil
import com.yausername.youtubedl_android.YoutubeDL
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
class CancelDownloadNotificationReceiver : BroadcastReceiver() { class CancelDownloadNotificationReceiver : BroadcastReceiver() {
override fun onReceive(c: Context, intent: Intent) { override fun onReceive(c: Context, intent: Intent) {
val message = intent.getStringExtra("cancel") val message = intent.getStringExtra("cancel")
val id = intent.getIntExtra("workID", 0) val id = intent.getIntExtra("workID", 0)
if (message != null) { if (message != null) {
WorkManager.getInstance(c).cancelAllWorkByTag(id.toString()) val notificationUtil = NotificationUtil(c)
YoutubeDL.getInstance().destroyProcessById(id.toString());
WorkManager.getInstance(c).cancelUniqueWork(id.toString())
notificationUtil.cancelDownloadNotification(id)
} }
} }
} }

View file

@ -20,6 +20,7 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.work.WorkManager
import com.deniscerri.ytdlnis.MainActivity import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.adapter.HomeAdapter import com.deniscerri.ytdlnis.adapter.HomeAdapter
@ -72,6 +73,8 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
private var sharedPreferences: SharedPreferences? = null private var sharedPreferences: SharedPreferences? = null
private var _binding : FragmentHomeBinding? = null private var _binding : FragmentHomeBinding? = null
private var workManager: WorkManager? = null
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
@ -188,6 +191,14 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
} else { } else {
resultViewModel.checkTrending() resultViewModel.checkTrending()
} }
WorkManager.getInstance(requireContext())
.getWorkInfosByTagLiveData("download")
.observe(viewLifecycleOwner){ list ->
list.forEach {
//Toast.makeText(context, """${it.progress.getInt("progress", 0)} ${it.progress.getString("output")}""", Toast.LENGTH_SHORT).show()
}
}
} }
private fun initMenu() { private fun initMenu() {
@ -341,8 +352,8 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
private fun showSingleDownloadSheet(resultItem : ResultItem, type: String){ private fun showSingleDownloadSheet(resultItem : ResultItem, type: String){
val downloadItem = downloadViewModel.createDownloadItemFromResult(resultItem, type) val downloadItem = downloadViewModel.createDownloadItemFromResult(resultItem, type)
downloadViewModel.insertDownload(downloadItem).observe(viewLifecycleOwner) { downloadViewModel.putDownloadsForProcessing(listOf(resultItem), listOf(downloadItem)).observe(viewLifecycleOwner) {
downloadItem.id = it downloadItem.id = it[0]
val bottomSheet = DownloadBottomSheetDialog(downloadItem) val bottomSheet = DownloadBottomSheetDialog(downloadItem)
bottomSheet.show(parentFragmentManager, "downloadSingleSheet") bottomSheet.show(parentFragmentManager, "downloadSingleSheet")
} }
@ -395,7 +406,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
if (viewIdName.isNotEmpty()) { if (viewIdName.isNotEmpty()) {
if (viewIdName == "downloadSelected") { if (viewIdName == "downloadSelected") {
val downloadList = downloadViewModel.turnResultItemstoDownloadItems(selectedObjects!!) val downloadList = downloadViewModel.turnResultItemstoDownloadItems(selectedObjects!!)
downloadViewModel.putDownloadsForProcessing(selectedObjects!!).observe(viewLifecycleOwner) { downloadViewModel.putDownloadsForProcessing(selectedObjects!!, downloadList).observe(viewLifecycleOwner) {
it.forEachIndexed { i, itemID -> it.forEachIndexed { i, itemID ->
downloadList[i].id = itemID downloadList[i].id = itemID
} }
@ -405,7 +416,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
} }
if (viewIdName == "downloadAll") { if (viewIdName == "downloadAll") {
val downloadList = downloadViewModel.turnResultItemstoDownloadItems(resultsList!!) val downloadList = downloadViewModel.turnResultItemstoDownloadItems(resultsList!!)
downloadViewModel.putDownloadsForProcessing(resultsList!!).observe(viewLifecycleOwner) { downloadViewModel.putDownloadsForProcessing(resultsList!!, downloadList).observe(viewLifecycleOwner) {
it.forEachIndexed { i, itemID -> it.forEachIndexed { i, itemID ->
downloadList[i].id = itemID downloadList[i].id = itemID
} }

View file

@ -104,20 +104,7 @@ class DownloadBottomSheetDialog(item: DownloadItem) : BottomSheetDialogFragment(
val download = view.findViewById<Button>(R.id.bottomsheet_download_button) val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
download!!.setOnClickListener { download!!.setOnClickListener {
downloadItem.status = DownloadRepository.status.Queued.toString() downloadViewModel.queueDownloads(listOf(downloadItem))
val workID = SystemClock.uptimeMillis()
downloadItem.workID = workID
downloadViewModel.insertDownload(downloadItem)
val workRequest = OneTimeWorkRequestBuilder<DownloadWorker>()
.setInputData(Data.Builder().putLong("workID", workID).build())
.build()
WorkManager.getInstance(requireContext()).beginUniqueWork(
downloadItem.id.toString(),
ExistingWorkPolicy.KEEP,
workRequest
).enqueue()
dismiss() dismiss()
} }
} }

View file

@ -81,23 +81,7 @@ class DownloadMultipleBottomSheetDialog(private val items: List<DownloadItem>) :
val download = view.findViewById<Button>(R.id.bottomsheet_download_button) val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
download!!.setOnClickListener { download!!.setOnClickListener {
downloadViewModel.queueAllProcessing() downloadViewModel.queueDownloads(items)
// for (i in selectedObjects!!.indices) {
// val vid = findVideo(
// selectedObjects!![i]!!.getURL()
// )
// vid!!.downloadedType = type
// updateDownloadingStatusOnResult(vid, type, true)
// homeAdapter!!.notifyItemChanged(resultsList!!.indexOf(vid))
// downloadQueue!!.add(vid)
// }
// selectedObjects = ArrayList()
// homeAdapter!!.clearCheckedVideos()
// downloadFabs!!.visibility = View.GONE
// if (isStoragePermissionGranted) {
// mainActivity!!.startDownloadService(downloadQueue, listener)
// downloadQueue!!.clear()
// }
dismiss() dismiss()
} }
} }

View file

@ -79,6 +79,7 @@ class FileUtil() {
return context.getString(R.string.unfound_file); return context.getString(R.string.unfound_file);
} }
@Throws(Exception::class)
fun moveFile(originDir: File, context: Context, destDir: String, progress: (p: Int) -> Unit) : String { fun moveFile(originDir: File, context: Context, destDir: String, progress: (p: Int) -> Unit) : String {
originDir.listFiles()?.forEach { originDir.listFiles()?.forEach {
if (it.name.equals("rList")){ if (it.name.equals("rList")){
@ -88,7 +89,7 @@ class FileUtil() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
val f = File(formatPath(destDir)+"/"+it.name) val f = File(formatPath(destDir)+"/"+it.name)
if (!f.exists()) f.mkdir() f.mkdirs()
Files.move(it.toPath(), f.toPath(), StandardCopyOption.REPLACE_EXISTING) Files.move(it.toPath(), f.toPath(), StandardCopyOption.REPLACE_EXISTING)
progress(100) progress(100)
}else{ }else{

View file

@ -4,20 +4,18 @@ import android.app.PendingIntent
import android.app.Service import android.app.Service
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.os.Handler
import android.os.Looper import android.os.Looper
import android.os.SystemClock
import android.provider.DocumentsContract
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
import androidx.work.ForegroundInfo import androidx.work.ForegroundInfo
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import androidx.work.workDataOf import androidx.work.workDataOf
import com.deniscerri.ytdlnis.BuildConfig
import com.deniscerri.ytdlnis.MainActivity import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdlnis.database.DBManager
import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.HistoryItem import com.deniscerri.ytdlnis.database.models.HistoryItem
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdlnis.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdlnis.util.FileUtil
@ -27,7 +25,6 @@ import com.yausername.youtubedl_android.YoutubeDLRequest
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import java.io.File import java.io.File
import java.util.regex.Pattern import java.util.regex.Pattern
import kotlin.math.abs
class DownloadWorker( class DownloadWorker(
@ -35,22 +32,35 @@ class DownloadWorker(
workerParams: WorkerParameters workerParams: WorkerParameters
) : Worker(context, workerParams) { ) : Worker(context, workerParams) {
override fun doWork(): Result { override fun doWork(): Result {
workID = inputData.getLong("workID", SystemClock.uptimeMillis()) itemId = inputData.getLong("id", 0)
if (itemId == 0L) return Result.failure()
val notificationUtil = NotificationUtil(context) val notificationUtil = NotificationUtil(context)
val dbManager = DBManager.getInstance(context) val dbManager = DBManager.getInstance(context)
val dao = dbManager.downloadDao val dao = dbManager.downloadDao
val repository = DownloadRepository(dao) val repository = DownloadRepository(dao)
val commandTemplateDao = dbManager.commandTemplateDao val commandTemplateDao = dbManager.commandTemplateDao
val historyDao = dbManager.historyDao val historyDao = dbManager.historyDao
val handler = Handler(Looper.getMainLooper())
val downloadItem: DownloadItem?
try {
downloadItem = repository.getItemByID(itemId)
}catch (e: Exception){
e.printStackTrace()
return Result.failure()
}
Log.e(TAG, downloadItem.toString())
val downloadItem = repository.getDownloadByWorkID(workID)
runBlocking{ runBlocking{
repository.setDownloadStatus(downloadItem, DownloadRepository.status.Active) repository.setDownloadStatus(downloadItem, DownloadRepository.Status.Active)
} }
val intent = Intent(context, MainActivity::class.java) val intent = Intent(context, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE) val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val notification = notificationUtil.createDownloadServiceNotification(pendingIntent, downloadItem.title, workID.toInt(), NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID) val notification = notificationUtil.createDownloadServiceNotification(pendingIntent, downloadItem.title, downloadItem.id.toInt(), NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID)
val foregroundInfo = ForegroundInfo(workID.toInt(), notification) val foregroundInfo = ForegroundInfo(downloadItem.id.toInt(), notification)
setForegroundAsync(foregroundInfo) setForegroundAsync(foregroundInfo)
@ -61,7 +71,7 @@ class DownloadWorker(
val tempFolder = StringBuilder(context.cacheDir.absolutePath + """/${downloadItem.title}##${downloadItem.type}""") val tempFolder = StringBuilder(context.cacheDir.absolutePath + """/${downloadItem.title}##${downloadItem.type}""")
tempFolder.append("##${downloadItem.format.format_id}") tempFolder.append("##${downloadItem.format.format_id}")
var tempFileDir = File(tempFolder.toString()) val tempFileDir = File(tempFolder.toString())
tempFileDir.delete() tempFileDir.delete()
tempFileDir.mkdir() tempFileDir.mkdir()
@ -90,6 +100,9 @@ class DownloadWorker(
request.addOption("--sponsorblock-remove", filters) request.addOption("--sponsorblock-remove", filters)
} }
request.addCommands(listOf("--replace-in-metadata","title",".*.",downloadItem.title));
request.addCommands(listOf("--replace-in-metadata","uploader",".*.",downloadItem.author));
when(type){ when(type){
"audio" -> { "audio" -> {
request.addOption("-x") request.addOption("-x")
@ -171,24 +184,32 @@ class DownloadWorker(
runCatching { runCatching {
YoutubeDL.getInstance().execute(request, downloadItem.id.toString()){ progress, _, line -> YoutubeDL.getInstance().execute(request, downloadItem.id.toString()){ progress, _, line ->
setProgressAsync(workDataOf("progress" to progress.toInt())) setProgressAsync(workDataOf("progress" to progress.toInt()))
setProgressAsync(workDataOf("output" to line))
val title: String = downloadItem.title val title: String = downloadItem.title
notificationUtil.updateDownloadNotification( notificationUtil.updateDownloadNotification(
downloadItem.workID.toInt(), downloadItem.id.toInt(),
line, progress.toInt(), 0, title, line, progress.toInt(), 0, title,
NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID
) )
} }
}.onSuccess { }.onSuccess {
//move file from internal to set download directory //move file from internal to set download directory
var finalPath : String?
val finalPath = moveFile(tempFileDir.absoluteFile, downloadLocation){ progress -> try {
setProgressAsync(workDataOf("progress" to progress)) finalPath = moveFile(tempFileDir.absoluteFile, downloadLocation){ progress ->
setProgressAsync(workDataOf("progress" to progress))
}
}catch (e: Exception){
finalPath = context.getString(R.string.unfound_file)
handler.postDelayed({
Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
}, 1000)
} }
//put download in history //put download in history
val incognito = sharedPreferences.getBoolean("incognito", false) val incognito = sharedPreferences.getBoolean("incognito", false)
if (!incognito) { if (!incognito) {
val unixtime = System.currentTimeMillis() / 1000 val unixtime = System.currentTimeMillis() / 1000
val historyItem = HistoryItem(0, downloadItem.url, downloadItem.title, downloadItem.author, downloadItem.duration, downloadItem.thumb, downloadItem.type, unixtime, finalPath, downloadItem.website, downloadItem.format) val historyItem = HistoryItem(0, downloadItem.url, downloadItem.title, downloadItem.author, downloadItem.duration, downloadItem.thumb, downloadItem.type, unixtime, finalPath!!, downloadItem.website, downloadItem.format)
runBlocking { runBlocking {
historyDao.insert(historyItem) historyDao.insert(historyItem)
} }
@ -197,43 +218,51 @@ class DownloadWorker(
dao.delete(downloadItem.id) dao.delete(downloadItem.id)
} }
}.onFailure { }.onFailure {
tempFileDir.delete() if (it is YoutubeDL.CanceledException) {
Looper.prepare() downloadItem.status = DownloadRepository.Status.Cancelled.toString()
Toast.makeText(context, it.message, Toast.LENGTH_LONG).show() runBlocking {
Log.e(TAG, context.getString(R.string.failed_download), it) dao.update(downloadItem)
notificationUtil.updateDownloadNotification( }
downloadItem.workID.toInt(), return Result.failure()
context.getString(R.string.failed_download), 0, 0, downloadItem.title, }else{
NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID tempFileDir.delete()
) handler.postDelayed({
Toast.makeText(context, it.message, Toast.LENGTH_SHORT).show()
}, 1000)
downloadItem.status = DownloadRepository.status.Errored.toString() Log.e(TAG, context.getString(R.string.failed_download), it)
runBlocking { notificationUtil.updateDownloadNotification(
dao.update(downloadItem) downloadItem.id.toInt(),
context.getString(R.string.failed_download), 0, 0, downloadItem.title,
NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID
)
downloadItem.status = DownloadRepository.Status.Error.toString()
runBlocking {
dao.update(downloadItem)
}
return Result.failure()
} }
return Result.failure()
} }
return Result.success() return Result.success()
} }
private fun getDownloadLocation(type: String, context: Context): String? { // private fun getDownloadLocation(type: String, context: Context): String? {
val sharedPreferences = context.getSharedPreferences("root_preferences", // val sharedPreferences = context.getSharedPreferences("root_preferences",
Service.MODE_PRIVATE // Service.MODE_PRIVATE
) // )
val downloadsDir: String? = if (type == "audio") { // val downloadsDir: String? = if (type == "audio") {
sharedPreferences.getString("music_path", context.getString(R.string.music_path)) // sharedPreferences.getString("music_path", context.getString(R.string.music_path))
} else { // } else {
sharedPreferences.getString("video_path", context.getString(R.string.video_path)) // sharedPreferences.getString("video_path", context.getString(R.string.video_path))
} // }
return downloadsDir // return downloadsDir
} // }
@Throws(Exception::class)
private fun moveFile(originDir: File, downLocation: String, progress: (progress: Int) -> Unit) : String{ private fun moveFile(originDir: File, downLocation: String, progress: (progress: Int) -> Unit) : String{
val destDir = Uri.parse(downLocation).run {
DocumentsContract.buildChildDocumentsUriUsingTree(this, DocumentsContract.getTreeDocumentId(this))
}
val fileUtil = FileUtil() val fileUtil = FileUtil()
val path = fileUtil.moveFile(originDir, context, downLocation){ p -> val path = fileUtil.moveFile(originDir, context, downLocation){ p ->
progress(p) progress(p)
@ -242,7 +271,7 @@ class DownloadWorker(
} }
companion object { companion object {
var workID: Long = 0 var itemId: Long = 0
const val TAG = "DownloadWorker" const val TAG = "DownloadWorker"
} }