fluttercommunity / fluttercommunity/flutter_downloader
Download callbacks not firing in production for some users
- Dominant language
- Kotlin
- Stars
- 940
- Forks
- 561
- Avg merge
- 1h 18m
- Merged PRs (30d)
- 1
Description
We're experiencing a critical issue where download callbacks are not being triggered on certain Android devices, specifically affecting multiple device brands including **Redmi, Vivo, Oppo, and OnePlus etc..**. This appears to be a broader compatibility issue across these manufacturers rather than being specific to particular models.
**Issue symptoms:**
- ✅ Downloads enqueue successfully via `FlutterDownloader.enqueue()`
- ✅ Download tasks appear in database with correct status when queried
- ❌ Registered callback function (`downloadCallback`) is never invoked
- ❌ Progress updates and completion notifications are completely lost
- ❌ Users see downloads stuck at 0% progress indefinitely
### Environment
- **flutter_downloader version**: `^1.11.8`
- Calling this in the `main.dart`
#### Initialization
```dart
// Called during app startup in main.dart
@pragma('vm:entry-point')
Future initializeBgDownloader() async {
await FlutterDownloader.initialize(debug: kDebugMode);
}
```
- This `BgDownloaderHost` is wrapper at the top level of App.
#### Callback Registration & Isolate Setup
```dart
class _BgDownloaderHostState extends State {
@override
void initState() {
super.initState();
bgDownloader = GetIt.I.get();
// First bind the background isolate
bgDownloader._startListening();
// Then register callback after isolate binding - recommended timing
FlutterDownloader.registerCallback(downloadCallback);
}
}
void _startListening({int attempt = 1}) {
// Prevent infinite retry loops - give up after 5 attempts
if (attempt > 5) {
logNonFatal("Port registration failed after 5 attempts");
return;
}
// Remove existing port mapping before registering
IsolateNameServer.removePortNameMapping('downloader_send_port');
// Register new port
final registrationSuccess = IsolateNameServer.registerPortWithName(
port.sendPort, 'downloader_send_port');
if (!registrationSuccess) {
_stopListening();
_startListening(attempt: attempt + 1); // Retry logic
return;
}
port.listen((dynamic data) async {
String id = data[0];
DownloadTaskStatus status = DownloadTaskStatus.fromInt(data[1]);
int progress = data[2];
_invokeListeners(id, status, progress);
});
}
bool isCallbackRegistered() {
return PluginUtilities.getCallbackHandle(downloadCallback) != null;
}
```
#### Download Callback Function
```dart
@pragma('vm:entry-point')
Future downloadCallback(String id, int status, int progress) async {
try {
final SendPort? send = IsolateNameServer.lookupPortByName('downloader_send_port');
if (send == null) {
developer.log("SendPort lookup failed - progress update lost for task $id");
return;
}
send.send([id, status, progress]);
} catch (e, st) {
developer.log("$e", name: "DownloadCallback", level: 1200, stackTrace: st);
}
}
```
### Additional Code
```dart
Future _saveDirectory() async {
Directory directory;
if (Platform.isAndroid) {
final path = await AndroidDownloadPath.downloadPath();
directory = Directory(path);
} else {
directory = await getApplicationDocumentsDirectory();
}
return directory;
}
final taskId = await FlutterDownloader.enqueue(
url: url,
savedDir: savedDir.absolute.path,
showNotification: false,
openFileFromNotification: true,
saveInPublicStorage: true,
fileName: fileName,
requiresStorageNotLow: false,
);
```
### 🔍 Diagnostic Information
Our comprehensive health checks reveal:
- ✅ `isCallbackRegistered()` returns `true` (callback handle exists)
- ✅ Port registration succeeds (`IsolateNameServer.registerPortWithName` returns `true`)
- ✅ Downloads are enqueued successfully and appear in database
Any insights or potential fixes would be greatly appreciated. We're happy to provide additional debugging information or test potential solutions.
---
**Labels**: `bug`, `android`, `callback`, `isolate-communication`
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.