首页 > 解决方案 > Flutter web - 上传到服务器时地理定位器不起作用

问题描述

每个人。

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

到目前为止,在调试应用程序时一切都按预期工作,但是当我运行时:

flutter build

或者

flutter build --release

然后运行

firebase deploy

网站被上传,地图按预期显示,它要求权限,但用户的位置从未显示,谷歌浏览器的控制台抛出此错误:

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.$2 (main.dart.js:34394)
at ahm.$1 (main.dart.js:34386)
at Rx.o1 (main.dart.js:35356)
at adi.$0 (main.dart.js:34770)
at Object.tQ (main.dart.js:5975)
at a5.mn (main.dart.js:34687)
at ada.$0 (main.dart.js:34731)

这是我在颤振上使用的代码:

地图框.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;
}

有谁知道问题出在哪里?

干杯!

标签: flutterprogressive-web-apps

解决方案


无论如何,我找到的解决方案是使用 geolocat文档中所述的 --no-sound-null-safety 参数

我引用:

注意:由于 dart:html 库中的错误,Geolocator 插件的 Web 版本在启用声音空安全性并在发布模式下编译时无法使用。在启用了健全的 null 安全性的情况下以发布模式运行应用程序会导致未捕获的类型错误(请参阅问题 #693)。当前的解决方法是在发布模式下禁用健全的空安全性来构建您的应用程序:


推荐阅读