My class:
import 'dart:isolate';
import 'dart:ui';
import 'package:flutter_downloader/flutter_downloader.dart';
class SettingsPage extends StatefulWidget with WidgetsBindingObserver {
SettingsPage({Key? key}) : super(key: key);
@override
State<SettingsPage> createState() => _SettingsPageState();
}
class _SettingsPageState extends State<SettingsPage> {
final ReceivePort _port = ReceivePort();
int uploadProgress = 0;
// (-1)
DownloadTaskStatus uploadStatus = DownloadTaskStatus(-1);
String identifier = '';
get downloadsPath =>
storage.read('downloadsPath') ?? AndroidPathProvider.downloadsPath;
@override
void initState() {
super.initState();
_bindBackgroundIsolate();
FlutterDownloader.registerCallback(downloadCallback);
}
@override
void dispose() {
_unbindBackgroundIsolate();
super.dispose();
}
void _bindBackgroundIsolate() {
final isSuccess = IsolateNameServer.registerPortWithName(
_port.sendPort, 'downloader_send_port');
simplelog.i('regPort: $isSuccess');
if (!isSuccess) {
_unbindBackgroundIsolate();
_bindBackgroundIsolate();
return;
}
///Listening for the data is comming other isolataes
simplelog.i('before listen');
_port.listen((dynamic data) {
simplelog.i('in listen');
final String _id = data[0];
final DownloadTaskStatus _status = data[1];
final int _progress = data[2];
simplelog.i(
'Callback on UI isolate: '
'task ($_id) is in status ($_status) and process ($_progress)',
);
setState(() {
uploadProgress = _progress;
uploadStatus = _status;
simplelog.i('inside setState');
});
simplelog.i(
'uploadProgress = $uploadProgress \n uploadStatus = $uploadStatus \n uploadStatus.value = ${uploadStatus.value}');
if (uploadProgress == 100 &&
uploadStatus == DownloadTaskStatus.complete &&
uploadStatus.value == 3) {
try {
OpenFilex.open('$downloadsPath/${Consts.apkName}');
} catch (e) {
simplelog.e('Cannot open file ${Consts.apkName}! \n $e');
}
}
}, onError: (err) {
simplelog.e('ISOLATE LISTEN ERROR: $err');
},
onDone: () {
simplelog.i('onDone listen');
});
}
void _unbindBackgroundIsolate() {
IsolateNameServer.removePortNameMapping('downloader_send_port');
}
@pragma('vm:entry-point')
static void downloadCallback(
String id,
DownloadTaskStatus status,
int progress,
) {
simplelog.i('Callback on background isolate: '
'task ($id) is in status ($status) and progress ($progress)');
IsolateNameServer.lookupPortByName('downloader_send_port')
?.send([id, status, progress]);
}
In case with dowloadCallback
all work good,
but in case _port.listen()
, I don't get any data (simplelog = print, it nothing to show me, work only case simplelog.i('before listen');
In init() method register callback, this prints works good, and file success downloaded
How I can solve this problem?
Tried to play around with opening and closing ports using Compiler
This problem came with an inappropriate type parameter sent by send(...)
.
Step 1: Change status
to primitive status.value
IsolateNameServer.lookupPortByName('downloader_send_port')
?.send([id, status.value, progress]);
Step 2: Convert the int back to a DownloadTaskStatus
after receiving it.
_port.listen((dynamic data) {
···
final DownloadTaskStatus _status = DownloadTaskStatus(data[1] as int);
···
}
You can see more detailed examples from the author's GitHub repo.