plus_plugins icon indicating copy to clipboard operation
plus_plugins copied to clipboard

[connectivity_plus] Opening the application causes onConnectivityChanged to emit two events

Open cal-g opened this issue 2 years ago β€’ 22 comments

System info

Platform the Issue occurs on: iOS Plugin name: connectivity_plus Plugin version: 2.2.1

Steps to Reproduce

Demo code increments counter when connection is changed to Wifi. Link to gist

  1. Run the gist code on a simulator or real device

When the app is opened the onConnectivityChanged emits two events instead of just one. On Android it correctly emits just one event. I'm guessing this can be a bug on the iOS. The video attached is the release build of the demo gist on a iPhone 8

Since, there are 2 events emitted the counter increments 2 times if WiFi is turned on and 2 is displayed when the app is opened. There are 2 events emitted even if Wifi and Data is turned off.

Expected: Only one event should be emitted.

https://user-images.githubusercontent.com/98470469/158479544-e5a1fa9a-45b5-47db-8bf0-578ad3ab67fd.mp4

Running in debug mode on iOS Simulator. "Got a new connectivity status! ::wifi" is printed twice. Logs
Launching lib/main.dart on iPhone SE (3rd generation) in debug mode...
Running Xcode build...                                                  
 └─Compiling, linking and signing...                         3.5s
Xcode build done.                                            9.6s
flutter: initState
flutter: Got a new connectivity status!  ::wifi
flutter: Got a new connectivity status!  ::wifi
Syncing files to device iPhone SE (3rd generation)...              214ms

Flutter run key commands.
r Hot reload. πŸ”₯πŸ”₯πŸ”₯
R Hot restart.
h List all available interactive commands.
d Detach (terminate "flutter run" but leave application running).
c Clear the screen
q Quit (terminate the application on the device).

πŸ’ͺ Running with sound null safety πŸ’ͺ
Flutter doctor output
βœ“] Flutter (Channel stable, 2.10.3, on macOS 12.2.1 21D62 darwin-x64, locale en-CA)
    β€’ Flutter version 2.10.3 at /Users/calvin.gonsalves/Desktop/development/flutter
    β€’ Upstream repository https://github.com/flutter/flutter.git
    β€’ Framework revision 7e9793dee1 (13 days ago), 2022-03-02 11:23:12 -0600
    β€’ Engine revision bd539267b4
    β€’ Dart version 2.16.1
    β€’ DevTools version 2.9.2

[βœ“] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
    β€’ Android SDK at /Users/calvin.gonsalves/Library/Android/sdk
    β€’ Platform android-31, build-tools 31.0.0
    β€’ Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    β€’ Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
    β€’ All Android licenses accepted.

[βœ“] Xcode - develop for iOS and macOS (Xcode 13.3)
    β€’ Xcode at /Applications/Xcode.app/Contents/Developer
    β€’ CocoaPods version 1.11.2

[βœ“] Chrome - develop for the web
    β€’ Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[βœ“] Android Studio (version 2021.1)
    β€’ Android Studio at /Applications/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 11.0.11+0-b60-7590822)

[βœ“] VS Code (version 1.65.2)
    β€’ VS Code at /Applications/Visual Studio Code.app/Contents
    β€’ Flutter extension version 3.37.20220301

[βœ“] Connected device (1 available)
    β€’ Chrome (web) β€’ chrome β€’ web-javascript β€’ Google Chrome 99.0.4844.51

[βœ“] HTTP Host Availability
    β€’ All required HTTP hosts are available

β€’ No issues found!

cal-g avatar Mar 15 '22 22:03 cal-g

I stumbled on this issue by chance and tested it with https://github.com/fluttercommunity/plus_plugins/pull/791 Same result, first event is ConnectivityResult.none and second is ConnectivityResult.wifi.

kuhnroyal avatar Mar 16 '22 09:03 kuhnroyal

