|
...
|
...
|
@@ -4,6 +4,7 @@ import 'dart:ui'; |
|
|
|
|
|
|
|
import 'package:common_utils/common_utils.dart';
|
|
|
|
import 'package:device_info/device_info.dart';
|
|
|
|
import 'package:dio/dio.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_picker/Picker.dart';
|
|
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
...
|
...
|
@@ -14,12 +15,14 @@ import 'package:one_key/widgets/v_empty_view.dart'; |
|
|
|
import 'package:path_provider/path_provider.dart';
|
|
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
|
|
|
|
|
|
import '../../../../net/dio_util.dart';
|
|
|
|
import '../../../../utils/dialog_util.dart';
|
|
|
|
import '../../../../utils/screen_util.dart';
|
|
|
|
import '../../../../utils/utils.dart';
|
|
|
|
import '../../../../widgets/h_empty_view.dart';
|
|
|
|
import 'package:flutter_downloader/flutter_downloader.dart';
|
|
|
|
import 'package:android_path_provider/android_path_provider.dart';
|
|
|
|
import 'package:open_file/open_file.dart';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 导出预订数据
|
|
...
|
...
|
@@ -51,14 +54,130 @@ class _ExportBookDataPageState extends State<ExportBookDataPage> { |
|
|
|
void initState() {
|
|
|
|
super.initState();
|
|
|
|
|
|
|
|
_bindBackgroundIsolate();
|
|
|
|
// IsolateNameServer.registerPortWithName(
|
|
|
|
// _port.sendPort, 'downloader_send_port');
|
|
|
|
// _port.listen((dynamic data) {
|
|
|
|
// taskId = data[0];
|
|
|
|
// status = DownloadTaskStatus(data[1]);
|
|
|
|
// progress = data[2];
|
|
|
|
// setState(() {});
|
|
|
|
// if (status == DownloadTaskStatus.undefined) {
|
|
|
|
// // _requestDownload(task);
|
|
|
|
// } else if (status == DownloadTaskStatus.running) {
|
|
|
|
// // _pauseDownload(task);
|
|
|
|
// // setState(() {});
|
|
|
|
// } else if (status == DownloadTaskStatus.paused) {
|
|
|
|
// // _resumeDownload(task);
|
|
|
|
// // setState(() {});
|
|
|
|
// } else if (status == DownloadTaskStatus.complete ||
|
|
|
|
// status == DownloadTaskStatus.canceled) {
|
|
|
|
// // _delete(task);
|
|
|
|
|
|
|
|
FlutterDownloader.registerCallback(downloadCallback, step: 1);
|
|
|
|
// // 显示是否打开的对话框
|
|
|
|
|
|
|
|
// DialogUtil.cupertinoAlertDialog(context,
|
|
|
|
// title: '提示',
|
|
|
|
// content: '文件下载完成,是否打开?',
|
|
|
|
// lTitle: '取消',
|
|
|
|
// rTitle: '打开', lCallback: () {
|
|
|
|
// Navigator.pop(context);
|
|
|
|
// }, rCallback: () async {
|
|
|
|
// // Navigator.pop(context);
|
|
|
|
|
|
|
|
// print(_localPath);
|
|
|
|
|
|
|
|
// final tasks = await FlutterDownloader.loadTasks();
|
|
|
|
// String str = '';
|
|
|
|
// tasks.forEach((element) {
|
|
|
|
// str = element.savedDir + '/' + element.filename;
|
|
|
|
// });
|
|
|
|
// print(str);
|
|
|
|
|
|
|
|
// if (str != '') {
|
|
|
|
// OpenFile.open(str);
|
|
|
|
// _delete();
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
// // showDialog(
|
|
|
|
// // // 设置点击 dialog 外部不取消 dialog,默认能够取消
|
|
|
|
// // barrierDismissible: false,
|
|
|
|
// // context: context,
|
|
|
|
// // builder: (context) => AlertDialog(
|
|
|
|
// // title: Text('提示'),
|
|
|
|
// // // 标题文字样式
|
|
|
|
// // content: Text('文件下载完成,是否打开?'),
|
|
|
|
// // // 内容文字样式
|
|
|
|
// // backgroundColor: MyColours.color_ffffff,
|
|
|
|
// // elevation: 8.0,
|
|
|
|
// // // 投影的阴影高度
|
|
|
|
// // semanticLabel: 'Label',
|
|
|
|
// // // 这个用于无障碍下弹出 dialog 的提示
|
|
|
|
// // shape: Border.all(),
|
|
|
|
// // // dialog 的操作按钮,actions 的个数尽量控制不要过多,否则会溢出 `Overflow`
|
|
|
|
// // actions: <Widget>[
|
|
|
|
// // // 点击取消按钮
|
|
|
|
// // InkWell(
|
|
|
|
// // onTap: () => Navigator.pop(context), child: Text('取消')),
|
|
|
|
// // // 点击打开按钮
|
|
|
|
// // InkWell(
|
|
|
|
// // onTap: () async {
|
|
|
|
// // Navigator.pop(context);
|
|
|
|
|
|
|
|
// // print(_localPath);
|
|
|
|
|
|
|
|
// // final tasks = await FlutterDownloader.loadTasks();
|
|
|
|
// // String str = '';
|
|
|
|
// // tasks.forEach((element) {
|
|
|
|
// // str = element.savedDir + '/' + element.filename;
|
|
|
|
// // });
|
|
|
|
// // print(str);
|
|
|
|
// // if (str != '') {
|
|
|
|
// // OpenFile.open(str);
|
|
|
|
// // }
|
|
|
|
|
|
|
|
// // // 打开文件
|
|
|
|
// // // _openDownloadedFile(taskId).then((success) {
|
|
|
|
// // // if (!success) {
|
|
|
|
// // // Utils.showToast('Cannot open this file');
|
|
|
|
// // // // Scaffold.of(context).showSnackBar(SnackBar(
|
|
|
|
// // // // content: Text('Cannot open this file')));
|
|
|
|
// // // }
|
|
|
|
// // // });
|
|
|
|
// // },
|
|
|
|
// // child: Text('打开')),
|
|
|
|
// // ],
|
|
|
|
// // ));
|
|
|
|
// } else if (status == DownloadTaskStatus.failed) {
|
|
|
|
// // _retryDownload(task);
|
|
|
|
// Utils.showToast('下载异常,请稍后重试');
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
|
|
|
|
// FlutterDownloader.registerCallback(downloadCallback);
|
|
|
|
|
|
|
|
// // _bindBackgroundIsolate();
|
|
|
|
|
|
|
|
// // FlutterDownloader.registerCallback(downloadCallback, step: 1);
|
|
|
|
// _delete();
|
|
|
|
}
|
|
|
|
|
|
|
|
// _preae() async {
|
|
|
|
// final tasks = await FlutterDownloader.loadTasks();
|
|
|
|
|
|
|
|
// if (tasks == null) {
|
|
|
|
// print('No tasks were retrieved from the database.');
|
|
|
|
// return;
|
|
|
|
// } else {
|
|
|
|
// tasks.forEach((element) {
|
|
|
|
// FlutterDownloader.remove(
|
|
|
|
// taskId: element.taskId, shouldDeleteContent: false);
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
@override
|
|
|
|
void dispose() {
|
|
|
|
_unbindBackgroundIsolate();
|
|
|
|
// _unbindBackgroundIsolate();
|
|
|
|
super.dispose();
|
|
|
|
}
|
|
|
|
|
|
...
|
...
|
@@ -68,13 +187,9 @@ class _ExportBookDataPageState extends State<ExportBookDataPage> { |
|
|
|
int status,
|
|
|
|
int progress,
|
|
|
|
) {
|
|
|
|
print(
|
|
|
|
'Callback on background isolate: '
|
|
|
|
'task ($id) is in status ($status) and process ($progress)',
|
|
|
|
);
|
|
|
|
|
|
|
|
IsolateNameServer.lookupPortByName('downloader_send_port')
|
|
|
|
?.send([id, status, progress]);
|
|
|
|
final SendPort send =
|
|
|
|
IsolateNameServer.lookupPortByName('downloader_send_port');
|
|
|
|
send.send([id, status, progress]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 根据taskId打开下载文件
|
|
...
|
...
|
@@ -82,75 +197,89 @@ class _ExportBookDataPageState extends State<ExportBookDataPage> { |
|
|
|
return FlutterDownloader.open(taskId: taskId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void _bindBackgroundIsolate() {
|
|
|
|
final isSuccess = IsolateNameServer.registerPortWithName(
|
|
|
|
_port.sendPort,
|
|
|
|
'downloader_send_port',
|
|
|
|
);
|
|
|
|
if (!isSuccess) {
|
|
|
|
_unbindBackgroundIsolate();
|
|
|
|
_bindBackgroundIsolate();
|
|
|
|
return;
|
|
|
|
// void _bindBackgroundIsolate() {
|
|
|
|
// final isSuccess = IsolateNameServer.registerPortWithName(
|
|
|
|
// _port.sendPort,
|
|
|
|
// 'downloader_send_port',
|
|
|
|
// );
|
|
|
|
// if (!isSuccess) {
|
|
|
|
// _unbindBackgroundIsolate();
|
|
|
|
// _bindBackgroundIsolate();
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
// _port.listen((dynamic data) {
|
|
|
|
// taskId = (data as List<dynamic>)[0] as String;
|
|
|
|
// status = DownloadTaskStatus(data[1] as int);
|
|
|
|
// progressT = data[2] as int;
|
|
|
|
|
|
|
|
// print(
|
|
|
|
// 'Callback on UI isolate: '
|
|
|
|
// 'task ($taskId) is in status ($status) and process ($progressT)',
|
|
|
|
// );
|
|
|
|
// if (status == DownloadTaskStatus.undefined) {
|
|
|
|
// // _requestDownload(task);
|
|
|
|
// } else if (status == DownloadTaskStatus.running) {
|
|
|
|
// // _pauseDownload(task);
|
|
|
|
// setState(() {});
|
|
|
|
// } else if (status == DownloadTaskStatus.paused) {
|
|
|
|
// // _resumeDownload(task);
|
|
|
|
// setState(() {});
|
|
|
|
// } else if (status == DownloadTaskStatus.complete ||
|
|
|
|
// status == DownloadTaskStatus.canceled) {
|
|
|
|
// // _delete(task);
|
|
|
|
// // 显示是否打开的对话框
|
|
|
|
// showDialog(
|
|
|
|
// // 设置点击 dialog 外部不取消 dialog,默认能够取消
|
|
|
|
// barrierDismissible: false,
|
|
|
|
// context: context,
|
|
|
|
// builder: (context) => AlertDialog(
|
|
|
|
// title: Text('提示'),
|
|
|
|
// // 标题文字样式
|
|
|
|
// content: Text('文件下载完成,是否打开?'),
|
|
|
|
// // 内容文字样式
|
|
|
|
// backgroundColor: MyColours.color_ffffff,
|
|
|
|
// elevation: 8.0,
|
|
|
|
// // 投影的阴影高度
|
|
|
|
// semanticLabel: 'Label',
|
|
|
|
// // 这个用于无障碍下弹出 dialog 的提示
|
|
|
|
// shape: Border.all(),
|
|
|
|
// // dialog 的操作按钮,actions 的个数尽量控制不要过多,否则会溢出 `Overflow`
|
|
|
|
// actions: <Widget>[
|
|
|
|
// // 点击取消按钮
|
|
|
|
// InkWell(
|
|
|
|
// onTap: () => Navigator.pop(context), child: Text('取消')),
|
|
|
|
// // 点击打开按钮
|
|
|
|
// InkWell(
|
|
|
|
// onTap: () {
|
|
|
|
// Navigator.pop(context);
|
|
|
|
// // 打开文件
|
|
|
|
// _openDownloadedFile(taskId).then((success) {
|
|
|
|
// if (!success) {
|
|
|
|
// Utils.showToast('Cannot open this file');
|
|
|
|
// // Scaffold.of(context).showSnackBar(SnackBar(
|
|
|
|
// // content: Text('Cannot open this file')));
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
// },
|
|
|
|
// child: Text('打开')),
|
|
|
|
// ],
|
|
|
|
// ));
|
|
|
|
// } else if (status == DownloadTaskStatus.failed) {
|
|
|
|
// // _retryDownload(task);
|
|
|
|
// Utils.showToast('下载异常,请稍后重试');
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
Future<void> _delete() async {
|
|
|
|
final task = await FlutterDownloader.loadTasks();
|
|
|
|
if (task != null) {
|
|
|
|
task.forEach((element) {
|
|
|
|
FlutterDownloader.remove(
|
|
|
|
taskId: element.taskId,
|
|
|
|
shouldDeleteContent: true,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
_port.listen((dynamic data) {
|
|
|
|
taskId = (data as List<dynamic>)[0] as String;
|
|
|
|
status = DownloadTaskStatus(data[1] as int);
|
|
|
|
progress = data[2] as int;
|
|
|
|
|
|
|
|
print(
|
|
|
|
'Callback on UI isolate: '
|
|
|
|
'task ($taskId) is in status ($status) and process ($progress)',
|
|
|
|
);
|
|
|
|
if (status == DownloadTaskStatus.undefined) {
|
|
|
|
// _requestDownload(task);
|
|
|
|
} else if (status == DownloadTaskStatus.running) {
|
|
|
|
// _pauseDownload(task);
|
|
|
|
} else if (status == DownloadTaskStatus.paused) {
|
|
|
|
// _resumeDownload(task);
|
|
|
|
} else if (status == DownloadTaskStatus.complete ||
|
|
|
|
status == DownloadTaskStatus.canceled) {
|
|
|
|
// _delete(task);
|
|
|
|
// 显示是否打开的对话框
|
|
|
|
showDialog(
|
|
|
|
// 设置点击 dialog 外部不取消 dialog,默认能够取消
|
|
|
|
barrierDismissible: false,
|
|
|
|
context: context,
|
|
|
|
builder: (context) => AlertDialog(
|
|
|
|
title: Text('提示'),
|
|
|
|
// 标题文字样式
|
|
|
|
content: Text('文件下载完成,是否打开?'),
|
|
|
|
// 内容文字样式
|
|
|
|
backgroundColor: MyColours.color_ffffff,
|
|
|
|
elevation: 8.0,
|
|
|
|
// 投影的阴影高度
|
|
|
|
semanticLabel: 'Label',
|
|
|
|
// 这个用于无障碍下弹出 dialog 的提示
|
|
|
|
shape: Border.all(),
|
|
|
|
// dialog 的操作按钮,actions 的个数尽量控制不要过多,否则会溢出 `Overflow`
|
|
|
|
actions: <Widget>[
|
|
|
|
// 点击取消按钮
|
|
|
|
InkWell(
|
|
|
|
onTap: () => Navigator.pop(context), child: Text('取消')),
|
|
|
|
// 点击打开按钮
|
|
|
|
InkWell(
|
|
|
|
onTap: () {
|
|
|
|
Navigator.pop(context);
|
|
|
|
// 打开文件
|
|
|
|
_openDownloadedFile(taskId).then((success) {
|
|
|
|
if (!success) {
|
|
|
|
Utils.showToast('Cannot open this file');
|
|
|
|
// Scaffold.of(context).showSnackBar(SnackBar(
|
|
|
|
// content: Text('Cannot open this file')));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
child: Text('打开')),
|
|
|
|
],
|
|
|
|
));
|
|
|
|
} else if (status == DownloadTaskStatus.failed) {
|
|
|
|
// _retryDownload(task);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> _prepareSaveDir() async {
|
|
...
|
...
|
@@ -165,14 +294,14 @@ class _ExportBookDataPageState extends State<ExportBookDataPage> { |
|
|
|
String externalStorageDirPath;
|
|
|
|
|
|
|
|
if (Platform.isAndroid) {
|
|
|
|
try {
|
|
|
|
externalStorageDirPath = await AndroidPathProvider.downloadsPath;
|
|
|
|
} catch (err, st) {
|
|
|
|
print('failed to get downloads path: $err, $st');
|
|
|
|
// try {
|
|
|
|
// externalStorageDirPath = await AndroidPathProvider.downloadsPath;
|
|
|
|
// } catch (err, st) {
|
|
|
|
// print('failed to get downloads path: $err, $st');
|
|
|
|
|
|
|
|
final directory = await getExternalStorageDirectory();
|
|
|
|
externalStorageDirPath = directory?.path;
|
|
|
|
}
|
|
|
|
final directory = await getExternalStorageDirectory();
|
|
|
|
externalStorageDirPath = directory?.path;
|
|
|
|
// }
|
|
|
|
} else if (Platform.isIOS) {
|
|
|
|
externalStorageDirPath =
|
|
|
|
(await getApplicationDocumentsDirectory()).absolute.path;
|
|
...
|
...
|
@@ -186,10 +315,10 @@ class _ExportBookDataPageState extends State<ExportBookDataPage> { |
|
|
|
}
|
|
|
|
|
|
|
|
if (Platform.isAndroid) {
|
|
|
|
final info = await DeviceInfoPlugin().androidInfo;
|
|
|
|
if (info.version.sdkInt > 28) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// final info = await DeviceInfoPlugin().androidInfo;
|
|
|
|
// if (info.version.sdkInt > 28) {
|
|
|
|
// return true;
|
|
|
|
// }
|
|
|
|
|
|
|
|
final status = await Permission.storage.status;
|
|
|
|
if (status == PermissionStatus.granted) {
|
|
...
|
...
|
@@ -299,8 +428,14 @@ class _ExportBookDataPageState extends State<ExportBookDataPage> { |
|
|
|
// controller: controller,
|
|
|
|
child: Column(
|
|
|
|
children: [
|
|
|
|
(status == DownloadTaskStatus.running ||
|
|
|
|
status == DownloadTaskStatus.paused)
|
|
|
|
// (status == DownloadTaskStatus.running ||
|
|
|
|
// status == DownloadTaskStatus.paused)
|
|
|
|
// ? LinearProgressIndicator(
|
|
|
|
// value: progress / 100,
|
|
|
|
// )
|
|
|
|
// : VEmptyView(10),
|
|
|
|
|
|
|
|
progress != null && progress != 100
|
|
|
|
? LinearProgressIndicator(
|
|
|
|
value: progress / 100,
|
|
|
|
)
|
|
...
|
...
|
@@ -404,7 +539,9 @@ class _ExportBookDataPageState extends State<ExportBookDataPage> { |
|
|
|
),
|
|
|
|
VEmptyView(26),
|
|
|
|
RoundButton(
|
|
|
|
text: '导出数据',
|
|
|
|
text: (progress != null && progress != 100)
|
|
|
|
? '${progress}%'
|
|
|
|
: '导出数据',
|
|
|
|
width: w(218),
|
|
|
|
height: w(43),
|
|
|
|
gradientStart: MyColours.color_f3f3f3,
|
|
...
|
...
|
@@ -415,22 +552,86 @@ class _ExportBookDataPageState extends State<ExportBookDataPage> { |
|
|
|
fontSize: 32,
|
|
|
|
isBold: true,
|
|
|
|
onPressed: () async {
|
|
|
|
if (progress != null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool _permissionReady = await _checkPermission();
|
|
|
|
if (_permissionReady) {
|
|
|
|
await _prepareSaveDir();
|
|
|
|
}
|
|
|
|
taskId = await FlutterDownloader.enqueue(
|
|
|
|
url:
|
|
|
|
// _delete();
|
|
|
|
String savePath = _localPath + "/fff.pdf";
|
|
|
|
Directory directory = new Directory(savePath);
|
|
|
|
if (directory.existsSync()) {
|
|
|
|
//删除历史
|
|
|
|
final List<FileSystemEntity> files = directory.listSync();
|
|
|
|
for (FileSystemEntity file in files) {
|
|
|
|
file.deleteSync();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
Response response = await DioUtil().download(
|
|
|
|
'http://englishonlineclub.com/pdf/iOS%20Programming%20-%20The%20Big%20Nerd%20Ranch%20Guide%20(6th%20Edition)%20[EnglishOnlineClub.com].pdf',
|
|
|
|
headers: {
|
|
|
|
'auth': 'test_for_sql_encoding'
|
|
|
|
}, // optional: header send with url (auth token etc)
|
|
|
|
savedDir: _localPath,
|
|
|
|
showNotification:
|
|
|
|
true, // show download progress in status bar (for Android)
|
|
|
|
openFileFromNotification:
|
|
|
|
true, // click on notification to open downloaded file (for Android)
|
|
|
|
);
|
|
|
|
savePath, onProgress: (received, total) {
|
|
|
|
if (progress != 100) {
|
|
|
|
progress = ((received / total) * 100).round();
|
|
|
|
|
|
|
|
setState(() {});
|
|
|
|
}
|
|
|
|
if (received == total) {
|
|
|
|
//下载完成
|
|
|
|
print('xaizaiwancheng');
|
|
|
|
|
|
|
|
DialogUtil.cupertinoAlertDialog(context,
|
|
|
|
title: '提示',
|
|
|
|
content: '文件下载完成,是否打开?',
|
|
|
|
lTitle: '取消',
|
|
|
|
rTitle: '打开', lCallback: () {
|
|
|
|
progress = null;
|
|
|
|
setState(() {});
|
|
|
|
}, rCallback: () async {
|
|
|
|
// Navigator.pop(context);
|
|
|
|
|
|
|
|
// print(_localPath);
|
|
|
|
|
|
|
|
// final tasks = await FlutterDownloader.loadTasks();
|
|
|
|
// String str = '';
|
|
|
|
// tasks.forEach((element) {
|
|
|
|
// str = element.savedDir + '/' + element.filename;
|
|
|
|
// });
|
|
|
|
// print(str);
|
|
|
|
|
|
|
|
// if (str != '') {
|
|
|
|
print(savePath);
|
|
|
|
progress = null;
|
|
|
|
setState(() {});
|
|
|
|
OpenFile.open(savePath);
|
|
|
|
// _delete();
|
|
|
|
// }
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
print(response);
|
|
|
|
} catch (e) {
|
|
|
|
print(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
// taskId = await FlutterDownloader.enqueue(
|
|
|
|
// url:
|
|
|
|
// 'http://englishonlineclub.com/pdf/iOS%20Programming%20-%20The%20Big%20Nerd%20Ranch%20Guide%20(6th%20Edition)%20[EnglishOnlineClub.com].pdf',
|
|
|
|
// headers: {
|
|
|
|
// // 'auth': 'test_for_sql_encoding'
|
|
|
|
// }, // optional: header send with url (auth token etc)
|
|
|
|
// savedDir: _localPath,
|
|
|
|
// saveInPublicStorage: true,
|
|
|
|
// // fileName:
|
|
|
|
// // // showNotification:
|
|
|
|
// // // true, // show download progress in status bar (for Android)
|
|
|
|
// // openFileFromNotification:
|
|
|
|
// // true, // click on notification to open downloaded file (for Android)
|
|
|
|
// );
|
|
|
|
},
|
|
|
|
)
|
|
|
|
],
|
...
|
...
|
|