diff --git a/android/src/main/java/vn/hunghd/flutterdownloader/DownloadTask.java b/android/src/main/java/vn/hunghd/flutterdownloader/DownloadTask.java index 84b3ae3f..3ea8518c 100644 --- a/android/src/main/java/vn/hunghd/flutterdownloader/DownloadTask.java +++ b/android/src/main/java/vn/hunghd/flutterdownloader/DownloadTask.java @@ -5,6 +5,7 @@ public class DownloadTask { String taskId; int status; int progress; + String title; String url; String filename; String savedDir; @@ -15,12 +16,13 @@ public class DownloadTask { boolean openFileFromNotification; long timeCreated; - DownloadTask(int primaryId, String taskId, int status, int progress, String url, String filename, String savedDir, + DownloadTask(int primaryId, String taskId, int status, int progress, String title, String url, String filename, String savedDir, String headers, String mimeType, boolean resumable, boolean showNotification, boolean openFileFromNotification, long timeCreated) { this.primaryId = primaryId; this.taskId = taskId; this.status = status; this.progress = progress; + this.title = title; this.url = url; this.filename = filename; this.savedDir = savedDir; @@ -34,6 +36,6 @@ public class DownloadTask { @Override public String toString() { - return "DownloadTask{taskId=" + taskId + ",status=" + status + ",progress=" + progress + ",url=" + url + ",filename=" + filename + ",savedDir=" + savedDir + ",headers=" + headers + "}"; + return "DownloadTask{taskId=" + taskId + ",status=" + status + ",progress=" + progress + ",title=" + title + ",url=" + url + ",filename=" + filename + ",savedDir=" + savedDir + ",headers=" + headers + "}"; } } diff --git a/android/src/main/java/vn/hunghd/flutterdownloader/DownloadWorker.java b/android/src/main/java/vn/hunghd/flutterdownloader/DownloadWorker.java index bd29a8f7..313e7698 100644 --- a/android/src/main/java/vn/hunghd/flutterdownloader/DownloadWorker.java +++ b/android/src/main/java/vn/hunghd/flutterdownloader/DownloadWorker.java @@ -57,6 +57,7 @@ import io.flutter.view.FlutterRunArguments; public class DownloadWorker extends Worker implements MethodChannel.MethodCallHandler { + public static final String ARG_TITLE = "title"; public static final String ARG_URL = "url"; public static final String ARG_FILE_NAME = "file_name"; public static final String ARG_SAVED_DIR = "saved_file"; @@ -160,6 +161,7 @@ public Result doWork() { dbHelper = TaskDbHelper.getInstance(context); taskDao = new TaskDao(dbHelper); + String title = getInputData().getString(ARG_TITLE); String url = getInputData().getString(ARG_URL); String filename = getInputData().getString(ARG_FILE_NAME); String savedDir = getInputData().getString(ARG_SAVED_DIR); @@ -185,17 +187,22 @@ public Result doWork() { buildNotification(context); - updateNotification(context, filename == null ? url : filename, DownloadStatus.RUNNING, task.progress, null); + // Default to the filename or URL if a title has not been specified. + if (title == null || title.isEmpty()) { + title = filename == null ? url : filename; + } + + updateNotification(context, title, DownloadStatus.RUNNING, task.progress, null); taskDao.updateTask(getId().toString(), DownloadStatus.RUNNING, 0); try { - downloadFile(context, url, savedDir, filename, headers, isResume); + downloadFile(context, title, url, savedDir, filename, headers, isResume); cleanUp(); dbHelper = null; taskDao = null; return Result.success(); } catch (Exception e) { - updateNotification(context, filename == null ? url : filename, DownloadStatus.FAILED, -1, null); + updateNotification(context, title, DownloadStatus.FAILED, -1, null); taskDao.updateTask(getId().toString(), DownloadStatus.FAILED, lastProgress); e.printStackTrace(); dbHelper = null; @@ -231,7 +238,7 @@ private long setupPartialDownloadedDataHeader(HttpURLConnection conn, String fil return downloadedBytes; } - private void downloadFile(Context context, String fileURL, String savedDir, String filename, String headers, boolean isResume) throws IOException { + private void downloadFile(Context context, String title, String fileURL, String savedDir, String filename, String headers, boolean isResume) throws IOException { String url = fileURL; URL resourceUrl, base, next; Map visited; @@ -340,7 +347,7 @@ private void downloadFile(Context context, String fileURL, String savedDir, Stri if ((lastProgress == 0 || progress > lastProgress + STEP_UPDATE || progress == 100) && progress != lastProgress) { lastProgress = progress; - updateNotification(context, filename, DownloadStatus.RUNNING, progress, null); + updateNotification(context, title, DownloadStatus.RUNNING, progress, null); // This line possibly causes system overloaded because of accessing to DB too many ?!!! // but commenting this line causes tasks loaded from DB missing current downloading progress, @@ -370,19 +377,19 @@ private void downloadFile(Context context, String fileURL, String savedDir, Stri } } } - updateNotification(context, filename, status, progress, pendingIntent); + updateNotification(context, title, status, progress, pendingIntent); taskDao.updateTask(getId().toString(), status, progress); log(isStopped() ? "Download canceled" : "File downloaded"); } else { DownloadTask task = taskDao.loadTask(getId().toString()); int status = isStopped() ? (task.resumable ? DownloadStatus.PAUSED : DownloadStatus.CANCELED) : DownloadStatus.FAILED; - updateNotification(context, filename, status, -1, null); + updateNotification(context, title, status, -1, null); taskDao.updateTask(getId().toString(), status, lastProgress); log(isStopped() ? "Download canceled" : "Server replied HTTP code: " + responseCode); } } catch (IOException e) { - updateNotification(context, filename == null ? fileURL : filename, DownloadStatus.FAILED, -1, null); + updateNotification(context, title, DownloadStatus.FAILED, -1, null); taskDao.updateTask(getId().toString(), DownloadStatus.FAILED, lastProgress); e.printStackTrace(); } finally { diff --git a/android/src/main/java/vn/hunghd/flutterdownloader/FlutterDownloaderPlugin.java b/android/src/main/java/vn/hunghd/flutterdownloader/FlutterDownloaderPlugin.java index 650d4e83..4348bc75 100644 --- a/android/src/main/java/vn/hunghd/flutterdownloader/FlutterDownloaderPlugin.java +++ b/android/src/main/java/vn/hunghd/flutterdownloader/FlutterDownloaderPlugin.java @@ -112,7 +112,7 @@ public void onDetachedFromEngine(FlutterPluginBinding binding) { } } - private WorkRequest buildRequest(String url, String savedDir, String filename, String headers, boolean showNotification, boolean openFileFromNotification, boolean isResume, boolean requiresStorageNotLow) { + private WorkRequest buildRequest(String url, String savedDir, String title, String filename, String headers, boolean showNotification, boolean openFileFromNotification, boolean isResume, boolean requiresStorageNotLow) { WorkRequest request = new OneTimeWorkRequest.Builder(DownloadWorker.class) .setConstraints(new Constraints.Builder() .setRequiresStorageNotLow(requiresStorageNotLow) @@ -121,6 +121,7 @@ private WorkRequest buildRequest(String url, String savedDir, String filename, S .addTag(TAG) .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 5, TimeUnit.SECONDS) .setInputData(new Data.Builder() + .putString(DownloadWorker.ARG_TITLE, title) .putString(DownloadWorker.ARG_URL, url) .putString(DownloadWorker.ARG_SAVED_DIR, savedDir) .putString(DownloadWorker.ARG_FILE_NAME, filename) @@ -162,6 +163,7 @@ private void registerCallback(MethodCall call, MethodChannel.Result result) { } private void enqueue(MethodCall call, MethodChannel.Result result) { + String title = call.argument("title"); String url = call.argument("url"); String savedDir = call.argument("saved_dir"); String filename = call.argument("file_name"); @@ -169,12 +171,12 @@ private void enqueue(MethodCall call, MethodChannel.Result result) { boolean showNotification = call.argument("show_notification"); boolean openFileFromNotification = call.argument("open_file_from_notification"); boolean requiresStorageNotLow = call.argument("requires_storage_not_low"); - WorkRequest request = buildRequest(url, savedDir, filename, headers, showNotification, openFileFromNotification, false, requiresStorageNotLow); + WorkRequest request = buildRequest(url, savedDir, title, filename, headers, showNotification, openFileFromNotification, false, requiresStorageNotLow); WorkManager.getInstance(context).enqueue(request); String taskId = request.getId().toString(); result.success(taskId); sendUpdateProgress(taskId, DownloadStatus.ENQUEUED, 0); - taskDao.insertOrUpdateNewTask(taskId, url, DownloadStatus.ENQUEUED, 0, filename, savedDir, headers, showNotification, openFileFromNotification); + taskDao.insertOrUpdateNewTask(taskId, title, url, DownloadStatus.ENQUEUED, 0, filename, savedDir, headers, showNotification, openFileFromNotification); } private void loadTasks(MethodCall call, MethodChannel.Result result) { @@ -185,6 +187,7 @@ private void loadTasks(MethodCall call, MethodChannel.Result result) { item.put("task_id", task.taskId); item.put("status", task.status); item.put("progress", task.progress); + item.put("title", task.title); item.put("url", task.url); item.put("file_name", task.filename); item.put("saved_dir", task.savedDir); @@ -203,6 +206,7 @@ private void loadTasksWithRawQuery(MethodCall call, MethodChannel.Result result) item.put("task_id", task.taskId); item.put("status", task.status); item.put("progress", task.progress); + item.put("title", task.title); item.put("url", task.url); item.put("file_name", task.filename); item.put("saved_dir", task.savedDir); @@ -243,7 +247,7 @@ private void resume(MethodCall call, MethodChannel.Result result) { String partialFilePath = task.savedDir + File.separator + filename; File partialFile = new File(partialFilePath); if (partialFile.exists()) { - WorkRequest request = buildRequest(task.url, task.savedDir, task.filename, task.headers, task.showNotification, task.openFileFromNotification, true, requiresStorageNotLow); + WorkRequest request = buildRequest(task.url, task.savedDir, task.title, task.filename, task.headers, task.showNotification, task.openFileFromNotification, true, requiresStorageNotLow); String newTaskId = request.getId().toString(); result.success(newTaskId); sendUpdateProgress(newTaskId, DownloadStatus.RUNNING, task.progress); @@ -266,7 +270,7 @@ private void retry(MethodCall call, MethodChannel.Result result) { boolean requiresStorageNotLow = call.argument("requires_storage_not_low"); if (task != null) { if (task.status == DownloadStatus.FAILED || task.status == DownloadStatus.CANCELED) { - WorkRequest request = buildRequest(task.url, task.savedDir, task.filename, task.headers, task.showNotification, task.openFileFromNotification, false, requiresStorageNotLow); + WorkRequest request = buildRequest(task.url, task.savedDir, task.title, task.filename, task.headers, task.showNotification, task.openFileFromNotification, false, requiresStorageNotLow); String newTaskId = request.getId().toString(); result.success(newTaskId); sendUpdateProgress(newTaskId, DownloadStatus.ENQUEUED, task.progress); diff --git a/android/src/main/java/vn/hunghd/flutterdownloader/TaskContract.java b/android/src/main/java/vn/hunghd/flutterdownloader/TaskContract.java index 425d1277..aa17985e 100644 --- a/android/src/main/java/vn/hunghd/flutterdownloader/TaskContract.java +++ b/android/src/main/java/vn/hunghd/flutterdownloader/TaskContract.java @@ -11,6 +11,7 @@ public static class TaskEntry implements BaseColumns { public static final String COLUMN_NAME_TASK_ID = "task_id"; public static final String COLUMN_NAME_STATUS = "status"; public static final String COLUMN_NAME_PROGRESS = "progress"; + public static final String COLUMN_NAME_TITLE = "title"; public static final String COLUMN_NAME_URL = "url"; public static final String COLUMN_NAME_SAVED_DIR = "saved_dir"; public static final String COLUMN_NAME_FILE_NAME = "file_name"; diff --git a/android/src/main/java/vn/hunghd/flutterdownloader/TaskDao.java b/android/src/main/java/vn/hunghd/flutterdownloader/TaskDao.java index 2c074dbb..42d411c1 100644 --- a/android/src/main/java/vn/hunghd/flutterdownloader/TaskDao.java +++ b/android/src/main/java/vn/hunghd/flutterdownloader/TaskDao.java @@ -16,6 +16,7 @@ public class TaskDao { TaskContract.TaskEntry.COLUMN_NAME_TASK_ID, TaskContract.TaskEntry.COLUMN_NAME_PROGRESS, TaskContract.TaskEntry.COLUMN_NAME_STATUS, + TaskContract.TaskEntry.COLUMN_NAME_TITLE, TaskContract.TaskEntry.COLUMN_NAME_URL, TaskContract.TaskEntry.COLUMN_NAME_FILE_NAME, TaskContract.TaskEntry.COLUMN_NAME_SAVED_DIR, @@ -31,12 +32,13 @@ public TaskDao(TaskDbHelper helper) { dbHelper = helper; } - public void insertOrUpdateNewTask(String taskId, String url, int status, int progress, String fileName, + public void insertOrUpdateNewTask(String taskId, String title, String url, int status, int progress, String fileName, String savedDir, String headers, boolean showNotification, boolean openFileFromNotification) { SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(TaskContract.TaskEntry.COLUMN_NAME_TASK_ID, taskId); + values.put(TaskContract.TaskEntry.COLUMN_NAME_TITLE, title); values.put(TaskContract.TaskEntry.COLUMN_NAME_URL, url); values.put(TaskContract.TaskEntry.COLUMN_NAME_STATUS, status); values.put(TaskContract.TaskEntry.COLUMN_NAME_PROGRESS, progress); @@ -214,6 +216,7 @@ private DownloadTask parseCursor(Cursor cursor) { String taskId = cursor.getString(cursor.getColumnIndexOrThrow(TaskContract.TaskEntry.COLUMN_NAME_TASK_ID)); int status = cursor.getInt(cursor.getColumnIndexOrThrow(TaskContract.TaskEntry.COLUMN_NAME_STATUS)); int progress = cursor.getInt(cursor.getColumnIndexOrThrow(TaskContract.TaskEntry.COLUMN_NAME_PROGRESS)); + String title = cursor.getString(cursor.getColumnIndexOrThrow(TaskContract.TaskEntry.COLUMN_NAME_TITLE)); String url = cursor.getString(cursor.getColumnIndexOrThrow(TaskContract.TaskEntry.COLUMN_NAME_URL)); String filename = cursor.getString(cursor.getColumnIndexOrThrow(TaskContract.TaskEntry.COLUMN_NAME_FILE_NAME)); String savedDir = cursor.getString(cursor.getColumnIndexOrThrow(TaskContract.TaskEntry.COLUMN_NAME_SAVED_DIR)); @@ -223,7 +226,7 @@ private DownloadTask parseCursor(Cursor cursor) { int showNotification = cursor.getShort(cursor.getColumnIndexOrThrow(TaskContract.TaskEntry.COLUMN_NAME_SHOW_NOTIFICATION)); int clickToOpenDownloadedFile = cursor.getShort(cursor.getColumnIndexOrThrow(TaskContract.TaskEntry.COLUMN_NAME_OPEN_FILE_FROM_NOTIFICATION)); long timeCreated = cursor.getLong(cursor.getColumnIndexOrThrow(TaskContract.TaskEntry.COLUMN_NAME_TIME_CREATED)); - return new DownloadTask(primaryId, taskId, status, progress, url, filename, savedDir, headers, + return new DownloadTask(primaryId, taskId, status, progress, title, url, filename, savedDir, headers, mimeType, resumable == 1, showNotification == 1, clickToOpenDownloadedFile == 1, timeCreated); } diff --git a/android/src/main/java/vn/hunghd/flutterdownloader/TaskDbHelper.java b/android/src/main/java/vn/hunghd/flutterdownloader/TaskDbHelper.java index d6ddfafd..bb21dbfe 100644 --- a/android/src/main/java/vn/hunghd/flutterdownloader/TaskDbHelper.java +++ b/android/src/main/java/vn/hunghd/flutterdownloader/TaskDbHelper.java @@ -7,7 +7,7 @@ import vn.hunghd.flutterdownloader.TaskContract.TaskEntry; public class TaskDbHelper extends SQLiteOpenHelper { - public static final int DATABASE_VERSION = 2; + public static final int DATABASE_VERSION = 3; public static final String DATABASE_NAME = "download_tasks.db"; private static TaskDbHelper instance = null; @@ -17,6 +17,7 @@ public class TaskDbHelper extends SQLiteOpenHelper { TaskEntry._ID + " INTEGER PRIMARY KEY," + TaskEntry.COLUMN_NAME_TASK_ID + " VARCHAR(256), " + TaskEntry.COLUMN_NAME_URL + " TEXT, " + + TaskEntry.COLUMN_NAME_TITLE + " TEXT, " + TaskEntry.COLUMN_NAME_STATUS + " INTEGER DEFAULT 0, " + TaskEntry.COLUMN_NAME_PROGRESS + " INTEGER DEFAULT 0, " + TaskEntry.COLUMN_NAME_FILE_NAME + " TEXT, " + diff --git a/example/android/app/app.iml b/example/android/app/app.iml index cedcbb2c..8c950334 100644 --- a/example/android/app/app.iml +++ b/example/android/app/app.iml @@ -121,12 +121,12 @@ - - - - - - + + + + + + @@ -145,6 +145,7 @@ + diff --git a/example/lib/main.dart b/example/lib/main.dart index 4599316d..fec47a71 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,12 +1,12 @@ +import 'dart:async'; +import 'dart:io'; import 'dart:isolate'; import 'dart:ui'; import 'package:flutter/material.dart'; -import 'dart:async'; -import 'package:path_provider/path_provider.dart'; import 'package:flutter_downloader/flutter_downloader.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; -import 'dart:io'; const debug = true; @@ -48,33 +48,22 @@ class MyHomePage extends StatefulWidget with WidgetsBindingObserver { class _MyHomePageState extends State { final _documents = [ - { - 'name': 'Learning Android Studio', - 'link': - 'http://barbra-coco.dyndns.org/student/learning_android_studio.pdf' - }, + {'name': 'Learning Android Studio', 'link': 'http://barbra-coco.dyndns.org/student/learning_android_studio.pdf'}, { 'name': 'Android Programming Cookbook', - 'link': - 'http://enos.itcollege.ee/~jpoial/allalaadimised/reading/Android-Programming-Cookbook.pdf' - }, - { - 'name': 'iOS Programming Guide', - 'link': - 'http://darwinlogic.com/uploads/education/iOS_Programming_Guide.pdf' + 'link': 'http://enos.itcollege.ee/~jpoial/allalaadimised/reading/Android-Programming-Cookbook.pdf' }, + {'name': 'iOS Programming Guide', 'link': 'http://darwinlogic.com/uploads/education/iOS_Programming_Guide.pdf'}, { 'name': 'Objective-C Programming (Pre-Course Workbook', - 'link': - 'https://www.bignerdranch.com/documents/objective-c-prereading-assignment.pdf' + 'link': 'https://www.bignerdranch.com/documents/objective-c-prereading-assignment.pdf' }, ]; final _images = [ { 'name': 'Arches National Park', - 'link': - 'https://upload.wikimedia.org/wikipedia/commons/6/60/The_Organ_at_Arches_National_Park_Utah_Corrected.jpg' + 'link': 'https://upload.wikimedia.org/wikipedia/commons/6/60/The_Organ_at_Arches_National_Park_Utah_Corrected.jpg' }, { 'name': 'Canyonlands National Park', @@ -83,27 +72,17 @@ class _MyHomePageState extends State { }, { 'name': 'Death Valley National Park', - 'link': - 'https://upload.wikimedia.org/wikipedia/commons/b/b2/Sand_Dunes_in_Death_Valley_National_Park.jpg' + 'link': 'https://upload.wikimedia.org/wikipedia/commons/b/b2/Sand_Dunes_in_Death_Valley_National_Park.jpg' }, { 'name': 'Gates of the Arctic National Park and Preserve', - 'link': - 'https://upload.wikimedia.org/wikipedia/commons/e/e4/GatesofArctic.jpg' + 'link': 'https://upload.wikimedia.org/wikipedia/commons/e/e4/GatesofArctic.jpg' } ]; final _videos = [ - { - 'name': 'Big Buck Bunny', - 'link': - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4' - }, - { - 'name': 'Elephant Dream', - 'link': - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4' - } + {'name': 'Big Buck Bunny', 'link': 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4'}, + {'name': 'Elephant Dream', 'link': 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4'} ]; List<_TaskInfo> _tasks; @@ -134,8 +113,7 @@ class _MyHomePageState extends State { } void _bindBackgroundIsolate() { - bool isSuccess = IsolateNameServer.registerPortWithName( - _port.sendPort, 'downloader_send_port'); + bool isSuccess = IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port'); if (!isSuccess) { _unbindBackgroundIsolate(); _bindBackgroundIsolate(); @@ -163,14 +141,11 @@ class _MyHomePageState extends State { IsolateNameServer.removePortNameMapping('downloader_send_port'); } - static void downloadCallback( - String id, DownloadTaskStatus status, int progress) { + static void downloadCallback(String id, DownloadTaskStatus status, int progress) { if (debug) { - print( - 'Background Isolate Callback: task ($id) is in status ($status) and process ($progress)'); + print('Background Isolate Callback: task ($id) is in status ($status) and process ($progress)'); } - final SendPort send = - IsolateNameServer.lookupPortByName('downloader_send_port'); + final SendPort send = IsolateNameServer.lookupPortByName('downloader_send_port'); send.send([id, status, progress]); } @@ -192,30 +167,21 @@ class _MyHomePageState extends State { children: _items .map((item) => item.task == null ? new Container( - padding: const EdgeInsets.symmetric( - horizontal: 16.0, vertical: 8.0), + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), child: Text( item.name, - style: TextStyle( - fontWeight: FontWeight.bold, - color: Colors.blue, - fontSize: 18.0), + style: TextStyle(fontWeight: FontWeight.bold, color: Colors.blue, fontSize: 18.0), ), ) : new Container( - padding: const EdgeInsets.only( - left: 16.0, right: 8.0), + padding: const EdgeInsets.only(left: 16.0, right: 8.0), child: InkWell( - onTap: item.task.status == - DownloadTaskStatus.complete + onTap: item.task.status == DownloadTaskStatus.complete ? () { - _openDownloadedFile(item.task) - .then((success) { + _openDownloadedFile(item.task).then((success) { if (!success) { Scaffold.of(context) - .showSnackBar(SnackBar( - content: Text( - 'Cannot open this file'))); + .showSnackBar(SnackBar(content: Text('Cannot open this file'))); } }); } @@ -226,47 +192,35 @@ class _MyHomePageState extends State { width: double.infinity, height: 64.0, child: new Row( - crossAxisAlignment: - CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, children: [ new Expanded( child: new Text( item.name, maxLines: 1, softWrap: true, - overflow: - TextOverflow.ellipsis, + overflow: TextOverflow.ellipsis, ), ), new Padding( - padding: - const EdgeInsets.only( - left: 8.0), - child: _buildActionForTask( - item.task), + padding: const EdgeInsets.only(left: 8.0), + child: _buildActionForTask(item.task), ), ], ), ), - item.task.status == - DownloadTaskStatus - .running || - item.task.status == - DownloadTaskStatus.paused + item.task.status == DownloadTaskStatus.running || + item.task.status == DownloadTaskStatus.paused ? new Positioned( left: 0.0, right: 0.0, bottom: 0.0, - child: - new LinearProgressIndicator( - value: item.task.progress / - 100, + child: new LinearProgressIndicator( + value: item.task.progress / 100, ), ) : new Container() - ] - .where((child) => child != null) - .toList(), + ].where((child) => child != null).toList(), ), ), )) @@ -280,13 +234,11 @@ class _MyHomePageState extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( - padding: - const EdgeInsets.symmetric(horizontal: 24.0), + padding: const EdgeInsets.symmetric(horizontal: 24.0), child: Text( 'Please grant accessing storage permission to continue -_-', textAlign: TextAlign.center, - style: TextStyle( - color: Colors.blueGrey, fontSize: 18.0), + style: TextStyle(color: Colors.blueGrey, fontSize: 18.0), ), ), SizedBox( @@ -302,10 +254,7 @@ class _MyHomePageState extends State { }, child: Text( 'Retry', - style: TextStyle( - color: Colors.blue, - fontWeight: FontWeight.bold, - fontSize: 20.0), + style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold, fontSize: 20.0), )) ], ), @@ -399,6 +348,7 @@ class _MyHomePageState extends State { void _requestDownload(_TaskInfo task) async { task.taskId = await FlutterDownloader.enqueue( url: task.link, + title: task.name, headers: {"auth": "test_for_sql_encoding"}, savedDir: _localPath, showNotification: true, @@ -428,20 +378,17 @@ class _MyHomePageState extends State { } void _delete(_TaskInfo task) async { - await FlutterDownloader.remove( - taskId: task.taskId, shouldDeleteContent: true); + await FlutterDownloader.remove(taskId: task.taskId, shouldDeleteContent: true); await _prepare(); setState(() {}); } Future _checkPermission() async { if (widget.platform == TargetPlatform.android) { - PermissionStatus permission = await PermissionHandler() - .checkPermissionStatus(PermissionGroup.storage); + PermissionStatus permission = await PermissionHandler().checkPermissionStatus(PermissionGroup.storage); if (permission != PermissionStatus.granted) { Map permissions = - await PermissionHandler() - .requestPermissions([PermissionGroup.storage]); + await PermissionHandler().requestPermissions([PermissionGroup.storage]); if (permissions[PermissionGroup.storage] == PermissionStatus.granted) { return true; } @@ -461,8 +408,7 @@ class _MyHomePageState extends State { _tasks = []; _items = []; - _tasks.addAll(_documents.map((document) => - _TaskInfo(name: document['name'], link: document['link']))); + _tasks.addAll(_documents.map((document) => _TaskInfo(name: document['name'], link: document['link']))); _items.add(_ItemHolder(name: 'Documents')); for (int i = count; i < _tasks.length; i++) { @@ -470,8 +416,7 @@ class _MyHomePageState extends State { count++; } - _tasks.addAll(_images - .map((image) => _TaskInfo(name: image['name'], link: image['link']))); + _tasks.addAll(_images.map((image) => _TaskInfo(name: image['name'], link: image['link']))); _items.add(_ItemHolder(name: 'Images')); for (int i = count; i < _tasks.length; i++) { @@ -479,8 +424,7 @@ class _MyHomePageState extends State { count++; } - _tasks.addAll(_videos - .map((video) => _TaskInfo(name: video['name'], link: video['link']))); + _tasks.addAll(_videos.map((video) => _TaskInfo(name: video['name'], link: video['link']))); _items.add(_ItemHolder(name: 'Videos')); for (int i = count; i < _tasks.length; i++) { @@ -514,9 +458,8 @@ class _MyHomePageState extends State { } Future _findLocalPath() async { - final directory = widget.platform == TargetPlatform.android - ? await getExternalStorageDirectory() - : await getApplicationDocumentsDirectory(); + final directory = + widget.platform == TargetPlatform.android ? await getExternalStorageDirectory() : await getApplicationDocumentsDirectory(); return directory.path; } } diff --git a/lib/src/downloader.dart b/lib/src/downloader.dart index 267cd295..0f73de19 100644 --- a/lib/src/downloader.dart +++ b/lib/src/downloader.dart @@ -16,8 +16,7 @@ import 'models.dart'; /// * `progress`: current progress value of a download task, the value is in /// range of 0 and 100 /// -typedef void DownloadCallback( - String id, DownloadTaskStatus status, int progress); +typedef void DownloadCallback(String id, DownloadTaskStatus status, int progress); /// /// A convenient class wraps all api functions of **FlutterDownloader** plugin @@ -27,14 +26,12 @@ class FlutterDownloader { static bool _initialized = false; static Future initialize({bool debug = true}) async { - assert(!_initialized, - 'FlutterDownloader.initialize() must be called only once!'); + assert(!_initialized, 'FlutterDownloader.initialize() must be called only once!'); WidgetsFlutterBinding.ensureInitialized(); final callback = PluginUtilities.getCallbackHandle(callbackDispatcher); - await _channel.invokeMethod( - 'initialize', [callback.toRawHandle(), debug ? 1 : 0]); + await _channel.invokeMethod('initialize', [callback.toRawHandle(), debug ? 1 : 0]); _initialized = true; return null; } @@ -65,6 +62,7 @@ class FlutterDownloader { static Future enqueue( {@required String url, @required String savedDir, + String title, String fileName, Map headers, bool showNotification = true, @@ -76,15 +74,13 @@ class FlutterDownloader { StringBuffer headerBuilder = StringBuffer(); if (headers != null) { headerBuilder.write('{'); - headerBuilder.writeAll( - headers.entries - .map((entry) => '\"${entry.key}\": \"${entry.value}\"'), - ','); + headerBuilder.writeAll(headers.entries.map((entry) => '\"${entry.key}\": \"${entry.value}\"'), ','); headerBuilder.write('}'); } try { String taskId = await _channel.invokeMethod('enqueue', { 'url': url, + 'title': title, 'saved_dir': savedDir, 'file_name': fileName, 'headers': headerBuilder.toString(), @@ -117,6 +113,7 @@ class FlutterDownloader { status: DownloadTaskStatus(item['status']), progress: item['progress'], url: item['url'], + title: item['title'], filename: item['file_name'], savedDir: item['saved_dir'], timeCreated: item['time_created'])) @@ -147,19 +144,18 @@ class FlutterDownloader { /// FlutterDownloader.loadTasksWithRawQuery(query: 'SELECT * FROM task WHERE status=3'); /// ``` /// - static Future> loadTasksWithRawQuery( - {@required String query}) async { + static Future> loadTasksWithRawQuery({@required String query}) async { assert(_initialized, 'FlutterDownloader.initialize() must be called first'); try { - List result = await _channel - .invokeMethod('loadTasksWithRawQuery', {'query': query}); + List result = await _channel.invokeMethod('loadTasksWithRawQuery', {'query': query}); return result .map((item) => new DownloadTask( taskId: item['task_id'], status: DownloadTaskStatus(item['status']), progress: item['progress'], url: item['url'], + title: item['title'], filename: item['file_name'], savedDir: item['saved_dir'], timeCreated: item['time_created'])) @@ -289,13 +285,11 @@ class FlutterDownloader { /// * `shouldDeleteContent`: if the task is completed, set `true` to let the /// plugin remove the downloaded file. The default value is `false`. /// - static Future remove( - {@required String taskId, bool shouldDeleteContent = false}) async { + static Future remove({@required String taskId, bool shouldDeleteContent = false}) async { assert(_initialized, 'FlutterDownloader.initialize() must be called first'); try { - return await _channel.invokeMethod('remove', - {'task_id': taskId, 'should_delete_content': shouldDeleteContent}); + return await _channel.invokeMethod('remove', {'task_id': taskId, 'should_delete_content': shouldDeleteContent}); } on PlatformException catch (e) { print(e.message); return null; @@ -387,9 +381,7 @@ class FlutterDownloader { assert(_initialized, 'FlutterDownloader.initialize() must be called first'); final callbackHandle = PluginUtilities.getCallbackHandle(callback); - assert(callbackHandle != null, - 'callback must be a top-level or a static function'); - _channel.invokeMethod( - 'registerCallback', [callbackHandle.toRawHandle()]); + assert(callbackHandle != null, 'callback must be a top-level or a static function'); + _channel.invokeMethod('registerCallback', [callbackHandle.toRawHandle()]); } } diff --git a/lib/src/models.dart b/lib/src/models.dart index 4d08532c..57b7d397 100644 --- a/lib/src/models.dart +++ b/lib/src/models.dart @@ -41,20 +41,23 @@ class DownloadTask { final DownloadTaskStatus status; final int progress; final String url; + final String title; final String filename; final String savedDir; final int timeCreated; - DownloadTask( - {this.taskId, - this.status, - this.progress, - this.url, - this.filename, - this.savedDir, - this.timeCreated}); + DownloadTask({ + this.taskId, + this.status, + this.progress, + this.url, + this.title, + this.filename, + this.savedDir, + this.timeCreated, + }); @override String toString() => - "DownloadTask(taskId: $taskId, status: $status, progress: $progress, url: $url, filename: $filename, savedDir: $savedDir, timeCreated: $timeCreated)"; + "DownloadTask(taskId: $taskId, status: $status, progress: $progress, url: $url, title: $title, filename: $filename, savedDir: $savedDir, timeCreated: $timeCreated)"; }