ably / ably-flutter

A wrapper around our Cocoa and Java client library SDKs, providing iOS and Android support for those using Flutter and Dart.
https://ably.com/download
Apache License 2.0
60 stars 16 forks source link

PlatformException #463

Open TheManuz opened 1 year ago

TheManuz commented 1 year ago

I'm getting these PlatformException reports in Firebase Crashlytics from ably_flutter package.

Stacktrace attached. com.atono.droppay_issue_651deded2d2148c2f3126a4ecfef5e5b_crash_session_6438ED7702140001717933A6E2DCBB88_DNE_0_v2_stacktrace.txt

┆Issue is synchronized with this Jira Bug by Unito

sync-by-unito[bot] commented 1 year ago

➤ Automation for Jira commented:

The link to the corresponding Jira issue is https://ably.atlassian.net/browse/SDK-3537

mikelee638 commented 1 year ago

Hi @TheManuz, thanks for bringing this to our attention and providing the stack trace. For clarity, can you provide the versions of ably-flutter, Flutter, and Android where this exception is occurring?

TheManuz commented 1 year ago

Thanks for investigating the exception.

We have 59 reports of this crash on 35 users, with these specifics:

I could also provide the stacktraces for all 59 exceptions, even if they're all pretty similar.

If you need them or other informations, feel free to ask.

ikbalkaya commented 1 year ago

@TheManuz Would it be possible to provide some details on how you use this SDK please? especially in terms of anything related to threading. The log shows that network calls are happening on main thread which seems a bit strange as SDK should be executing network operations on a background thread

TheManuz commented 1 year ago

Sure, this is the class that uses ably_flutter:

import 'package:ably_flutter/ably_flutter.dart';
import 'package:async/async.dart';
import 'package:my_app/core/logger.dart';
import 'package:my_app/notification/API/druid_notification.api.dart';
import 'package:my_app/notification/model/rtcManagers/rtc_manager.dart';

class AblyRtcManager extends RtcManager {
  final Realtime realtime;

  AblyRtcManager({
    required String token,
    required super.environment,
    required super.uuid,
  }) : realtime = Realtime(
          options: ClientOptions(
            key: token,
            authCallback: (TokenParams params) async {
              final result = await GetAblyRtcToken().consume();
              return result.data!["token"] as String;
            },
          ),
        );

  void _connectionStateListener(ConnectionStateChange stateChange) {
    logger.d('$runtimeType connection state: ${stateChange.current}');
  }

  @override
  Stream<Map<String, dynamic>> subscribeToAllChannels() {
    realtime.connection
        .on(ConnectionEvent.connected)
        .listen(_connectionStateListener);

    final streams = channels.map(
      (String channel) => realtime.channels.get(channel).subscribe(),
    );

    return StreamGroup.merge(streams).map(
      // Ably returns a Map<Object?, Object?>, must be converted
      (m) => Map<String, dynamic>.from(m.data as Map<Object?, Object?>),
    );
  }

  @override
  void unsubscribeToAllChannels() {
    void releaseChannel(channel) => realtime.channels.release(channel);
    channels.forEach(releaseChannel);
  }
}

You say that network calls are happening on the main thread, but I'm not sure I have control on this, since these network calls happen on the Android layer (which is handle by ably-flutter plugin), and not on the Flutter layer.

I hope that this these informations helps.

ikbalkaya commented 1 year ago

Thanks @TheManuz That's really helpful. I will investigate this further later.

Just to be clear on network thread running on main thread, I don't think it's something to do with what you are doing. This is something that our SDK should handle.

sync-by-unito[bot] commented 1 year ago

➤ Ikbal Kaya commented:

There is a MainThreadSink in Android plugin that runs everything on main thread and this issue happens when a connection fails (that is called in a background thread) and subsequently invokes a network call. (checkFallbackHosts). I don’t want to change this behaviour, since function execution from plugins to dart side (not yet sure) has to be done from main thread. It might be better for someone for a more knowledge on Flutter plugin look into this