liodali / osm_flutter

OpenStreetMap plugin for flutter
https://pub.dev/packages/flutter_osm_plugin
MIT License
239 stars 98 forks source link

startLocationUpdating not show user marker #520

Open frxk opened 7 months ago

frxk commented 7 months ago

Hi and thank you for this useful library. The question is that when i call the function

controller.startLocationUpdating(enableStopFollow: true,useDirectionMarker: true)

the map is centered on position, but not showing the user marker.

Instead if i execute this code, the user marker is showed.

controller.currentLocation().whenComplete((){ controller.enableTracking(enableStopFollow: true); });

Thank you

liodali commented 7 months ago

startLocationUpdating is designed for that only receive user location without control the map can you share some part of your code to see because if you use it the map should not move only receive the location in onLocationChanged that give you possibility to do you own custom logic we have enableTracking that contain our logic for that

frxk commented 7 months ago

HI, I found the error on my code. When I enable the tracking location, the controller.currentLocation() function inside onLocationChanged center the map. Commenting that line everything works. Below is the extract of the code. Thank you

import 'dart:async';

import 'package:flutter/material.dart';

import 'package:flutter_osm_plugin/flutter_osm_plugin.dart';

//-----------------MAP--------

class OpenStreetMapsTest extends StatefulWidget {

  const OpenStreetMapsTest({Key? key}) : super(key: key);

  @override

  State<OpenStreetMapsTest> createState() => _OpenStreetMapsState();

}

ValueNotifier<bool> showFab = ValueNotifier(true);

ValueNotifier<bool> statusTrackPosizione = ValueNotifier(false);

late MapController controller;

class _OpenStreetMapsState extends State<OpenStreetMapsTest>  with OSMMixinObserver,TickerProviderStateMixin {

  @override

  void initState() {

    super.initState();

    controller = MapController(

      initPosition: GeoPoint(latitude: 41.450202, longitude: 12.234500),

      useExternalTracking: statusTrackPosizione.value,

    );

    controller.addObserver(this);

    scaffoldKey = GlobalKey<ScaffoldState>();

  }

  @override

  Future<void> mapIsReady(bool isReady) async {

    if (isReady) {}

  }

  @override

  void dispose() {

    // Clean up the controller when the widget is removed from the

    controller.dispose();

    showFab = ValueNotifier(true);

    statusTrackPosizione = ValueNotifier(false);

    super.dispose();

  }

  late GlobalKey<ScaffoldState> scaffoldKey;

  @override

  Widget build(BuildContext context) {

    //double sidebarInfoTrackWidth=MediaQuery.of(context).size.width;

    return Scaffold(

      key: scaffoldKey,

      backgroundColor: Colors.white,

      body: Mappa(),

      floatingActionButton: ValueListenableBuilder<bool>(

        valueListenable: showFab,

        builder: (ctx, isShow, child) {

          if (!isShow) {

            return const SizedBox.shrink();

          }

          return child!;

        },

        child: FloatingActionButton(

          backgroundColor: Colors.black,

          onPressed: () {

            TrackPosizione();

          },

          tooltip: "Tracking",

          child: ValueListenableBuilder<bool>(

            valueListenable: statusTrackPosizione,

            builder: (ctx, isTracking, _) {

              if (isTracking) {

                return const Icon(Icons.my_location);

              }

              return const Icon(Icons.gps_off_sharp);

            },

          ),

        ),

      ),

    );

  }

  //----------FUNZIONI della Mappa-------------------------

  //Mappa

