From 91e2110beb30c569ae04fc43cec1eab48db62b68 Mon Sep 17 00:00:00 2001 From: Ankit Suda Date: Sun, 10 Nov 2024 13:56:22 +0530 Subject: [PATCH] Add custom notification title for android --- README.md | 1 + .../vn/hunghd/flutterdownloader/DownloadTask.kt | 1 + .../hunghd/flutterdownloader/DownloadWorker.kt | 17 ++++++++++------- .../FlutterDownloaderPlugin.kt | 8 +++++++- .../vn/hunghd/flutterdownloader/TaskDao.kt | 5 +++++ .../vn/hunghd/flutterdownloader/TaskDbHelper.kt | 11 ++++++++++- .../vn/hunghd/flutterdownloader/TaskEntry.kt | 1 + lib/src/downloader.dart | 5 +++++ 8 files changed, 40 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index fd0097a2..1bcbb04f 100644 --- a/README.md +++ b/README.md @@ -385,6 +385,7 @@ CREATE TABLE `task` ( `saved_dir` TEXT, `resumable` TINYINT DEFAULT 0, `headers` TEXT, + `notification_title` TEXT, `show_notification` TINYINT DEFAULT 0, `open_file_from_notification` TINYINT DEFAULT 0, `time_created` INTEGER DEFAULT 0 diff --git a/android/src/main/kotlin/vn/hunghd/flutterdownloader/DownloadTask.kt b/android/src/main/kotlin/vn/hunghd/flutterdownloader/DownloadTask.kt index b07ac219..84420527 100644 --- a/android/src/main/kotlin/vn/hunghd/flutterdownloader/DownloadTask.kt +++ b/android/src/main/kotlin/vn/hunghd/flutterdownloader/DownloadTask.kt @@ -11,6 +11,7 @@ data class DownloadTask( var headers: String, var mimeType: String?, var resumable: Boolean, + var notificationTitle: String?, var showNotification: Boolean, var openFileFromNotification: Boolean, var timeCreated: Long, diff --git a/android/src/main/kotlin/vn/hunghd/flutterdownloader/DownloadWorker.kt b/android/src/main/kotlin/vn/hunghd/flutterdownloader/DownloadWorker.kt index d5d68e3d..60f59222 100644 --- a/android/src/main/kotlin/vn/hunghd/flutterdownloader/DownloadWorker.kt +++ b/android/src/main/kotlin/vn/hunghd/flutterdownloader/DownloadWorker.kt @@ -62,6 +62,7 @@ class DownloadWorker(context: Context, params: WorkerParameters) : private var dbHelper: TaskDbHelper? = null private var taskDao: TaskDao? = null private var showNotification = false + private var notificationTitle: String? = null private var clickToOpenDownloadedFile = false private var debug = false private var ignoreSsl = false @@ -139,7 +140,7 @@ class DownloadWorker(context: Context, params: WorkerParameters) : val filename: String? = inputData.getString(ARG_FILE_NAME) val task = taskDao?.loadTask(id.toString()) if (task != null && task.status == DownloadStatus.ENQUEUED) { - updateNotification(context, filename ?: url, DownloadStatus.CANCELED, -1, null, true) + updateNotification(context, notificationTitle ?: filename ?: url, DownloadStatus.CANCELED, -1, null, true) taskDao?.updateTask(id.toString(), DownloadStatus.CANCELED, lastProgress) } } @@ -179,6 +180,7 @@ class DownloadWorker(context: Context, params: WorkerParameters) : if (task == null || task.status == DownloadStatus.CANCELED) { return Result.success() } + notificationTitle = inputData.getString(ARG_NOTIFICATION_TITLE) showNotification = inputData.getBoolean(ARG_SHOW_NOTIFICATION, false) clickToOpenDownloadedFile = inputData.getBoolean(ARG_OPEN_FILE_FROM_NOTIFICATION, false) @@ -187,7 +189,7 @@ class DownloadWorker(context: Context, params: WorkerParameters) : setupNotification(applicationContext) updateNotification( applicationContext, - filename ?: url, + notificationTitle ?: filename ?: url, DownloadStatus.RUNNING, task.progress, null, @@ -209,7 +211,7 @@ class DownloadWorker(context: Context, params: WorkerParameters) : taskDao = null Result.success() } catch (e: Exception) { - updateNotification(applicationContext, filename ?: url, DownloadStatus.FAILED, -1, null, true) + updateNotification(applicationContext, notificationTitle ?: filename ?: url, DownloadStatus.FAILED, -1, null, true) taskDao?.updateTask(id.toString(), DownloadStatus.FAILED, lastProgress) e.printStackTrace() dbHelper = null @@ -416,7 +418,7 @@ class DownloadWorker(context: Context, params: WorkerParameters) : taskDao!!.updateTask(id.toString(), DownloadStatus.RUNNING, progress) updateNotification( context, - actualFilename, + notificationTitle ?: actualFilename, DownloadStatus.RUNNING, progress, null, @@ -462,19 +464,19 @@ class DownloadWorker(context: Context, params: WorkerParameters) : } } taskDao!!.updateTask(id.toString(), status, progress) - updateNotification(context, actualFilename, status, progress, pendingIntent, true) + updateNotification(context, notificationTitle ?: actualFilename, status, progress, pendingIntent, true) log(if (isStopped) "Download canceled" else "File downloaded") } else { val loadedTask = taskDao!!.loadTask(id.toString()) val status = if (isStopped) if (loadedTask!!.resumable) DownloadStatus.PAUSED else DownloadStatus.CANCELED else DownloadStatus.FAILED taskDao!!.updateTask(id.toString(), status, lastProgress) - updateNotification(context, actualFilename ?: fileURL, status, -1, null, true) + updateNotification(context, notificationTitle ?: actualFilename ?: fileURL, status, -1, null, true) log(if (isStopped) "Download canceled" else "Server replied HTTP code: $responseCode") } } catch (e: IOException) { taskDao!!.updateTask(id.toString(), DownloadStatus.FAILED, lastProgress) - updateNotification(context, actualFilename ?: fileURL, DownloadStatus.FAILED, -1, null, true) + updateNotification(context, notificationTitle ?: actualFilename ?: fileURL, DownloadStatus.FAILED, -1, null, true) e.printStackTrace() } finally { if (outputStream != null) { @@ -837,6 +839,7 @@ class DownloadWorker(context: Context, params: WorkerParameters) : const val ARG_HEADERS = "headers" const val ARG_IS_RESUME = "is_resume" const val ARG_TIMEOUT = "timeout" + const val ARG_NOTIFICATION_TITLE = "notification_title" const val ARG_SHOW_NOTIFICATION = "show_notification" const val ARG_OPEN_FILE_FROM_NOTIFICATION = "open_file_from_notification" const val ARG_CALLBACK_HANDLE = "callback_handle" diff --git a/android/src/main/kotlin/vn/hunghd/flutterdownloader/FlutterDownloaderPlugin.kt b/android/src/main/kotlin/vn/hunghd/flutterdownloader/FlutterDownloaderPlugin.kt index 6867bf65..db00f75b 100644 --- a/android/src/main/kotlin/vn/hunghd/flutterdownloader/FlutterDownloaderPlugin.kt +++ b/android/src/main/kotlin/vn/hunghd/flutterdownloader/FlutterDownloaderPlugin.kt @@ -86,6 +86,7 @@ class FlutterDownloaderPlugin : MethodChannel.MethodCallHandler, FlutterPlugin { savedDir: String?, filename: String?, headers: String?, + notificationTitle: String?, showNotification: Boolean, openFileFromNotification: Boolean, isResume: Boolean, @@ -109,6 +110,7 @@ class FlutterDownloaderPlugin : MethodChannel.MethodCallHandler, FlutterPlugin { .putString(DownloadWorker.ARG_SAVED_DIR, savedDir) .putString(DownloadWorker.ARG_FILE_NAME, filename) .putString(DownloadWorker.ARG_HEADERS, headers) + .putString(DownloadWorker.ARG_NOTIFICATION_TITLE, notificationTitle) .putBoolean(DownloadWorker.ARG_SHOW_NOTIFICATION, showNotification) .putBoolean( DownloadWorker.ARG_OPEN_FILE_FROM_NOTIFICATION, @@ -165,6 +167,7 @@ class FlutterDownloaderPlugin : MethodChannel.MethodCallHandler, FlutterPlugin { val filename: String? = call.argument("file_name") val headers: String = call.requireArgument("headers") val timeout: Int = call.requireArgument("timeout") + val notificationTitle: String? = call.argument("notification_title") val showNotification: Boolean = call.requireArgument("show_notification") val openFileFromNotification: Boolean = call.requireArgument("open_file_from_notification") val requiresStorageNotLow: Boolean = call.requireArgument("requires_storage_not_low") @@ -175,6 +178,7 @@ class FlutterDownloaderPlugin : MethodChannel.MethodCallHandler, FlutterPlugin { savedDir, filename, headers, + notificationTitle, showNotification, openFileFromNotification, false, @@ -195,6 +199,7 @@ class FlutterDownloaderPlugin : MethodChannel.MethodCallHandler, FlutterPlugin { filename, savedDir, headers, + notificationTitle, showNotification, openFileFromNotification, saveInPublicStorage, @@ -279,6 +284,7 @@ class FlutterDownloaderPlugin : MethodChannel.MethodCallHandler, FlutterPlugin { task.savedDir, task.filename, task.headers, + task.notificationTitle, task.showNotification, task.openFileFromNotification, true, @@ -323,7 +329,7 @@ class FlutterDownloaderPlugin : MethodChannel.MethodCallHandler, FlutterPlugin { if (task.status == DownloadStatus.FAILED || task.status == DownloadStatus.CANCELED) { val request: WorkRequest = buildRequest( task.url, task.savedDir, task.filename, - task.headers, task.showNotification, task.openFileFromNotification, + task.headers, task.notificationTitle, task.showNotification, task.openFileFromNotification, false, requiresStorageNotLow, task.saveInPublicStorage, timeout, allowCellular = task.allowCellular ) val newTaskId: String = request.id.toString() diff --git a/android/src/main/kotlin/vn/hunghd/flutterdownloader/TaskDao.kt b/android/src/main/kotlin/vn/hunghd/flutterdownloader/TaskDao.kt index a3f7b3da..89af24b1 100644 --- a/android/src/main/kotlin/vn/hunghd/flutterdownloader/TaskDao.kt +++ b/android/src/main/kotlin/vn/hunghd/flutterdownloader/TaskDao.kt @@ -18,6 +18,7 @@ class TaskDao(private val dbHelper: TaskDbHelper) { TaskEntry.COLUMN_NAME_MIME_TYPE, TaskEntry.COLUMN_NAME_RESUMABLE, TaskEntry.COLUMN_NAME_OPEN_FILE_FROM_NOTIFICATION, + TaskEntry.COLUMN_NAME_NOTIFICATION_TITLE, TaskEntry.COLUMN_NAME_SHOW_NOTIFICATION, TaskEntry.COLUMN_NAME_TIME_CREATED, TaskEntry.COLUMN_SAVE_IN_PUBLIC_STORAGE, @@ -32,6 +33,7 @@ class TaskDao(private val dbHelper: TaskDbHelper) { fileName: String?, savedDir: String?, headers: String?, + notificationTitle: String?, showNotification: Boolean, openFileFromNotification: Boolean, saveInPublicStorage: Boolean, @@ -47,6 +49,7 @@ class TaskDao(private val dbHelper: TaskDbHelper) { values.put(TaskEntry.COLUMN_NAME_SAVED_DIR, savedDir) values.put(TaskEntry.COLUMN_NAME_HEADERS, headers) values.put(TaskEntry.COLUMN_NAME_MIME_TYPE, "unknown") + values.put(TaskEntry.COLUMN_NAME_NOTIFICATION_TITLE, notificationTitle) values.put(TaskEntry.COLUMN_NAME_SHOW_NOTIFICATION, if (showNotification) 1 else 0) values.put( TaskEntry.COLUMN_NAME_OPEN_FILE_FROM_NOTIFICATION, @@ -242,6 +245,7 @@ class TaskDao(private val dbHelper: TaskDbHelper) { val headers = cursor.getString(cursor.getColumnIndexOrThrow(TaskEntry.COLUMN_NAME_HEADERS)) val mimeType = cursor.getString(cursor.getColumnIndexOrThrow(TaskEntry.COLUMN_NAME_MIME_TYPE)) val resumable = cursor.getShort(cursor.getColumnIndexOrThrow(TaskEntry.COLUMN_NAME_RESUMABLE)).toInt() + val notificationTitle = cursor.getString(cursor.getColumnIndexOrThrow(TaskEntry.COLUMN_NAME_NOTIFICATION_TITLE)) val showNotification = cursor.getShort(cursor.getColumnIndexOrThrow(TaskEntry.COLUMN_NAME_SHOW_NOTIFICATION)).toInt() val clickToOpenDownloadedFile = cursor.getShort(cursor.getColumnIndexOrThrow(TaskEntry.COLUMN_NAME_OPEN_FILE_FROM_NOTIFICATION)).toInt() val timeCreated = cursor.getLong(cursor.getColumnIndexOrThrow(TaskEntry.COLUMN_NAME_TIME_CREATED)) @@ -258,6 +262,7 @@ class TaskDao(private val dbHelper: TaskDbHelper) { headers, mimeType, resumable == 1, + notificationTitle, showNotification == 1, clickToOpenDownloadedFile == 1, timeCreated, diff --git a/android/src/main/kotlin/vn/hunghd/flutterdownloader/TaskDbHelper.kt b/android/src/main/kotlin/vn/hunghd/flutterdownloader/TaskDbHelper.kt index 07737109..6e9c0571 100644 --- a/android/src/main/kotlin/vn/hunghd/flutterdownloader/TaskDbHelper.kt +++ b/android/src/main/kotlin/vn/hunghd/flutterdownloader/TaskDbHelper.kt @@ -15,6 +15,7 @@ class TaskDbHelper private constructor(context: Context) : update1to2(db, oldVersion) update2to3(db, oldVersion) update3to4(db, oldVersion) + update4to5(db, oldVersion) } private fun update1to2(db: SQLiteDatabase, oldVersion: Int) { @@ -39,12 +40,19 @@ class TaskDbHelper private constructor(context: Context) : db.execSQL("ALTER TABLE ${TaskEntry.TABLE_NAME} ADD COLUMN ${TaskEntry.COLUMN_ALLOW_CELLULAR} TINYINT DEFAULT 1") } + private fun update4to5(db: SQLiteDatabase, oldVersion: Int) { + if (oldVersion > 4) { + return + } + db.execSQL("ALTER TABLE ${TaskEntry.TABLE_NAME} ADD COLUMN ${TaskEntry.COLUMN_NAME_NOTIFICATION_TITLE} TEXT") + } + override fun onDowngrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { onUpgrade(db, oldVersion, newVersion) } companion object { - const val DATABASE_VERSION = 4 + const val DATABASE_VERSION = 5 const val DATABASE_NAME = "download_tasks.db" private var instance: TaskDbHelper? = null private const val SQL_CREATE_ENTRIES = ( @@ -59,6 +67,7 @@ class TaskDbHelper private constructor(context: Context) : TaskEntry.COLUMN_NAME_HEADERS + " TEXT, " + TaskEntry.COLUMN_NAME_MIME_TYPE + " VARCHAR(128), " + TaskEntry.COLUMN_NAME_RESUMABLE + " TINYINT DEFAULT 0, " + + TaskEntry.COLUMN_NAME_NOTIFICATION_TITLE + " TEXT, " + TaskEntry.COLUMN_NAME_SHOW_NOTIFICATION + " TINYINT DEFAULT 0, " + TaskEntry.COLUMN_NAME_OPEN_FILE_FROM_NOTIFICATION + " TINYINT DEFAULT 0, " + TaskEntry.COLUMN_NAME_TIME_CREATED + " INTEGER DEFAULT 0, " + diff --git a/android/src/main/kotlin/vn/hunghd/flutterdownloader/TaskEntry.kt b/android/src/main/kotlin/vn/hunghd/flutterdownloader/TaskEntry.kt index 78cececf..51eeeab3 100644 --- a/android/src/main/kotlin/vn/hunghd/flutterdownloader/TaskEntry.kt +++ b/android/src/main/kotlin/vn/hunghd/flutterdownloader/TaskEntry.kt @@ -13,6 +13,7 @@ object TaskEntry : BaseColumns { const val COLUMN_NAME_MIME_TYPE = "mime_type" const val COLUMN_NAME_RESUMABLE = "resumable" const val COLUMN_NAME_HEADERS = "headers" + const val COLUMN_NAME_NOTIFICATION_TITLE = "notification_title" const val COLUMN_NAME_SHOW_NOTIFICATION = "show_notification" const val COLUMN_NAME_OPEN_FILE_FROM_NOTIFICATION = "open_file_from_notification" const val COLUMN_NAME_TIME_CREATED = "time_created" diff --git a/lib/src/downloader.dart b/lib/src/downloader.dart index adbe4504..180fa108 100644 --- a/lib/src/downloader.dart +++ b/lib/src/downloader.dart @@ -74,6 +74,9 @@ class FlutterDownloader { /// /// ### Android-only /// + /// [notificationTitle] is the title of the notification shown during the + /// download. If it is null, the title is determined from the fileName or HTTP response. + /// /// If [showNotification] is true, a notification with the current download /// progress will be shown. /// @@ -96,6 +99,7 @@ class FlutterDownloader { required String savedDir, String? fileName, Map headers = const {}, + String? notificationTitle, bool showNotification = true, bool openFileFromNotification = true, bool requiresStorageNotLow = true, @@ -112,6 +116,7 @@ class FlutterDownloader { 'saved_dir': savedDir, 'file_name': fileName, 'headers': jsonEncode(headers), + 'notification_title': notificationTitle, 'show_notification': showNotification, 'open_file_from_notification': openFileFromNotification, 'requires_storage_not_low': requiresStorageNotLow,