Flutterのアップデートが日々行われているからか、ググってみたものをパクってコードに落としてみても、意図した動作をしないことがあった。

例えば、geolocatorを使うこのサイトを参考にしても、位置情報サービスを許可するダイアログが表示されない。

それどころか、なぜかLAN内を探索できるようにするかのダイアログが表示されたりして、意味がわからない。これは出たり出なかったりするので、恐らくAndroid Studioからデバッガが接続しているために表示されるものだろう。。。と勝手な解釈をして無かったことにする。

結果的にgeolocatorは使わず、locatorだけでよかった。多分GPSの位置情報はlocatorで、Mapに表示させたりするのにgeolocatorを使うのかもしれない。

一番参考になった(というよりパクれた)サイトはこのサイトだった。

基本的には、メイン画面から、GPS位置情報取得用ページに飛ぶと、イニシャライザでgetlocationを実行する。この時に位置情報取得の許可ダイアログが出てくる。

許可しない場合、例外を捕捉してOS上のどの問題が発生しているのかを判断するルーチンを用意したが、一番最初に拒否した時には、補足できず、「no data」のままになってしまう。

画面を戻って、再度GPS位置情報取得用ページに飛ぶと、例外を捕捉でき、設定アプリから許可してねって促すメッセージを表示できる。残念ながらこの問題はどうにもならなかった。

あと、常にGPS値に変化があった場合に取得するルーチンを用意したが、iOSシミュレータでは動作しなかった。実機(iPhone SE2)では動作したが、アプリが開いている間のみ。ホーム画面に戻ると、数秒間は取得を続けるが、そのうち取得しなくなる。スリープ状態になるのだと思う。

とりあえずアプリ表示中のみでも、GPS位置情報を取得し続けられるので、今後はこれをAppleマップやGoogleマップに位置情報を渡して表示させるものを作る予定。

誰も興味ないとは思うが、一応GitHubにてPublic設定にしてあるので興味がある方はご覧ください。

Flutter GPS位置情報取得サンプル

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:location/location.dart';
import 'package:permission_handler/permission_handler.dart' as per_handler;

class GpsPosition extends StatefulWidget {
  const GpsPosition({Key? key}) : super(key: key);

  @override
  _GpsPositionState createState() => _GpsPositionState();
}
class _GpsPositionState extends State<GpsPosition> {
  String currentLocationText = 'no data';

  final Location _locationService = Location();

  late bool _serviceEnabled;
  late PermissionStatus _permissionGranted;
  late LocationData _locationData;

  @override
  void initState() {
    super.initState();
    // GPS値を監視する ※実機だと動作するがエミュレーターだと動作しない
    //initWatchLocationService();
    // FloatActionButtonを押してGPS値を取得する
    getLocationAndPlatformState();
  }

  /// GPS値を監視する
  void initWatchLocationService() async {
    _serviceEnabled = await _locationService.serviceEnabled();
    if (!_serviceEnabled) {
      _serviceEnabled = await _locationService.requestService();
      if (!_serviceEnabled) {
        return;
      }
    }

    _permissionGranted = await _locationService.hasPermission();
    if (_permissionGranted == PermissionStatus.denied) {
      _permissionGranted = await _locationService.requestPermission();
      if (_permissionGranted != PermissionStatus.granted) {
        return;
      }
    }

    _locationData = await _locationService.getLocation();

    _locationService.onLocationChanged.listen((LocationData currentLocation) {
      // Use current location
      setState(() {
        currentLocationText = '$currentLocation';
      });
    });

    _locationService.enableBackgroundMode(enable: true);
  }

  void getLocationAndPlatformState() async {
    try {
      /// ↓ここで位置情報取得の許諾ダイアログが表示される
      /// iOS:設定アプリ>プライバシー>位置情報サービス>当該アプリ
      LocationData myLocation = await _locationService.getLocation();
      setState(() {
        currentLocationText = '$myLocation';
      });
    } on PlatformException catch (e) {
      String error = '位置情報が取得できません';
      if (e.code.contains('PERMISSION_DENIED')) {
        error = '位置情報取得の許可が得られませんでした';
        error += '設定アプリにて許可するようにお願いします';
      }
      setState(() {
        currentLocationText = error;
      });
      bool isShown = await per_handler.Permission.contacts.shouldShowRequestRationale;
      if (isShown == false) {
        per_handler.openAppSettings();
        // sleep(const Duration(seconds: 2));
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('GPS Position'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              currentLocationText,
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          getLocationAndPlatformState();
        },
        child: const Icon(Icons.location_on),
      ),
    );
  }
}
import 'package:flutter/material.dart';
import 'package:gpsposition/gps_position.dart';

void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, this.title}) : super(key: key);
  final String? title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title!),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => GpsPosition()),
                );
              },
              child: const Text('位置情報取得ページへ'),
            ),
          ],
        ),
      ),
    );
  }
}


About The Author

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA