flutterfire
flutterfire copied to clipboard
🐛 [firebase_storage] uploading in foreground service stops once app closes
Bug report
Describe the bug
- I'm using flutter_background_service to start uploading and sync my files to firebase_storage even when app closed.
- The uploading is working fine while app and foreground service are running , once I close the app the uploading is being canceled and the foreground service is still running .
- Then this was printed in logs.
D/UploadTask(20779): Increasing chunk size to 2097152
E/StorageException(20779): StorageException has occurred.
E/StorageException(20779): The operation was cancelled.
E/StorageException(20779): Code: -13040 HttpResult: 0
W/NetworkRequest(20779): No App Check token for request.
Steps to reproduce
Steps to reproduce the behavior:
- two TODOs in sample app :
- replace the
bucket
name with yours - replace
filePath
with yours
- replace the
- run the sample project in
profile
mode to see the console logs - press
start
button , to start foreground service - press
upload
, to start uploading to Firebase storage - close the app and remove from recent menu.
- The uploading task will be canceled and the foreground process still running , check console:
D/UploadTask(20779): Increasing chunk size to 2097152
E/StorageException(20779): StorageException has occurred.
E/StorageException(20779): The operation was cancelled.
E/StorageException(20779): Code: -13040 HttpResult: 0
W/NetworkRequest(20779): No App Check token for request.
Expected behavior
The uploading task shouldn't be canceled , if the app is closed.
Sample project
https://github.com/HosamHasanRamadan/foreground_issue
Additional context
- Android issue
Flutter doctor
Run flutter doctor
and paste the output below:
Click To Expand
[✓] Flutter (Channel stable, 3.10.6, on macOS 13.3 22E252 darwin-arm64, locale en-EG)
• Flutter version 3.10.6 on channel stable at /Users/hosamhasan/fvm/versions/stable
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision f468f3366c (4 weeks ago), 2023-07-12 15:19:05 -0700
• Engine revision cdbeda788a
• Dart version 3.0.6
• DevTools version 2.23.1
[!] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
• Android SDK at /Users/hosamhasan/Library/Android/sdk
• Platform android-33, build-tools 34.0.0
• ANDROID_HOME = /Users/hosamhasan/Library/Android/sdk
• Java binary at: /Users/hosamhasan/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/223.8836.35.2231.10406996/Android Studio.app/Contents/jbr/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)
✗ Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 14.3)
• Xcode at /Applications/Xcode-14.3.0.app/Contents/Developer
• Build 14E222b
• CocoaPods version 1.12.1
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2022.2)
• Android Studio at /Users/hosamhasan/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/222.4459.24.2221.10121639/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
[✓] Android Studio (version 2022.3)
• Android Studio at /Users/hosamhasan/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/223.8836.35.2231.10406996/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)
[✓] IntelliJ IDEA Community Edition (version 2022.3)
• IntelliJ at /Users/hosamhasan/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/223.7571.182/IntelliJ IDEA CE.app
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
[✓] IntelliJ IDEA Community Edition (version 2023.1.3)
• IntelliJ at /Users/hosamhasan/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/231.9161.38/IntelliJ IDEA CE.app
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
[✓] VS Code (version 1.81.0)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.70.0
[✓] Connected device (3 available)
• Lenovo TB 8505FS (mobile) • HA16YBY9 • android-arm64 • Android 10 (API 29)
• macOS (desktop) • macos • darwin-arm64 • macOS 13.3 22E252 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 115.0.5790.170
[✓] Network resources
• All expected network resources are available.
! Doctor found issues in 1 category.
Flutter dependencies
Run flutter pub deps -- --style=compact
and paste the output below:
Click To Expand
Dart SDK 3.0.6
Flutter SDK 3.10.6
fb_bg_issue 0.1.0
dependencies:
- firebase_auth 4.7.2 [firebase_auth_platform_interface firebase_auth_web firebase_core firebase_core_platform_interface flutter meta]
- firebase_core 2.15.0 [firebase_core_platform_interface firebase_core_web flutter meta]
- firebase_storage 11.2.5 [firebase_core firebase_core_platform_interface firebase_storage_platform_interface firebase_storage_web flutter]
- flutter 0.0.0 [characters collection js material_color_utilities meta vector_math sky_engine]
- flutter_background_service 4.0.0 [flutter flutter_background_service_platform_interface flutter_background_service_android flutter_background_service_ios]
- path_provider 2.1.0 [flutter path_provider_android path_provider_foundation path_provider_linux path_provider_platform_interface path_provider_windows]
dev dependencies:
- flutter_lints 2.0.2 [lints]
- flutter_test 0.0.0 [flutter test_api path fake_async clock stack_trace vector_math async boolean_selector characters collection js matcher material_color_utilities meta source_span stream_channel string_scanner term_glyph]
transitive dependencies:
- _flutterfire_internals 1.3.4 [collection firebase_core firebase_core_platform_interface flutter meta]
- async 2.11.0 [collection meta]
- boolean_selector 2.1.1 [source_span string_scanner]
- characters 1.3.0
- clock 1.1.1
- collection 1.17.1
- fake_async 1.3.1 [clock collection]
- ffi 2.1.0
- firebase_auth_platform_interface 6.16.1 [_flutterfire_internals collection firebase_core flutter meta plugin_platform_interface]
- firebase_auth_web 5.6.2 [firebase_auth_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins http_parser js meta]
- firebase_core_platform_interface 4.8.0 [collection flutter flutter_test meta plugin_platform_interface]
- firebase_core_web 2.6.0 [firebase_core_platform_interface flutter flutter_web_plugins js meta]
- firebase_storage_platform_interface 4.4.4 [collection firebase_core flutter meta plugin_platform_interface]
- firebase_storage_web 3.6.5 [_flutterfire_internals async firebase_core firebase_core_web firebase_storage_platform_interface flutter flutter_web_plugins http js meta]
- flutter_background_service_android 5.0.0 [flutter flutter_background_service_platform_interface]
- flutter_background_service_ios 4.0.0 [flutter flutter_background_service_platform_interface]
- flutter_background_service_platform_interface 4.0.0 [flutter platform plugin_platform_interface]
- flutter_web_plugins 0.0.0 [flutter js characters collection material_color_utilities meta vector_math]
- http 1.1.0 [async http_parser meta]
- http_parser 4.0.2 [collection source_span string_scanner typed_data]
- js 0.6.7 [meta]
- lints 2.1.1
- matcher 0.12.15 [async meta stack_trace term_glyph test_api]
- material_color_utilities 0.2.0
- meta 1.9.1
- path 1.8.3
- path_provider_android 2.1.0 [flutter path_provider_platform_interface]
- path_provider_foundation 2.3.0 [flutter path_provider_platform_interface]
- path_provider_linux 2.2.0 [ffi flutter path path_provider_platform_interface xdg_directories]
- path_provider_platform_interface 2.1.0 [flutter platform plugin_platform_interface]
- path_provider_windows 2.2.0 [ffi flutter path path_provider_platform_interface win32]
- platform 3.1.0
- plugin_platform_interface 2.1.5 [meta]
- sky_engine 0.0.99
- source_span 1.9.1 [collection path term_glyph]
- stack_trace 1.11.0 [path]
- stream_channel 2.1.1 [async]
- string_scanner 1.2.0 [source_span]
- term_glyph 1.2.1
- test_api 0.5.1 [async boolean_selector collection meta source_span stack_trace stream_channel string_scanner term_glyph matcher]
- typed_data 1.3.2 [collection]
- vector_math 2.1.4
- win32 5.0.6 [ffi]
- xdg_directories 1.0.2 [meta path]
Thanks for the report @HosamHasanRamadan Is there a way to replicate the same behavior without using the flutter_background_service package which is third party ? This is just to confirm and narrow down the reported behavior is specific to firebase_storage or has dependency with the third party package used.
Thanks @darshankawar for your response. Unfortunately , I need to use foreground service to reproduce this issue . There is another use case that leads to the same issue . I added it to the sample repo: Steps to reproduce it:
- two TODOs in sample app :
- replace the
bucket
name with yours - replace
filePath
with yours
- replace the
- run the sample project in
profile
mode to see the console logs - press
start
button , to start foreground service - press
delayed upload
, to start uploading to Firebase storage after 10 secs - close the app and remove from recent menu.
- Wait for the uploading to start after 10 secs
- open the app while uploading
- then close the app while uploading
- uploading task will be canceled with the same message in console
E/StorageException(20779): StorageException has occurred.
E/StorageException(20779): The operation was cancelled.
E/StorageException(20779): Code: -13040 HttpResult: 0
And sometimes I get this line in console:
W/StorageTask( 8037): unable to change internal state to: INTERNAL_STATE_IN_PROGRESS isUser: false from state:INTERNAL_STATE_CANCELING
Thanks for the feedback. Using the repo and steps to replicate, I do see the same behavior / error log as reported, but I am not sure if this need to be handled by the plugin or at native side.
hey @HosamHasanRamadan - I don't understand, if the app is closed, the expectation should be that the upload task is cancelled, not completed.
Hey @russellwheatley The upload task shouldn't be canceled if the upload task started in foreground service that keeps running event if the app is closed. The problem is, when I close the app , the upload task will be canceled and the foreground service still up and running.
@HosamHasanRamadan - I think I understand your problem. When you close the app, the Firebase services will be shutdown and all tasks in progress will be cancelled. If you want to restart the Firebase services and upload, I believe you would have to start the upload again. The problem is, background service are supposed to be a short lived operation (i.e. fire a notification to the user, not uploading files). I'm not sure what you want is advisable. Much better to fire a request to a server to perform the operation than to attempt from background and drain the resources of the device when the user has specifically closed the app.
@russellwheatley
I believe you would have to start the upload again.
Yes, I have a code in the foreground service that checks the upload progress if stuck or canceled.
Much better to fire a request to a server to perform the operation than to attempt from background and drain the resources of the device when the user has specifically closed the app.
- I have a long-running foreground service that can last for 8+ hours, I do a lot of things in this service and the user aware of the running service from sticky notification.
- Also if I am uploading 10mb file that won't drain the battery, the task will be canceled if user closes the app
What is the best way to upload a file to Firebase and keeps running even when the app is closed ?
@HosamHasanRamadan did you found the solution !
What is the best way to upload a file to Firebase and keeps running even when the app is closed ?
@HosamHasanRamadan - when the app is terminated either by the user or by the system, the Firebase plugins on FlutterFire are cleaned up. If the app is just in the background and it hasn't been terminated by the system, the FlutterFire plugins should still work as intended. You should design your app appropriately with these considerations in mind.
Hey @HosamHasanRamadan. We need more information to resolve this issue but there hasn't been an update in 7 weekdays. I'm marking the issue as stale and if there are no new updates in the next 7 days I will close it automatically.
If you have more information that will help us get to the bottom of this, just add a comment!
@russellwheatley So It's impossible to use foreground service for uploading data to Firebase Storage while app is closed ?
@HosamHasanRamadan - The firebase plugins will be cleaned up when the app is terminated. This needs to be kept in mind when designing your app. Closing as this isn't a bug.
Hello I'm getting the same error but when the upload complete the TaskState
doesn't changeto TaskState.success
The error I get :
unable to change internal state to: INTERNAL_STATE_CANCELED, INTERNAL_STATE_CANCELING isUser: true from state:INTERNAL_STATE_SUCCESS
the upload function :
Future<Either<Failure, UploadTask>> uploadAssessmentVideo({
required File video,
required String patientId,
required AssessmentResult assessmentResult,
}) async {
try {
if (await networkInfo.isConnected) {
debugPrint('Uploading video');
final storage = FirebaseStorage.instance;
final fileName =
'${assessmentResult.id}_${patientId}_${assessmentResult.createdAt.toIso8601String()}.mp4';
final ref = storage.ref().child('assessments/$fileName');
final UploadTask uploadTask = ref.putFile(
video,
SettableMetadata(contentType: 'video/mp4', customMetadata: {
'patientId': patientId,
'date': assessmentResult.createdAt.toIso8601String(),
}),
);
return Right(uploadTask);
} else {
throw NoInternetException('no-internet');
}
} catch (e) {
debugPrint('Error: $e');
return Left(Failure(e.toString()));
}
}
The controller i use to control the UI state :
uploadAssessmentVideo({
required File video,
required String patientId,
required AssessmentResult assessmentResult,
}) async {
change(TaskState.running, status: RxStatus.success());
final result = await assessmentsRepository.uploadAssessmentVideo(
video: video,
patientId: patientId,
assessmentResult: assessmentResult,
);
result.fold(
(l) {
Get.snackbar(
'Error',
l.message,
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red,
colorText: Colors.white,
);
},
(r) {
r.snapshotEvents.listen(
(event) {
if (state == TaskState.running) {
debugPrint('Uploading: $percentage%');
percentage.value =
(event.bytesTransferred * 100 ~/ event.totalBytes).toInt();
} else if (state == TaskState.success) {
debugPrint('Upload success');
_updateAssessmentReuslt(event, assessmentResult, patientId)
.then((value) {
change(TaskState.success);
});
} else if (state == TaskState.error) {
debugPrint('Upload failed');
change(TaskState.error);
}
update();
},
);
r.then(
(value) async {},
);
},
);
}