Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistency in AppLifecycleState Detection Between iOS and Android in Flutter Hooks #409

Closed
motucraft opened this issue Jan 6, 2024 · 5 comments
Assignees
Labels
bug Something isn't working needs triage

Comments

@motucraft
Copy link

Describe the bug
When transitioning a Flutter app to the background, the AppLifecycleState.paused state is not detected on Android devices, while it is correctly detected on iOS. On Android, the lifecycle only reaches AppLifecycleState.inactive, omitting the paused state. This inconsistency between platforms can lead to issues in handling app lifecycle states in Flutter applications using flutter_hooks.

To Reproduce

Use the following Flutter code to monitor app lifecycle states:

Sample Code
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: Sample());
  }
}

class Sample extends HookWidget {
  const Sample({super.key});

  @override
  Widget build(BuildContext context) {
    final appLifecycle = useAppLifecycleState();
    print('appLifecycle=$appLifecycle');
    return Scaffold(body: Center(child: Text('$appLifecycle')));
  }
}
pubspec.yaml
name: app_lifecycle
description: "A new Flutter project."
publish_to: 'none'
version: 1.0.0+1
environment:
  sdk: '>=3.2.3 <4.0.0'

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  hooks_riverpod: ^2.4.9
  flutter_hooks: ^0.20.4
  riverpod_annotation: ^2.3.3

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0
  riverpod_generator: ^2.3.9
  build_runner: ^2.4.7
  custom_lint: ^0.5.7
  riverpod_lint: ^2.3.7

flutter:
  uses-material-design: true
console(Android)
Launching lib/main.dart on sdk gphone64 arm64 in debug mode...
Running Gradle task 'assembleDebug'...
✓  Built build/app/outputs/flutter-apk/app-debug.apk.
Debug service listening on ws://127.0.0.1:50008/retjf42mpLQ=/ws
Syncing files to device sdk gphone64 arm64...
I/flutter ( 9338): appLifecycle=AppLifecycleState.resumed
I/flutter ( 9338): appLifecycle=AppLifecycleState.inactive
console(iOS)
Launching lib/main.dart on iPhone 15 Pro Max in debug mode...
Running Xcode build...
Xcode build done.                                           18.5s
Debug service listening on ws://127.0.0.1:64621/OFX7kmx7qO0=/ws
Syncing files to device iPhone 15 Pro Max...
flutter: appLifecycle=AppLifecycleState.resumed
flutter: appLifecycle=AppLifecycleState.inactive
flutter: appLifecycle=AppLifecycleState.paused
  1. Run the app on an iOS device and transition the app to the background. The console logs will correctly show the lifecycle states transitioning through resumed, inactive, and paused.
  2. Run the same app on an Android device and repeat the process. The console logs will only show resumed and inactive, missing the paused state.
appLifecycle.mov

Expected behavior
The expected behavior is that on both iOS and Android platforms, transitioning the app to the background should consistently trigger AppLifecycleState.resumed, AppLifecycleState.inactive, and AppLifecycleState.paused in that order.

@motucraft motucraft added bug Something isn't working needs triage labels Jan 6, 2024
@motucraft
Copy link
Author

motucraft commented Jan 6, 2024

Would the following issues be relevant?
flutter/flutter#114756

I would like to detect AppLifecycleState because I want to cancel the Firestore snapshot once the app has moved to the background. (I'm using cloud_firestore_odm and riverpod.)

@rrousselGit
Copy link
Owner

The expected behavior is that on both iOS and Android platforms, transitioning the app to the background should consistently trigger AppLifecycleState.resumed, AppLifecycleState.inactive, and AppLifecycleState.paused in that order.

It is not possible to make this guarantee
Flutter decides when it invoked build. It could very well be that two life-cycle changes happen at once, before build could be invoked.
This would swallow the first event.

@motucraft
Copy link
Author

I see, thanks your reply.

I would like to detect AppLifecycleState because I want to cancel the Firestore snapshot once the app has moved to the background. (I'm using cloud_firestore_odm and riverpod.)

Any ideas on this?

@rrousselGit
Copy link
Owner

You could use useOnAppLifecycleStateChange

@motucraft
Copy link
Author

That build may not be called means that it can only be handled within a callback, right?
I decided to respond in this way.

    useOnAppLifecycleStateChange((_, current) {
      switch (current) {
        case AppLifecycleState.resumed || AppLifecycleState.inactive:
          FirebaseFirestore.instance.enableNetwork();
          break;
        default:
          FirebaseFirestore.instance.disableNetwork();
      }
    });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs triage
Projects
None yet
Development

No branches or pull requests

2 participants