I think I fixed this in e0d37a4 (#791) except for hot restarts

kuhnroyal avatar Mar 16 '22 17:03 kuhnroyal

closing, if the issue reappears please say so here and I will reopen the issue

miquelbeltran avatar Apr 12 '22 08:04 miquelbeltran

I have tested the recently published version v2.3.0 and I also tested PR 791 and I'm still facing the same issue. The commit I specifically tested from PR 791 was:

connectivity_plus: #^2.3.0
    git:
      url: https://github.com/kuhnroyal/plus_plugins
      path: packages/connectivity_plus/connectivity_plus
      ref: d7b83c425f63a049d5195df99848c33a9eb1e894

luis901101 avatar Apr 19 '22 22:04 luis901101

@luis901101 On which iOS version did you test? The line which can potentially cause double emit is still there: https://github.com/fluttercommunity/plus_plugins/blob/main/packages/connectivity_plus/connectivity_plus/ios/Classes/SwiftConnectivityPlusPlugin.swift#L67

I remember this also being a timing issue. In my test app on iOS 15 I only had one event. Removing the line sometimes leads to no initial event being fired.

Will try to test this again.

kuhnroyal avatar Apr 19 '22 23:04 kuhnroyal

Also this may play a role here: https://github.com/fluttercommunity/plus_plugins/pull/791#issuecomment-1069385002

kuhnroyal avatar Apr 19 '22 23:04 kuhnroyal

Tested in iOS 15.3.1 and 15.4.1

luis901101 avatar Apr 19 '22 23:04 luis901101

@kuhnroyal @miquelbeltran

I also have the same issue on iOS. When listening to the onConnectivityChanged or when connectivity changes, the onConnectivityChanged will be emitted twice with ConnectivityResult.none as the first value.

838 avatar Apr 25 '22 15:04 838

Reopened. Just to be sure, is this a big issue if you receive two events? How is that affecting your code? (just want to understand better the scope of this problem)

miquelbeltran avatar May 03 '22 07:05 miquelbeltran

@838 Which iOS version and did the same happen before the 2.3.0 release?

kuhnroyal avatar May 03 '22 09:05 kuhnroyal

@miquelbeltran In my case, I'm checking the connectivity state on every AppLifecycleState.resumed and for a very short time the app will show a offline page if I don't skip the first emit.

@kuhnroyal The iOS version is 15.4.1. I have tested the 2.2.2 and 2.2.1 releases and have the same issue, but if I'm connected to WIFI then onConnectivityChanged emits ConnectivityResult.wifi twice. In 2.3.0 the first emit is always ConnectivityResult.none.

838 avatar May 03 '22 17:05 838

@838 This is likely due to https://github.com/fluttercommunity/plus_plugins/pull/791#issuecomment-1069385002 My suggestion in that comment would probably fix this. What I do to circumvent this is an await checkConnection() and start the stream afterwards, discarding the first event.

kuhnroyal avatar May 03 '22 18:05 kuhnroyal

@kuhnroyal calling await checkConnection() before start the stream doesn't change anything with double emit 😟 for iOS.

Also check on Android and there onConnectivityChanged emits one event as expected.

ycherniavskyi avatar May 06 '22 13:05 ycherniavskyi

Just fallback to old ReachabilityConnectivityProvider by commented PathMonitorConnectivityProvider within plugin source code and event emit one time as expected.

Also create stub SwiftUI app with next initial block:

        let monitor = NWPathMonitor()
        monitor.pathUpdateHandler = { path in
            print(path)
        }
        let queue = DispatchQueue.global(qos: .background)
        monitor.start(queue: queue)

and also get double handle calls with identical path objects (at last from its public fields view).

My current iOS version is 15.4.1.

πŸ€·πŸ»β€β™‚οΈ

ycherniavskyi avatar May 07 '22 10:05 ycherniavskyi

Same issue. [2.3.5]

LarYoungruu avatar Jun 27 '22 03:06 LarYoungruu

I am also getting two initial events 90% of the time, but sometimes there is only one... Gonna try a couple things and will test with my suggestion from https://github.com/fluttercommunity/plus_plugins/pull/791#issuecomment-1069385002

kuhnroyal avatar Jun 30 '22 14:06 kuhnroyal

So it seems the NWPathMonitor .pathUpdaterHandler can be called multiple times with the same path. According to discussions on the apple community board, your app needs to be resilient against multiple invocations. This can happen on app start or even while the app is running and you lose connectivity.

There may still be ways to reduce the chance of this happening on app start but I don't think it can be prevent completely.

kuhnroyal avatar Aug 05 '22 13:08 kuhnroyal

What's a fantastic Apple API. Does this board explain what the reason for these multiple invocations is? Does it indicate something valuable (some interface updated, but I can't see any property changes when debugging it)?

In any case, what do you think about adding multiple invocations handling in connectivity_plus plugin and putting only different ConnectivityResult in onConnectivityChanged?

ycherniavskyi avatar Aug 06 '22 12:08 ycherniavskyi

In any case, what do you think about adding multiple invocations handling in connectivity_plus plugin and putting only different ConnectivityResult in onConnectivityChanged?

I thought about this but that is rather hard to do correct. Like changing from one wifi to another wifi network will result in 2 wifi events.

Maybe it can be done with a very limited timeframe check but it will not completely guard you from those events. You need to handle the meaning of this on your side, especially if you want to do more than just a connectivity check.

kuhnroyal avatar Aug 06 '22 15:08 kuhnroyal

Does it indicate something valuable (some interface updated, but I can't see any property changes when debugging it)?

Yes I have noticed the same thing, but the objects are not comparable so that I can filter them out. Could probably try to compare it on a field by fiel basis. Maybe someone else knows more about swift ^^

kuhnroyal avatar Aug 06 '22 15:08 kuhnroyal

I thought about this but that is rather hard to do correct. Like changing from one wifi to another wifi network will result in 2 wifi events.

Have you checked that the wifi network switch emits two wifi results without none between them?

ycherniavskyi avatar Aug 09 '22 13:08 ycherniavskyi

This is how I fixed this issue using RxDart's debounceTime.

late StreamSubscription connectivitySubs;
PublishSubject<ConnectivityResult> onConnectionChange =
      PublishSubject<ConnectivityResult>();
      
      onConnectionChange
        .debounceTime(const Duration(
      seconds: 1,
    ))
        .listen((event) {
      log.d('connectionOnChange $event');
      if (event == ConnectivityResult.none) {
        Get.dialog(
          const NoInternetModal(),
          barrierDismissible: false,
        );
      }
    });
    
    connectivitySubs = Connectivity()
            .onConnectivityChanged
            .listen((ConnectivityResult result) {
          connectionOnChange.add(result);
        });
        
    // don't forget to dispose connectivitySubs
    connectivitySubs.cancel();
        

I know it's redundant to use 2 listeners, but it works for me.

freeman29 avatar Aug 25 '22 05:08 freeman29

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 15 days

github-actions[bot] avatar Dec 28 '22 00:12 github-actions[bot]

Same issue happened to me. version [3.0.3]

NijatTagizada avatar Mar 07 '23 18:03 NijatTagizada