  OSMFlutter Mappa() {

    return OSMFlutter(

      controller: controller,

      osmOption: OSMOption(

        /*userTrackingOption: UserTrackingOption(

          enableTracking: true,

          unFollowUser: false,

          ),*/

        enableRotationByGesture: false,

        showContributorBadgeForOSM: false,

        showDefaultInfoWindow: false,

        //popup info waypoint

        isPicker: false,

        zoomOption: const ZoomOption(

          initZoom: 16,

          minZoomLevel: 2,

          maxZoomLevel: 19,

          stepZoom: 1.0,

        ),

        userLocationMarker: UserLocationMaker(

          personMarker: const MarkerIcon(

            icon: Icon(

              Icons.directions_walk,

              color: Colors.red,

              size: 80,

              shadows: [

                Shadow(offset: Offset(0.0, 0.0),

                    blurRadius: 10.0,

                    color: Colors.blue),

                Shadow(offset: Offset(0.0, 0.0),

                    blurRadius: 10.0,

                    color: Colors.blue),

                Shadow(offset: Offset(0.0, 0.0),

                    blurRadius: 10.0,

                    color: Colors.blue),

                Shadow(offset: Offset(0.0, 0.0),

                    blurRadius: 4.0,

                    color: Colors.black),

                Shadow(offset: Offset(0.0, 0.0),

                    blurRadius: 4.0,

                    color: Colors.black),

                Shadow(offset: Offset(0.0, 0.0),

                    blurRadius: 7.0,

                    color: Colors.black)

              ],

            ),

          ),

          directionArrowMarker: const MarkerIcon(

            icon: Icon(

              Icons.navigation,

              color: Colors.red,

              size: 90,

              shadows: [

                Shadow(offset: Offset(0.0, 0.0),

                    blurRadius: 18.0,

                    color: Colors.blue),

                Shadow(offset: Offset(0.0, 0.0),

                    blurRadius: 18.0,

                    color: Colors.blue),

                Shadow(offset: Offset(0.0, 0.0),

                    blurRadius: 18.0,

                    color: Colors.blue),

                Shadow(offset: Offset(0.0, 0.0),

                    blurRadius: 4.0,

                    color: Colors.black),

                Shadow(offset: Offset(0.0, 0.0),

                    blurRadius: 4.0,

                    color: Colors.black),

                Shadow(offset: Offset(0.0, 0.0),

                    blurRadius: 7.0,

                    color: Colors.black)

              ],

            ),

          ),

        ),

      ),

      onLocationChanged: (myLocation) {

        if (statusTrackPosizione.value == true) {

          //controller.currentLocation();

        }

      },

      onGeoPointClicked: (geoPoint) async {},

    );

  }

  //segui posizione--------

  void TrackPosizione() {

    if (!statusTrackPosizione.value) {

      controller.startLocationUpdating(enableStopFollow: true, useDirectionMarker: true).whenComplete(() {

        statusTrackPosizione.value = true;

      });

      ScaffoldMessenger.of(context)

        ..removeCurrentSnackBar()

        ..showSnackBar(Snackbar("Tracking GPS enabled"));

      /*controller.currentLocation().whenComplete(() {

        controller.enableTracking(enableStopFollow: true).whenComplete((){statusTrackPosizione.value=true;});

        ScaffoldMessenger.of(context)

          ..removeCurrentSnackBar()

          ..showSnackBar(Snackbar("Tracking GPS enabled"));

      });*/

    } else {

      //controller.disabledTracking().whenComplete((){statusTrackPosizione.value=false;});

      controller.stopLocationUpdating().whenComplete(() {

        statusTrackPosizione.value = false;

      });

      ScaffoldMessenger.of(context)

        ..removeCurrentSnackBar()

        ..showSnackBar(Snackbar("Tracking GPS disabled"));

    }

  }

