roam-ai/roam-flutter

On iOS using Flutter Roam.initialise() never returns?

mj6uc opened this issue · 10 comments

mj6uc commented

Hi,
I am trying this out in a flutter app on iOS.

The following code, never returns.

await Roam.initialize(publishKey: Constants.roamId).then((value) {
  debugPrint('[[MJ]] ==> isInitialized $value');
}).catchError((e) {
  debugPrint('isInitialized error $e');
});

Neither does this:
await Roam.initialize(publishKey: Constants.roamId);

If I do not await the initialization, and go ahead with tracking and subscription -- app crashes on iOS.
Screenshot 2022-05-09 at 2 56 57 PM

I tried posting on the Support forums -- but they are having trouble sending a validation key to my email for the past 2 days -- so I can not post there!

Any help will be appreciated.

Hey @mj6uc,

Roam.initialize() does not return anything.
Please share the replication steps for the crash.

mj6uc commented

Hi Sahil,

Here is the code I am testing with:

Future<void> initRoam() async {
    debugPrint("[[MJ]] Initialising Roam...");
    // this await never returns -- and removing await crashes the app
    await Roam.initialize(publishKey: Constants.roamId).then((value) {
      debugPrint('[[MJ]] ==> isInitialized $value');
    }).catchError((e) {
      debugPrint('isInitialized error $e');
    });
  }
    debugPrint("[[MJ]] checkperm Called...");
    bool isGranted = await _checkLocationPermission();

    debugPrint("[[MJ]] checkperm loc service ...");
    bool isRunning = await geo.Geolocator.isLocationServiceEnabled();

    if (isGranted && !isRunning) {
      debugPrint("[[MJ]] open loc settings ...");
      await geo.Geolocator.openLocationSettings();
    }
    if (isGranted && isRunning) {
      await initRoam();
      debugPrint("[[MJ]] roam initialised"); // this is never printed till I remove await from the Roam.initialise() call -- and then app crashes

      try {
        debugPrint("user is " + user.toString());
        if (user.value?.roamId?.isNotEmpty ?? false) {
          Roam.getUser(
            userId: user.value!.roamId!,
            callBack: ({String? user}) {
              if(user?.isNotEmpty??false) {
                debugPrint('Roam.getUser( $user');
                Map map = jsonDecode(user!);
                this.user.value!.roamId = map['userId'];
              }
            },
          );
        } else {
          Roam.createUser(
            description: user.value!.id!,
            callBack: ({String? user}) {
              debugPrint('Roam.createUser( $user');
              if(user?.isNotEmpty??false) {
                Map map = jsonDecode(user!);
                this.user.value!.roamId = map['userId'];
                _userRepository.updateUser(
                  this.user.value!.id,
                  companyId: selectedCompany.value?.id ?? '',
                  userModel: this.user.value,
                );
              }
            },
          );
        }



        debugPrint("[[MJ]] Start Tracking");

        Roam.startTracking(trackingMode: 'balanced');
        Roam.getCurrentLocation(
          accuracy: 100,
          callBack: ({location}) {
            debugPrint('location_callBack $location');
            if (location is String && (user.value?.id?.isNotEmpty ?? false)) {
              LocationCallbackHandler.callbackFromRoam(location, user.value!.id!);
            }
          },
        );
        debugPrint("[[MJ]] Toggle listener");
        Roam.toggleListener(locations: true,events: true,callBack: ({user}) {
          //Do something with user
          debugPrint(user);
          debugPrint("[[MJ]] Location updated");
        });
        debugPrint("[[MJ]] Subscribe location");
        Roam.subscribeLocation();

And here is the output in case I do not await Roam initialise() -- and the app crashes:

flutter: [[MJ]] Toggle listener
flutter: [[MJ]] Subscribe location
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x108159a54)
    frame #0: 0x0000000108159a54 Roam`___lldb_unnamed_symbol707$$Roam + 700
Roam`___lldb_unnamed_symbol707$$Roam:
->  0x108159a54 <+700>: brk    #0x1
Roam`___lldb_unnamed_symbol708$$Roam:
    0x108159a58 <+0>:   stp    x28, x27, [sp, #-0x60]!
    0x108159a5c <+4>:   stp    x26, x25, [sp, #0x10]
    0x108159a60 <+8>:   stp    x24, x23, [sp, #0x20]
Target 0: (Runner) stopped.
Lost connection to device.

Same issue on Android where Roam.initialize() never returns. Spent a few hours puzzled about why it won't initialize, then I ran the demo code and realised it all just works. How do we know that Roam is successfully initialized if it never returns, or is it just a bug?

It's especially strange as returning in init methods once init is successful is a convention in Flutter(and other frameworks) and because the initialize() method has a return type of Future<bool?> it's extra confusing.

mj6uc commented

Does not seem to work on Android as well -- the app does not crash there - -but I do not get any Location hits on the Roam dashboard either.

Hey @mj6uc @irjayjay Thanks for the raising your concerns. We would like to get into a quick call to clarify both our methods and example application. We feel it would be faster to resolve and answer all your questions faster in a call along with our developers.

You can use the below link to schedule a quick call.

https://calendly.com/roam-support/30min

Our team is also looking into the issue facing with our forum and we will get that resolved as soon as possible and update you.

I don't know what happened in the call, but I guess the problem can be resolved using the MethodChannel.Result (android) e FlutterResult (iOS) to return for Flutter.
I opened this #24 suggesting the solution

Hey @luisfelipeas5 Thanks for the suggestion. The Roam.initialize() method does not return anything. It is supposed to be called at the beginning or entry point of your app. Our team is constantly working on improving the SDK with upcoming releases.

Hey @luisfelipeas5 Thanks for the suggestion. The Roam.initialize() method does not return anything. It is supposed to be called at the beginning or entry point of your app. Our team is constantly working on improving the SDK with upcoming releases.

Thank you. Make sense. But, how initialize has a Future<void> return in your signature (because of the nature of Method Channels), the user expect at least that he/she can use await to wait for our execution of the method, right?

Hey @luisfelipeas5 Yes, you are right. But there is no need to add await since the initialize method runs asynchronously on the native side and does not return anything. It is to be called at the beginning of app lifecycle.
I’ll share your suggestion to my team and we’ll look it as we update our SDK during our future releases.
For now, since this is no longer an issue and it’s resolved we closed the issue. If you do have other suggestions. Don’t hesitate to reach out to me at sahil@roam.ai

Hmm make sense. So, I think it is important replace the type of the return from Future<bool?> to void. This can consume precious time on debug