Flutter-geolocator: `Geolocator.isLocationServiceEnabled()๊ฐ€ true๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ `LocationServiceDisabledException`์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2020๋…„ 11์›” 06์ผ  ยท  20์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: Baseflow/flutter-geolocator

๐Ÿ› ๋ฒ„๊ทธ ์‹ ๊ณ 

์˜ˆ์ƒ๋˜๋Š” ํ–‰๋™

์œ„์น˜ ๊ถŒํ•œ์ด ๋ถ€์—ฌ๋œ ํ›„ ํ˜„์žฌ ์œ„์น˜๋ฅผ ๊ฐ€์ ธ์˜ค๋ ค๊ณ  ์‹œ๋„ํ•˜๊ณ  ์œ„์น˜ ์„œ๋น„์Šค๋„ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์ง€๋งŒ getCurrentPosition ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ LocationServiceDisabledException ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

๋ฒˆ์‹ ๋‹จ๊ณ„

try {
      final enabled = await Geolocator.isLocationServiceEnabled();

      print("enabled $enabled"); // true

      final permission = await Geolocator.checkPermission();

      print("permission $permission"); // whileInUse

      final position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.medium,
      ); // throw exception here

    } catch (e) {
        // i got `LocationServiceDisabledException` here
    }

๊ตฌ์„ฑ

๊ด€๋ จ๋œ ๋ชจ๋“  ๊ถŒํ•œ์ด ๋ถ€์—ฌ๋˜๊ณ  Android์˜ ๋ชจ๋“  ๊ตฌ์„ฑ์ด ์™„๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

๋ฒ„์ „: 6.1.5

ํ”Œ๋žซํผ:

  • [ ] : ์•„์ดํฐ: iOS
  • [x] :๋กœ๋ด‡: ์•ˆ๋“œ๋กœ์ด๋“œ
android triage

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•˜๋Š” geolocator ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ฒ„์ „ 6.1.10์„ ๋ฐฉ๊ธˆ ์ถœ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค.

Android์—์„œ onLocationAvailability ์ฝœ๋ฐฑ ๋ฉ”์„œ๋“œ๋Š” ์œ„์น˜ ์„œ๋น„์Šค๊ฐ€ ๋น„ํ™œ์„ฑํ™”๋˜์—ˆ์„ ๋•Œ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์œ„์น˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ์ž์ฃผ ๋ณด๊ณ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์„ ๋ฏธ์„ธ ์กฐ์ •ํ–ˆ์œผ๋ฉฐ ๋” ์ด์ƒ ์ž˜๋ชป๋œ LocationServiceDisabledException ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ๋ฅผ ๋ณด๊ณ ํ•˜๊ณ , ๋ช…ํ™•ํžˆ ํ•˜๊ณ , ์žฌํ˜„ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ฃผ์‹  ๋ชจ๋“  ๋ถ„๋“ค๊ป˜ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

๋ชจ๋“  20 ๋Œ“๊ธ€

๋™์ผํ•œ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์ง€๋งŒ LocationAccuracy ๋ฅผ ๊ธฐ๋ณธ๊ฐ’์—์„œ ๋‹ค๋ฅธ ๊ฒƒ์œผ๋กœ ๋ณ€๊ฒฝํ•  ๋•Œ๋งŒ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

StreamSubscription _streamSubscription = Geolocator.getPositionStream( // desiredAccuracy: LocationAccuracy.medium, <-- LocationServiceDisabledException error if I use a different accuracy distanceFilter: 500 ).listen(_listenData)..onError((e, stk) => print(e));

์ด ๋ฌธ์ œ๋ฅผ ์กฐ์‚ฌํ•˜๊ณ  ์žˆ์ง€๋งŒ ์žฌํ˜„ํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์งˆ๋ฌธ์— ๋‹ตํ•˜๊ณ  ์ด ๋ฌธ์ œ๋ฅผ ๋””๋ฒ„๊น…ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์—๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ๋˜๋Š” ์‹ค์ œ ์žฅ์น˜์—์„œ๋„ ์ด๊ฒƒ์„ ๋ณด๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?
  2. Google Play ์„œ๋น„์Šค๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ์Šต๋‹ˆ๊นŒ(์ด์— ๋”ฐ๋ผ Geolocator๋Š” FusedLocationProvider SDK ๋˜๋Š” LocationManager SDK๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฌธ์ œ๋ฅผ ์ฐพ์„ ์œ„์น˜๋ฅผ ์ขํžˆ๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค)?

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋„๋ก ํ”ผ๋“œ๋ฐฑ์„ ๊ธฐ๋‹ค๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ํ•  ๋•Œ ๊ฐ™์€ Unhandled Exception: The location service on the device is disabled. ์–ป์—ˆ์Šต๋‹ˆ๋‹ค.

Position position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.low);

ํ•ด๋‹น ์•ฑ์˜ ์œ„์น˜ ์„œ๋น„์Šค๊ฐ€ ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ์—๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

  1. Android 10์˜ ์‹ค์ œ ๊ธฐ๊ธฐ
  2. Google Play ์„œ๋น„์Šค๊ฐ€ ์„ค์น˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์‹œ๋„ํ–ˆ๊ณ  ๊ทธ๊ฒƒ์€ ์ค‘๊ฐ„ ์ •ํ™•๋„๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹ค๋ฅธ ์„ค์ •์—์„œ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  1. ์—๋ฎฌ๋ ˆ์ดํ„ฐ.
  2. ๋‘˜ ๋‹ค ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋™์ผํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์œผ๋ฉฐ ์–ด๋–ค ์„ค์ •์—์„œ๋„ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์œ„์น˜๊ฐ€ ํ•ญ์ƒ ์ผœ์ ธ ์žˆ๋Š” ์—๋ฎฌ๋ ˆ์ดํ„ฐ์™€ ์‹ค์ œ ์žฅ์น˜ ๋ชจ๋‘์—์„œ ํ…Œ์ŠคํŠธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ตœ๊ณ ์˜ ์ •ํ™•์„ฑ๋งŒ์„ ์ถ”๊ตฌํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  1. ์—๋ฎฌ๋ ˆ์ดํ„ฐ.
  2. Google Play ์„œ๋น„์Šค๊ฐ€ ์„ค์น˜๋จ

๋” ๋งŽ์€ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ํ˜„์žฌ ๊ทธ๊ฒƒ์„ ์กฐ์‚ฌํ•˜๊ณ  ์žˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ๊ทธ๊ฒƒ์„ ์žฌํ˜„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํŠน์ • ์„ค์ •์ด ํ™œ์„ฑํ™”/๋น„ํ™œ์„ฑํ™”๋˜๋Š” ๊ฒƒ๊ณผ ๊ด€๋ จ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•Œ๊ฒŒ๋˜๋ฉด ๋‹น์—ฐํžˆ ์•Œ๋ ค๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋™์•ˆ ์šฐ๋ฆฌ๋Š” ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์œ„ํ•ด ์—ด๋ ค ์žˆ์Šต๋‹ˆ๋‹ค(์ฆ‰, ์ด๊ฒƒ์€ ๋ชจ๋“  Android API์—์„œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๊นŒ ์•„๋‹ˆ๋ฉด Android 10์—์„œ๋งŒ ๋ฐœ์ƒํ•ฉ๋‹ˆ๊นŒ).

๋‚˜๋Š” ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. https://prnt.sc/vr3glj

์žฅ์น˜๊ฐ€ ๋„คํŠธ์›Œํฌ(WIFI ๋˜๋Š” ๋ชจ๋ฐ”์ผ)์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์ง€ ์•Š๊ณ  ๊ฑด๋ฌผ ์•ˆ์— ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: GPS ์—ฐ๊ฒฐ ๋ถˆ๋Ÿ‰).

ํ˜„์žฌ ์ŠคํŠธ๋ฆผ ์„ค์ •:
StreamSubscription<Position> positionStream = Geolocator.getPositionStream( desiredAccuracy: LocationAccuracy.best, distanceFilter: 0) .listen((Position position) {}

AndroidManifest.xml: <!--Location--> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

์žฅ์น˜ ์œ„์น˜ ์„ค์ •: ๋†’์€ ์ •ํ™•๋„(GPS, Wi-Fi, Bluetooth ๋ฐ ๋ชจ๋ฐ”์ผ ๋„คํŠธ์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์œ„์น˜ ํ™•์ธ)
ํŽธ์ง‘: ๋ฌผ๋ฆฌ์  ์žฅ์น˜ ์‚ฌ์šฉ

@seb3n ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ์ด๊ฒƒ์€ ๋งค์šฐ ์œ ์šฉํ•œ ์ •๋ณด์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์ด ๋‚˜์—๊ฒŒ ๊ณ„์†ํ•  ๋ฌด์–ธ๊ฐ€๋ฅผ ์ค„ ๊ฒƒ์ด๋ผ๊ณ  ํ™•์‹ ํ•œ๋‹ค.

๋” ๋งŽ์€ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ํ˜„์žฌ ๊ทธ๊ฒƒ์„ ์กฐ์‚ฌํ•˜๊ณ  ์žˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ๊ทธ๊ฒƒ์„ ์žฌํ˜„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํŠน์ • ์„ค์ •์ด ํ™œ์„ฑํ™”/๋น„ํ™œ์„ฑํ™”๋˜๋Š” ๊ฒƒ๊ณผ ๊ด€๋ จ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•Œ๊ฒŒ๋˜๋ฉด ๋‹น์—ฐํžˆ ์•Œ๋ ค๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋™์•ˆ ์šฐ๋ฆฌ๋Š” ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์œ„ํ•ด ์—ด๋ ค ์žˆ์Šต๋‹ˆ๋‹ค(์ฆ‰, ์ด๊ฒƒ์€ ๋ชจ๋“  Android API์—์„œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๊นŒ ์•„๋‹ˆ๋ฉด Android 10์—์„œ๋งŒ ๋ฐœ์ƒํ•ฉ๋‹ˆ๊นŒ).

@mvanbeusekom Android 9์—์„œ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

E/flutter (31570): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: The location service on the device is disabled.
E/flutter (31570): #0      MethodChannelGeolocator._handlePlatformException (package:geolocator_platform_interface/src/implementations/method_channel_geolocator.dart:192:9)
E/flutter (31570): #1      MethodChannelGeolocator.getCurrentPosition (package:geolocator_platform_interface/src/implementations/method_channel_geolocator.dart:121:7)
E/flutter (31570): <asynchronous suspension>
E/flutter (31570): #2      Geolocator.getCurrentPosition (package:geolocator/geolocator.dart:258:35)

isLocationServiceEnabled๊ฐ€ true์ž…๋‹ˆ๋‹ค.
์•”ํ˜ธ

      bool isLocationServiceEnabled =
          await Geolocator.isLocationServiceEnabled();
      AppLog.d(isLocationServiceEnabled);
      if (isLocationServiceEnabled) {
        Position position = await Geolocator.getCurrentPosition(
            desiredAccuracy: LocationAccuracy.high);
        return {"position": position.toString()};
      }

position = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.medium, forceAndroidLocationManager: true) .timeout(Duration(seconds: 10));

์ด ์ฝ”๋“œ ์กฐ๊ฐ์€ ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์ตœ์†Œํ•œ์˜ ์žฌํ˜„ ๊ฐ€๋Šฅํ•œ ์˜ค๋ฅ˜๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋Š” ์‹œ๋„์ž…๋‹ˆ๋‹ค.

import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'dart:async';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  <strong i="6">@override</strong>
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Flutter Demo',
        home: SafeArea(
          child: Scaffold(body: GeoLocatorWidget()),
        ));
  }
}

class GeoLocatorWidget extends StatefulWidget {
  const GeoLocatorWidget({
    Key key,
  }) : super(key: key);

  <strong i="7">@override</strong>
  _GeoLocatorWidgetState createState() => _GeoLocatorWidgetState();
}

class _GeoLocatorWidgetState extends State<GeoLocatorWidget> {
  StreamSubscription<Position> _streamSubscription;
  String message = 'empty';

  <strong i="8">@override</strong>
  void initState() {
    super.initState();
    _streamSubscription = Geolocator.getPositionStream(
            //desiredAccuracy: LocationAccuracy.medium,
            distanceFilter: 500)
        .listen(_onData, onError: _onError);
  }

  void _onData(Position position) {
    ScaffoldState _scaffoldKey = Scaffold.of(context, nullOk: true);
    if ((_scaffoldKey?.mounted ?? false)) _scaffoldKey.hideCurrentSnackBar();
    setState(() {
      message = 'latitude: ${position.latitude}, longitude: ${position.longitude}';
    });
  }

  void _onError(dynamic error) {
    bool geoService = error is LocationServiceDisabledException ||
        error is PermissionDeniedException;
    ScaffoldState _scaffoldKey = Scaffold.of(context, nullOk: true);
    if (!(_scaffoldKey?.mounted ?? false)) return;
    _scaffoldKey.hideCurrentSnackBar();
    _scaffoldKey.showSnackBar(SnackBar(
      content: Text('$error'),
      duration: const Duration(minutes: 2),
      action: geoService
          ? SnackBarAction(
              label: 'Change',
              onPressed: () async {
                if (error is LocationServiceDisabledException) {
                  bool locationEnabled =
                      await Geolocator.isLocationServiceEnabled();
                  if (!locationEnabled) await Geolocator.openLocationSettings();
                  else setState(() {
                    message = '''
                      locationService is enabled but the error says 
                      its of type LocationServiceDisabledException anyway :(
                    ''';
                  });
                } else await Geolocator.openAppSettings();
              },
            )
          : null,
    ));
  }

  <strong i="9">@override</strong>
  void dispose() {
    _streamSubscription?.cancel();
    super.dispose();
  }

  <strong i="10">@override</strong>
  Widget build(BuildContext context) {
    return Center(
      child: Text(message),
    );
  }
}

AndroidManifest์— ๋ชจ๋“  ๊ถŒํ•œ ์ถ”๊ฐ€

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

๋ฒˆ์‹ ๋‹จ๊ณ„

  1. streamSubscription์€ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ๊ถŒํ•œ ๋ฐ ์œ„์น˜ ์„œ๋น„์Šค๋ฅผ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค ๋ถ€์—ฌํ•˜๋ฉด ํ™”๋ฉด์— ์œ„๋„์™€ ๊ฒฝ๋„๊ฐ€ ๋ชจ๋‘ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  2. ์•ฑ์„ ์—ฐ ์ƒํƒœ์—์„œ ํ™”๋ฉด ๋„๊ธฐ(์‚ฌ์šฉ์ž๊ฐ€ ์‚ฐ๋งŒํ•˜๋‹ค๊ณ  ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•œ ๋‹ค์Œ 1๋ถ„ ํ›„์— ๋‹ค์‹œ ๋Œ์•„์˜ด)
  3. ํ™”๋ฉด์„ ์ผœ๊ฑฐ๋‚˜ ์ž ๊ธˆ ํ•ด์ œํ•˜๋ฉด ์ด์ œ ์•ฑ์— ์˜ค๋ฅ˜( LocationServiceDisabledException )์™€ ์Šค๋‚ต๋ฐ” ์ž‘์—… ๋ฒ„ํŠผ "๋ณ€๊ฒฝ"์ด ์žˆ๋Š” ์Šค๋‚ต๋ฐ”๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  4. ๋ฒ„ํŠผ์„ ํƒญํ•˜๋ฉด ์œ„์น˜ ์„œ๋น„์Šค๊ฐ€ ์‹ค์ œ๋กœ ๋น„ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๋Š”์ง€ ๋น„๋™๊ธฐ์‹์œผ๋กœ ํ™•์ธํ•˜๊ณ , ๋น„ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ LocationServiceDisabledException ์œ ํ˜•์˜ ์˜ค๋ฅ˜๋ผ๋„ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์œผ๋ฉด Geolocator.openLocationSettings(); ์—ด๊ธฐ๋ฅผ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค. ์ด ์Šค๋ ˆ๋“œ์˜ ๋ฌธ์ œ) ๊ทธ๋Ÿฐ ๋‹ค์Œ ํ™œ์„ฑํ™”๋˜์—ˆ์Œ์„ ์•Œ๋ฆฌ๋Š” ํ™”๋ฉด ํ…์ŠคํŠธ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด ์‹ค์ œ๋กœ ์•„๋ฌด ๊ฒƒ๋„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๊ณ ๋ ค ์‚ฌํ•ญ

  • Android 8.1.0 ๋ฐ Android 10์„ ์‚ฌ์šฉํ•˜๋Š” ์‹ค์ œ ๊ธฐ๊ธฐ๋กœ ํ…Œ์ŠคํŠธํ•œ ๊ฒฐ๊ณผ Android 8.1.0์—์„œ๋Š” ๋ชจ๋“  ๊ฒƒ์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ–ˆ์ง€๋งŒ(๊ป๋‹ค๊ฐ€ ์ผœ๊ณ  ์ž ์‹œ ํ›„ ์•ฑ์œผ๋กœ ๋Œ์•„์™€ ์˜ค๋ฅ˜๋ฅผ ํ‘œ์‹œํ•˜์ง€ ์•Š์Œ) Android์—์„œ ๋ฌธ์ œ๊ฐ€ ์ง€์†๋จ 10
  • ์—๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋„๋ก ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค(์ž ์ž๊ธฐ ๋˜๋Š” ๋ฐฐํ„ฐ๋ฆฌ ์ ˆ์•ฝ ๋ชจ๋“œ์™€ ๊ด€๋ จ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Œ).
  • ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์œ„์น˜๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ•˜์ง€๋งŒ ์œ„์น˜๊ฐ€ ๋ช…ํ™•ํ•˜๊ฒŒ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์„ ๋•Œ ์ด ์˜ค๋ฅ˜๋ฅผ ๋ณด๋‚ด์ง€ ์•Š์•„์•ผ ํ•˜๋ฉฐ ์•ฑ์ด ๋‹ค์‹œ ํฌ๊ทธ๋ผ์šด๋“œ ์ƒํƒœ์ผ ๋•Œ ์ŠคํŠธ๋ฆผ์„ ๋‹ค์‹œ ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์œ„์น˜ ์„œ๋น„์Šค ๋ฌธ์ œ)
  • ์ด๊ฒƒ์€ ๊ถŒํ•œ/์„œ๋น„์Šค๊ฐ€ ๋น„ํ™œ์„ฑํ™”๋˜์—ˆ๋‹ค๊ฐ€ ํ™œ์„ฑํ™”๋œ #568๊ณผ๋„ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ•œ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ ์•ฑ ์™ธ๋ถ€๋กœ ์ด๋™ํ•  ๋•Œ WidgetsBindingObserver๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ŠคํŠธ๋ฆผ์„ ๋‹ค์‹œ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(์„ค์ •์„ ์—ด์–ด ์œ„์น˜ ๋˜๋Š” ๊ถŒํ•œ์„ ๋ณ€๊ฒฝํ•  ๋•Œ ์•ฑ)
<strong i="5">@override</strong>
  void didChangeAppLifecycleState(AppLifecycleState state) {
    switch (state) {
      case AppLifecycleState.paused:
        if (_streamSubscription != null) {
          _streamSubscription.cancel();
          _streamSubscription = null;
        }
        break;
      case AppLifecycleState.resumed:
        _streamSubscription ??= Geolocator.getPositionStream(
            //desiredAccuracy: LocationAccuracy.medium,
            distanceFilter: 500).listen(_onData, onError: _onError);
        break;
      default:
        break;
    }
  }

์‚ฌ์šฉ์ž๊ฐ€ "๋ณ€๊ฒฝ" ๋ฒ„ํŠผ์„ ํƒญํ•˜๊ณ  ์œ„์น˜ ์„œ๋น„์Šค ์„ค์ •์œผ๋กœ ๋ฆฌ๋””๋ ‰์…˜๋˜๊ณ  ์ด๋ฅผ ์ผœ๊ณ  ์•ฑ์œผ๋กœ ๋Œ์•„๊ฐ€๋ฉด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€๋งŒ ์‚ฌ์šฉ์ž๊ฐ€ ์ƒํƒœ ํ‘œ์‹œ์ค„(์ŠคํŠธ๋ฆผ ๊ทธ ํ›„์— ๊ฐ’ ๋ฐ˜ํ™˜์„ ์ค‘์ง€ํ•ฉ๋‹ˆ๋‹ค).

๋‹ค๋ฅธ ์•„์ด๋””์–ด๋Š” cancelOnError: true ๋ฐ HandleError ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ŠคํŠธ๋ฆผ์˜ ์ผ๋ถ€ ์˜ค๋ฅ˜๋ฅผ ๊ฐ€๋กœ์ฑ„๊ณ  ๊ทธ๋‹ค์ง€ ์ค‘์š”ํ•˜์ง€ ์•Š์ง€๋งŒ(์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ) LocationServiceDisabledException ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ŠคํŠธ๋ฆผ์„ ๋‹ซ๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. HandleError ๋ฅผ ์–ธ์ œ, ์–ธ์ œ ์“ฐ๋ฉด ์•ˆ ๋˜๋Š”์ง€ ๋ถ„๊ฐ„ํ•˜๊ธฐ ์–ด๋ ค์›Œ์š”.

Android 8.0.0์ด ์ƒˆ๋กœ ์„ค์น˜๋œ ์‹ค์ œ ๊ธฐ๊ธฐ์—์„œ ๋˜ ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ๋ฅผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

API ํ˜ธ์ถœ

Position position = await Geolocator.getCurrentPosition(
      desiredAccuracy: LocationAccuracy.$accuracy$,
    ).timeout(Duration(seconds: 10));

๊ฐ $accuracy$ ๊ฐ’์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ:
| $์ •ํ™•๋„$ | ๊ฒฐ๊ณผ |
|----------|----------------------------- ------|
| ์ตœ์ € | ์‹œ๊ฐ„ ์ดˆ๊ณผ ์˜ˆ์™ธ |
| ๋‚ฎ์€ | ์œ„์น˜ ์„œ๋น„์Šค ๋น„ํ™œ์„ฑํ™” ์˜ˆ์™ธ |
| ๋งค์ฒด | ์œ„์น˜ ์„œ๋น„์Šค ๋น„ํ™œ์„ฑํ™” ์˜ˆ์™ธ |
| ๋†’์€ | ์‹œ๊ฐ„ ์ดˆ๊ณผ ์˜ˆ์™ธ |
| ์ตœ๊ณ  | ์œ„์น˜ ์„œ๋น„์Šค ๋น„ํ™œ์„ฑํ™” ์˜ˆ์™ธ |
| ๋ฒ ์ŠคํŠธํฌ๋‚ด๋น„๊ฒŒ์ด์…˜ | ํƒ€์ž„์•„์›ƒ ์˜ˆ์™ธ |

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

๊ธฐ๊ธฐ ์„ค์ •

๊ธฐ๊ธฐ ์œ„์น˜ ์„ค์ •: ๋†’์€ ์ •ํ™•๋„(GPS, Wi-Fi ๋ฐ ๋ชจ๋ฐ”์ผ ๋„คํŠธ์›Œํฌ ์‚ฌ์šฉ)
์™€์ดํŒŒ์ด: ์—ฐ๊ฒฐ๋จ
VPN: ์—†์Œ
GPS ์‹ ํ˜ธ ๊ฐ•๋„: ํž˜๋‚ด์„ธ์š”
์œ„์น˜ ์ •๋ณด: ์ผœ์ง
์ตœ๊ทผ ์œ„์น˜ ์š”์ฒญ: Geolocation API๋ฅผ ํ˜ธ์ถœํ•œ ์•ฑ ํ‘œ์‹œ

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•˜๋Š” geolocator ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ฒ„์ „ 6.1.10์„ ๋ฐฉ๊ธˆ ์ถœ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค.

Android์—์„œ onLocationAvailability ์ฝœ๋ฐฑ ๋ฉ”์„œ๋“œ๋Š” ์œ„์น˜ ์„œ๋น„์Šค๊ฐ€ ๋น„ํ™œ์„ฑํ™”๋˜์—ˆ์„ ๋•Œ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์œ„์น˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ์ž์ฃผ ๋ณด๊ณ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์„ ๋ฏธ์„ธ ์กฐ์ •ํ–ˆ์œผ๋ฉฐ ๋” ์ด์ƒ ์ž˜๋ชป๋œ LocationServiceDisabledException ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ๋ฅผ ๋ณด๊ณ ํ•˜๊ณ , ๋ช…ํ™•ํžˆ ํ•˜๊ณ , ์žฌํ˜„ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ฃผ์‹  ๋ชจ๋“  ๋ถ„๋“ค๊ป˜ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” xiaomi Redmi Note 8์—์„œ ๊ทธ๊ฒƒ์„ ์žฌํ˜„ํ–ˆ์ง€๋งŒ huawei p20 lite์—์„œ๋Š” ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.
xiaomi์—์„œ ์„œ๋น„์Šค๊ฐ€ ๋น„ํ™œ์„ฑํ™”๋˜๋ฉด ๋‹ค์Œ ๋ฉ”์„œ๋“œ๊ฐ€ true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  huawei์—์„œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ false๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ฒ„์ „: geolocator: ^6.1.13
Geolocator.isLocationServiceEnabled()๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.

@sejr1996 ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Nokia 3.1(android 9), Galaxy A10s(android 10) ๋ฒ„์ „ 6.1.13์—์„œ ๋™์ผํ•œ ๋ฌธ์ œ๋ฅผ ๊ฐ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค.

The location service on the device is disabled.
       at MethodChannelGeolocator._handlePlatformException(MethodChannelGeolocator.java:192)
       at MethodChannelGeolocator.<fn>(MethodChannelGeolocator.java:171)

@sejr1996 ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Nokia 3.1(android 9), Galaxy A10s(android 10) ๋ฒ„์ „ 6.1.13์—์„œ ๋™์ผํ•œ ๋ฌธ์ œ๋ฅผ ๊ฐ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค.

The location service on the device is disabled.
       at MethodChannelGeolocator._handlePlatformException(MethodChannelGeolocator.java:192)
       at MethodChannelGeolocator.<fn>(MethodChannelGeolocator.java:171)

๋‚˜๋Š” ๋˜‘๊ฐ™์ด ๋ฐ›๊ณ ์žˆ๋‹ค

๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์ด๋ฏธ ํ•ด๊ฒฐ๋˜์—ˆ๋‹ค๊ณ  ๋ฏฟ์Šต๋‹ˆ๋‹ค. ์„œ๋น„์Šค ์œ„์น˜๋ฅผ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•œ ๋งˆ์ง€๋ง‰ ์ˆ˜๋‹จ์€ ์œ„์น˜ ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด์ œ ์ƒˆ๋กœ์šด ๋ฒ„์ „์˜ geolocator ํŒจํ‚ค์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„์น˜ ๊ถŒํ•œ์ด ๋จผ์ € ์˜ค๊ณ  ์„œ๋น„์Šค ์œ„์น˜๊ฐ€ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