  SnackBar Snackbar(String Testo) {

    return SnackBar(

      behavior: SnackBarBehavior.floating,

      margin: EdgeInsets.only(left: 8, right: 8, bottom: MediaQuery

          .of(context)

          .size

          .height * 0.1),

      backgroundColor: Colors.white,

      elevation: 10,

      action: SnackBarAction(

          label: "Close", textColor: Colors.black, onPressed: () {

        ScaffoldMessenger.of(context).hideCurrentSnackBar();

      }),

      //shape: StadiumBorder(),

      content: Container(

        constraints: BoxConstraints(maxWidth: (MediaQuery

            .of(context)

            .size

            .width - 10)),

        child: FittedBox(

          fit: BoxFit.scaleDown,

          child: Row(

            mainAxisSize: MainAxisSize.min,

            mainAxisAlignment: MainAxisAlignment.center,

            children: [

              const Icon(

                  Icons.info_outline_rounded, color: Colors.white, size: 20),

              const SizedBox(width: 5,),

              Text(Testo, maxLines: 2,

                  style: TextStyle(fontSize: 15, color: Colors.black)),

            ],

          ),

        ),

      ),

      duration: const Duration(seconds: 1),

    );

  }

}
liodali commented 7 months ago

ah call controller.currentLocation() outside of the onLocationChanged and in general is used with enableTracking or separate depend on the logic or use case startLocationUpdation just that you will receive the user location without using our internal logic that we already impl in enableTracking

tmp78 commented 7 months ago

@liodali , Could you please check if this piece of code is causing an error for you?

await _controller.currentLocation();
await _controller.enableTracking(
        enableStopFollow: true,
        disableUserMarkerRotation: false,
        anchor: Anchor.center,
      );

On the iOS simulator everything works fine, on the Android simulator it gives the following error:

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(400, java.lang.NullPointerException: getLastKnownLocation(...) must not be null
E/flutter ( 5876):  at hamza.dali.flutter_osm_plugin.overlays.CustomLocationManager.enableFollowLocation(CustomLocation.kt:119)
E/flutter ( 5876):  at hamza.dali.flutter_osm_plugin.overlays.CustomLocationManager.toggleFollow(CustomLocation.kt:252)
E/flutter ( 5876):  at hamza.dali.flutter_osm_plugin.FlutterOsmView.trackUserLocation(FlutterOsmView.kt:1171)
E/flutter ( 5876):  at hamza.dali.flutter_osm_plugin.FlutterOsmView.onMethodCall(FlutterOsmView.kt:463)
E/flutter ( 5876):  at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:267)
E/flutter ( 5876):  at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:292)
E/flutter ( 5876):  at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)
E/flutter ( 5876):  at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)
E/flutter ( 5876):  at android.os.Handler.handleCallback(Handler.java:938)
E/flutter ( 5876):  at android.os.Handler.dispatchMessage(Handler.java:99)
E/flutter ( 5876):  at android.os.Looper.loopOnce(Looper.java:201)
E/flutter ( 5876):  at android.os.Looper.loop(Looper.java:288)
E/flutter ( 5876):  at android.app.ActivityThread.main(ActivityThread.java:7839)
E/flutter ( 5876):  at java.lang.reflect.Method.invoke(Native Method)
E/flutter ( 5876):  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
E/flutter ( 5876):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
E/flutter ( 5876): , , null)
E/flutter ( 5876): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:651:7)
E/flutter ( 5876): #1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:334:18)
E/flutter ( 5876): <asynchronous suspension>
E/flutter ( 5876): #2      MethodChannelOSM.enableTracking (package:flutter_osm_interface/src/channel/osm_method_channel.dart:280:5)
E/flutter ( 5876): <asynchronous suspension>
E/flutter ( 5876): #3      MobileOSMController.enableTracking (package:flutter_osm_plugin/src/controller/osm/osm_controller.dart:467:5)
E/flutter ( 5876): <asynchronous suspension>
E/flutter ( 5876): #4      MapController.enableTracking (package:flutter_osm_plugin/src/controller/map_controller.dart:330:5)
E/flutter ( 5876): <asynchronous suspension>
E/flutter ( 5876): #5      MapManager.switchTracking (package:kutno/models/map_manager.dart:156:7)
E/flutter ( 5876): <asynchronous suspension>
E/flutter ( 5876): 

The next executions are OK. This problem doesn't exist on iOS. And I think it worked fine on Android in previous versions as well.

liodali commented 7 months ago

I will do fix for that