You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio模拟器中Flutter Geolocator PositionStream停止工作

Geolocator positionStream 无输出问题排查与修复

截至昨日,Geolocator的positionStream运行正常,但目前即使通过模拟器扩展控件修改设备位置,该流也不再输出任何数据,且无错误日志。相关代码如下:

相关代码片段

Riverpod位置流Provider

@riverpod
Stream<Position> positionStream(
  PositionStreamRef ref,
) async* {
  final locationService = ref.watch(locationServiceProvider);

  yield* locationService.geolocator.getPositionStream(
    locationSettings: locationService.getLocationSettings(),
  );
}

位置服务中的设置方法

LocationSettings getLocationSettings() {
if (defaultTargetPlatform == TargetPlatform.android) {
  return AndroidSettings(
      distanceFilter: 50,
      //(Optional) Set foreground notification config to keep the app alive
      //when going to the background
      foregroundNotificationConfig: const ForegroundNotificationConfig(
        notificationTitle: "Running in Background",
        notificationText:
            "Example app will continue to receive your location even when you aren't using it",
        notificationIcon: AndroidResource(name: 'notification_icon'),
      ));
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
  return AppleSettings(
    accuracy: LocationAccuracy.best,
    distanceFilter: AppLocationSettings.locationChangeDistance,
    activityType: ActivityType.automotiveNavigation,
    pauseLocationUpdatesAutomatically: true,
    // Only set to true if our app will be started up in the background.
    showBackgroundLocationIndicator: true,
  );
} else {
  return const LocationSettings(
    accuracy: LocationAccuracy.best,
    distanceFilter: 50,
  );
}
}

用于监听positionStreamProvider的Provider

@riverpod
CameraPosition 
myLocationCameraPosition(MyLocationCameraPositionRef ref) {
  final myLocation =
      ref.watch(positionStreamProvider.select((value) => value.valueOrNull));

  return CameraPosition(
    target: LatLng(
      myLocation?.latitude ?? defaultLatLng.latitude,
      myLocation?.longitude ?? defaultLatLng.longitude,
    ),
    zoom: defaultMapZoom,
  );
}

Provider启动方式

final locationAsync = ref.watch(
  positionStreamProvider.select((value) => value.whenData((value) => true)),
);

排查与修复步骤

  • 检查位置权限状态
    确认应用已授予精确位置权限(Android)或使用期间/始终允许权限(iOS),调用Geolocator.checkPermission()验证权限,若被拒绝需引导用户重新授权。

  • 调整位置更新阈值
    Android设置中distanceFilter设为50米,模拟器位置修改可能未达到该距离差,临时改为0测试:

    distanceFilter: 0,
    

    iOS端的AppLocationSettings.locationChangeDistance也需确认数值是否过大,建议临时改为0。

  • 修复Riverpod流生命周期问题
    当前Provider使用async*直接转发流,若locationServiceProvider重建可能导致流中断,修改为持有流并保持Provider活跃:

    @riverpod
    Stream<Position> positionStream(PositionStreamRef ref) {
      final locationService = ref.watch(locationServiceProvider);
      final stream = locationService.geolocator.getPositionStream(
        locationSettings: locationService.getLocationSettings(),
      );
      ref.keepAlive();
      return stream;
    }
    
  • 验证流的订阅状态
    在流中添加日志,确认是否有数据输出:

    @riverpod
    Stream<Position> positionStream(PositionStreamRef ref) {
      final locationService = ref.watch(locationServiceProvider);
      final stream = locationService.geolocator.getPositionStream(
        locationSettings: locationService.getLocationSettings(),
      ).map((position) {
        print('Received position: ${position.latitude}, ${position.longitude}');
        return position;
      });
      ref.keepAlive();
      return stream;
    }
    

    通过控制台日志判断是流未产生数据还是订阅未生效。

  • 检查模拟器位置模拟方式
    Android模拟器:使用Extended Controls > Location,确保点击“Set location”而非仅修改经纬度;iOS模拟器:通过Debug > Location选择自定义位置,或用simctl命令行设置位置。

  • 重置Geolocator实例
    在LocationService中添加重置方法,避免内部状态异常:

    void resetGeolocator() {
      _geolocator = GeolocatorPlatform.instance;
    }
    

    在Provider中监听重置信号,触发流重建。

内容的提问来源于stack exchange,提问作者DeKekem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 15:34:55