Flutter web - Geolocator 在上传到服务器时不起作用

Flutter web - Geolocator not working when uploaded to server

大家。

我正在尝试使用 flutter 2.2.1 开发一个 PWA,它使用 Mapbox_gl 显示地图并使用 Geolocator 显示用户当前位置。

到目前为止,调试应用程序时一切正常,但是当我 运行:

flutter build

flutter build --release

然后是运行

firebase deploy

网站已上传,地图按预期显示并请求权限,但用户的位置从未显示,Google Chrome 的控制台抛出此错误:

Uncaught TypeError: m.gfR is not a function
at Object.avh (main.dart.js:20405)
at main.dart.js:65755
at aiD.a (main.dart.js:5853)
at aiD. (main.dart.js:34394)
at ahm. (main.dart.js:34386)
at Rx.o1 (main.dart.js:35356)
at adi.[=13=] (main.dart.js:34770)
at Object.tQ (main.dart.js:5975)
at a5.mn (main.dart.js:34687)
at ada.[=13=] (main.dart.js:34731)

这是我在 flutter 上使用的代码:

mapbox.dart

import 'dart:async';
import 'dart:io';
import 'dart:math';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:geolocator/geolocator.dart';
import 'package:kkc/main.dart';
import 'package:mapbox_gl/mapbox_gl.dart';
import 'package:kkc/services/location_service.dart';

class Mapbox extends StatefulWidget {
   const Mapbox();

   @override
   State createState() => MapboxState();
}

class MapboxState extends State<Mapbox> {
   final Random _rnd = new Random();

   Position? _currentLocation;
   LatLng _currentCoordinates = new LatLng(0,0);
   final List<_PositionItem> _positionItems = <_PositionItem>[];
   StreamSubscription<Position>? _positionStreamSubscription;

   late MapboxMapController _mapController;
   List<Marker> _markers = [];
   List<_MarkerState> _markerStates = [];

   CameraPosition _kInitialPosition = CameraPosition(
     target: LatLng(19.4274418, -99.1682147),
     zoom: 18.0,
     tilt: 70,
   );

   void _addMarkerStates(_MarkerState markerState) {
     _markerStates.add(markerState);
   }

   void _onMapCreated(MapboxMapController controller) {
     _mapController = controller;
     controller.addListener(() {
       if (controller.isCameraMoving) {
         _updateMarkerPosition();
       }
     });
   }

   void _onStyleLoadedCallback() {
     _updateMarkerPosition();
   }

   void _onCameraIdleCallback() {
     _updateMarkerPosition();
   }

   void _updateMarkerPosition() {
     final coordinates = <LatLng>[];

     for (final markerState in _markerStates) {
       coordinates.add(markerState.getCoordinate());
     }

     _mapController.toScreenLocationBatch(coordinates).then((points) {
       _markerStates.asMap().forEach((i, value) {
         _markerStates[i].updatePosition(points[i]);
       });
     });
  }

  void _addMarker(Point<double> point, LatLng coordinates) {
     setState(() {
       _markers.add(Marker(_rnd.nextInt(100000).toString(), coordinates, point, _addMarkerStates));
     });
  }

  @override
  void initState() {
     super.initState();
     _getCurrentLocation();
  }

  @override
  void dispose() {
     super.dispose();
  }

  @override
  Widget build(BuildContext context) {
     return new Scaffold(
       body: Stack(children: [
         MapboxMap(
           accessToken: Kukulcan.MAPBOX_ACCESS_TOKEN,
           trackCameraPosition: true,
           onMapCreated: _onMapCreated,
           onCameraIdle: _onCameraIdleCallback,
           onStyleLoadedCallback: _onStyleLoadedCallback,
           initialCameraPosition: _kInitialPosition,
         ),
         IgnorePointer(
             ignoring: true,
             child: Stack(
               children: _markers,
             ))
        ]),
     );
  }

  void _getCurrentLocation() async {
     _currentLocation = await LocationService.startLocationService();
     _currentCoordinates = new LatLng(_currentLocation!.latitude,_currentLocation!.longitude);

     await _mapController.animateCamera(CameraUpdate.newLatLng(_currentCoordinates));
     _addMarker(new Point(1, 1), _currentCoordinates);

     if (_positionStreamSubscription == null) {
       final positionStream = Geolocator.getPositionStream();
       _positionStreamSubscription = positionStream.handleError((error) {
         _positionStreamSubscription?.cancel();
         _positionStreamSubscription = null;
       }).listen((position) => setState(() => _positionItems.add(
         _PositionItem(_PositionItemType.position, position.toString()))));
       _positionStreamSubscription?.pause();
     }
   }
}

class Marker extends StatefulWidget {
   final Point _initialPosition;
   LatLng _coordinate;
   final void Function(_MarkerState) _addMarkerState;

   Marker(
       String key, this._coordinate, this._initialPosition, this._addMarkerState)
       : super(key: Key(key));

   @override
   State<StatefulWidget> createState() {
     final state = _MarkerState(_initialPosition);
     _addMarkerState(state);
     return state;
   }
}

class _MarkerState extends State with TickerProviderStateMixin {
   final _iconSize = 80.0;

   Point _position;

   _MarkerState(this._position);

   @override
   Widget build(BuildContext context) {
     var ratio = 1.0;

     //web does not support Platform._operatingSystem
     if (!kIsWeb) {
       // iOS returns logical pixel while Android returns screen pixel
       ratio = Platform.isIOS ? 1.0 : MediaQuery.of(context).devicePixelRatio;
     }

     return Positioned(
         left: _position.x / ratio - _iconSize / 2,
         top: _position.y / ratio - _iconSize / 2,
         child: Image.asset('assets/img/pin.png', height: _iconSize));
   }

   void updatePosition(Point<num> point) {
     setState(() {
       _position = point;
     });
   }

   LatLng getCoordinate() {
     return (widget as Marker)._coordinate;
   }
}

enum _PositionItemType {
   permission,
   position, 
}

class _PositionItem {
   _PositionItem(this.type, this.displayValue);

   final _PositionItemType type;
   final String displayValue;
}

有人知道问题出在哪里吗?

干杯!

无论如何,我找到的解决方案是使用 geolocat documentation

所述的 --no-sound-null-safety 参数

我引用:

NOTE: due to a bug in the dart:html library the web version of the Geolocator plugin does not work with sound null safety enabled and compiled in release mode. Running the App in release mode with sound null safety enabled results in a Uncaught TypeError (see issue #693). The current workaround would be to build your App with sound null safety disabled in release mode: