ytdlnis/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt
deniscerri b1b5dbc608
alot of stuff
-added download now option when u highlight only scheduled items in the context menu

-tappin on the errored notification will send you to errored tab, if you have logs disabled. If logs on it will send u to the log

-added preferred format ordering. By ID, FILESIZE, CONTAINER. Formats grouped by container will also be sorted by filesize

-fixed app not showing formats when u try to modify a current download item and its a different type (audio formats not showing if its a video type and vice versa)

-fixed app showing generic formats in cases where the format length was the same as that of generic formats (silly mistake)

-made the app store static strings for 'best' and 'worst' so that there isnt any confusion when u try to change the language and the stored downloads will have the other language's string

-added collected filesize on top of the download queue

-potentially fixed app not crashing when going to queued screen? idk

-fixed app not moving files when its a fresh install and u havent tried to change the download path. Now the app will just straight up download in that path if it finds that it can write in it. If not, it will use the old method of moving through URI's

-added download retries options
--retries and --fragment-retries
2023-06-25 22:07:08 +02:00

354 lines
No EOL
15 KiB
Kotlin

package com.deniscerri.ytdlnis.util
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.TaskStackBuilder
import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.os.Build
import android.os.Bundle
import androidx.core.app.NotificationCompat
import androidx.core.content.FileProvider
import androidx.navigation.NavDeepLinkBuilder
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.receiver.CancelDownloadNotificationReceiver
import com.deniscerri.ytdlnis.receiver.PauseDownloadNotificationReceiver
import com.deniscerri.ytdlnis.receiver.ResumeActivity
import com.deniscerri.ytdlnis.receiver.ShareFileActivity
import java.io.File
class NotificationUtil(var context: Context) {
private val downloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_SERVICE_CHANNEL_ID)
private val commandDownloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID)
private val finishedDownloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_FINISHED_CHANNEL_ID)
private val notificationManager: NotificationManager = context.getSystemService(NotificationManager::class.java)
fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = context.getSystemService(
NotificationManager::class.java
)
//gui downloads
var name: CharSequence = context.getString(R.string.download_notification_channel_name)
var description = context.getString(R.string.download_notification_channel_description)
val importance = NotificationManager.IMPORTANCE_LOW
var channel = NotificationChannel(DOWNLOAD_SERVICE_CHANNEL_ID, name, importance)
channel.description = description
notificationManager.createNotificationChannel(channel)
//command downloads
name = context.getString(R.string.command_download_notification_channel_name)
description =
context.getString(R.string.command_download_notification_channel_description)
channel = NotificationChannel(COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID, name, importance)
channel.description = description
notificationManager.createNotificationChannel(channel)
//finished or errored downloads
name = context.getString(R.string.finished_download_notification_channel_name)
description =
context.getString(R.string.finished_download_notification_channel_description)
channel = NotificationChannel(DOWNLOAD_FINISHED_CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH)
channel.description = description
notificationManager.createNotificationChannel(channel)
//misc
name = context.getString(R.string.misc)
description = ""
channel = NotificationChannel(DOWNLOAD_MISC_CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH)
channel.description = description
notificationManager.createNotificationChannel(channel)
}
}
private fun getBuilder(channel: String) : NotificationCompat.Builder {
when(channel) {
DOWNLOAD_SERVICE_CHANNEL_ID -> { return downloadNotificationBuilder}
COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID -> { return commandDownloadNotificationBuilder }
DOWNLOAD_FINISHED_CHANNEL_ID -> { return finishedDownloadNotificationBuilder }
}
return downloadNotificationBuilder
}
fun createDownloadServiceNotification(
pendingIntent: PendingIntent?,
title: String?,
workID: Int,
channel: String
): Notification {
val notificationBuilder = getBuilder(channel)
val pauseIntent = Intent(context, PauseDownloadNotificationReceiver::class.java)
pauseIntent.putExtra("workID", workID)
pauseIntent.putExtra("title", title)
val pauseNotificationPendingIntent = PendingIntent.getBroadcast(
context,
workID,
pauseIntent,
PendingIntent.FLAG_IMMUTABLE
)
val cancelIntent = Intent(context, CancelDownloadNotificationReceiver::class.java)
cancelIntent.putExtra("cancel", "")
cancelIntent.putExtra("workID", workID)
val cancelNotificationPendingIntent = PendingIntent.getBroadcast(
context,
workID,
cancelIntent,
PendingIntent.FLAG_IMMUTABLE
)
return notificationBuilder
.setContentTitle(title)
.setOngoing(true)
.setCategory(Notification.CATEGORY_PROGRESS)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setLargeIcon(
BitmapFactory.decodeResource(
context.resources,
android.R.drawable.stat_sys_download
)
)
.setContentText("")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setProgress(PROGRESS_MAX, PROGRESS_CURR, false)
.setContentIntent(pendingIntent)
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
.clearActions()
.addAction(0, context.getString(R.string.pause), pauseNotificationPendingIntent)
.addAction(0, context.getString(R.string.cancel), cancelNotificationPendingIntent)
.build()
}
fun createResumeDownload(workID: Int, title: String?, channel: String){
val notificationBuilder = getBuilder(channel)
notificationBuilder
.setContentTitle(title)
.setSmallIcon(R.drawable.ic_launcher_foreground_large)
.setLargeIcon(
BitmapFactory.decodeResource(
context.resources,
R.drawable.ic_launcher_foreground_large
)
)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.clearActions()
val intent = Intent(context, ResumeActivity::class.java)
intent.putExtra("workID", workID)
val resumeNotificationPendingIntent = PendingIntent.getActivity(
context,
workID,
intent,
PendingIntent.FLAG_IMMUTABLE
)
notificationBuilder.addAction(0, context.getString(R.string.resume), resumeNotificationPendingIntent)
notificationManager.notify(DOWNLOAD_RESUME_NOTIFICATION_ID, notificationBuilder.build())
}
fun createUpdatingItemNotification(channel: String){
val notificationBuilder = getBuilder(channel)
notificationBuilder
.setContentTitle(context.getString(R.string.updating_download_data))
.setSmallIcon(android.R.drawable.stat_sys_download)
.setLargeIcon(
BitmapFactory.decodeResource(
context.resources,
android.R.drawable.stat_sys_download
)
)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.clearActions()
notificationManager.notify(DOWNLOAD_UPDATING_NOTIFICATION_ID, notificationBuilder.build())
}
fun createDownloadFinished(title: String?,
filepath: List<String>?,
channel: String
) {
val notificationBuilder = getBuilder(channel)
notificationBuilder
.setContentTitle("${context.getString(R.string.downloaded)} $title")
.setSmallIcon(R.drawable.ic_launcher_foreground_large)
.setLargeIcon(
BitmapFactory.decodeResource(
context.resources,
R.drawable.ic_launcher_foreground_large
)
)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.clearActions()
if (filepath != null){
try{
val file = File(filepath.first())
val uri = FileProvider.getUriForFile(
context,
"com.deniscerri.ytdl.fileprovider",
file
)
//open intent
val intent = Intent()
intent.action = Intent.ACTION_VIEW
intent.setDataAndType(uri, "*/*")
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
val openNotificationPendingIntent: PendingIntent = TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(intent)
getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
//share intent
val shareIntent = Intent(context, ShareFileActivity::class.java)
shareIntent.putExtra("path", filepath.toTypedArray())
shareIntent.putExtra("notificationID", DOWNLOAD_FINISHED_NOTIFICATION_ID)
val shareNotificationPendingIntent: PendingIntent = PendingIntent.getActivity(
context,
0,
shareIntent,
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
notificationBuilder.addAction(0, context.getString(R.string.Open_File), openNotificationPendingIntent)
notificationBuilder.addAction(0, context.getString(R.string.share), shareNotificationPendingIntent)
}catch (_: Exception){}
}
notificationManager.notify(DOWNLOAD_FINISHED_NOTIFICATION_ID, notificationBuilder.build())
}
fun createDownloadErrored(title: String?,
error: String?,
logFile: File?,
channel: String
) {
val notificationBuilder = getBuilder(channel)
val bundle = Bundle()
bundle.putString("logpath", logFile?.absolutePath)
val errorPendingIntent = NavDeepLinkBuilder(context)
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.downloadLogFragment)
.setArguments(bundle)
.createPendingIntent()
val tabBundle = Bundle()
tabBundle.putString("tab", "error")
val errorTabPendingIntent = NavDeepLinkBuilder(context)
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.downloadQueueMainFragment)
.setArguments(tabBundle)
.createPendingIntent()
notificationBuilder
.setContentTitle("${context.getString(R.string.failed_download)}: $title")
.setContentText(error)
.setSmallIcon(R.drawable.ic_launcher_foreground_large)
.setLargeIcon(
BitmapFactory.decodeResource(
context.resources,
R.drawable.ic_launcher_foreground_large
)
)
.setContentIntent(errorTabPendingIntent)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.clearActions()
if (logFile != null){
notificationBuilder.setContentIntent(errorPendingIntent)
notificationBuilder.addAction(0, context.getString(R.string.logs), errorPendingIntent)
}
notificationManager.notify(DOWNLOAD_FINISHED_NOTIFICATION_ID, notificationBuilder.build())
}
fun updateDownloadNotification(
id: Int,
desc: String,
progress: Int,
queue: Int,
title: String?,
channel : String
) {
val notificationBuilder = getBuilder(channel)
var contentText = ""
if (queue > 1) contentText += """${queue - 1} ${context.getString(R.string.items_left)}""" + "\n"
contentText += desc.replace("\\[.*?\\] ".toRegex(), "")
try {
notificationBuilder.setProgress(100, progress, false)
.setContentTitle(title)
.setStyle(NotificationCompat.BigTextStyle().bigText(contentText))
notificationManager.notify(id, notificationBuilder.build())
} catch (e: Exception) {
e.printStackTrace()
}
}
fun cancelDownloadNotification(id: Int) {
notificationManager.cancel(id)
}
fun createMoveCacheFilesNotification(pendingIntent: PendingIntent?, downloadMiscChannelId: String): Notification {
val notificationBuilder = getBuilder(downloadMiscChannelId)
return notificationBuilder
.setContentTitle(context.getString(R.string.move_temporary_files))
.setOngoing(true)
.setCategory(Notification.CATEGORY_PROGRESS)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setLargeIcon(
BitmapFactory.decodeResource(
context.resources,
android.R.drawable.stat_sys_download
)
)
.setContentText("")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setProgress(PROGRESS_MAX, PROGRESS_CURR, false)
.setContentIntent(pendingIntent)
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
.clearActions()
.build()
}
fun updateCacheMovingNotification(id: Int, progress: Int, totalFiles: Int) {
val notificationBuilder = getBuilder(DOWNLOAD_MISC_CHANNEL_ID)
val contentText = "${progress}/${totalFiles}"
try {
notificationBuilder.setProgress(100, progress, false)
.setContentTitle(context.getString(R.string.move_temporary_files))
.setStyle(NotificationCompat.BigTextStyle().bigText(contentText))
notificationManager.notify(id, notificationBuilder.build())
} catch (e: Exception) {
e.printStackTrace()
}
}
companion object {
const val DOWNLOAD_SERVICE_CHANNEL_ID = "1"
const val COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID = "2"
const val DOWNLOAD_FINISHED_CHANNEL_ID = "3"
const val DOWNLOAD_FINISHED_NOTIFICATION_ID = 3
const val DOWNLOAD_RESUME_NOTIFICATION_ID = 4
const val DOWNLOAD_UPDATING_NOTIFICATION_ID = 5
const val DOWNLOAD_MISC_CHANNEL_ID = "4"
const val DOWNLOAD_MISC_NOTIFICATION_ID = 4
private const val PROGRESS_MAX = 100
private const val PROGRESS_CURR = 0
}
}