iOS GPS 設定によるポップアップ、バックグラウンド処理修正。Android は未確認
This commit is contained in:
169
lib/main.dart
169
lib/main.dart
@ -1,8 +1,12 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
//import 'dart:convert';
|
||||
//import 'dart:developer';
|
||||
import 'package:rogapp/model/gps_data.dart';
|
||||
import 'package:rogapp/utils/database_gps.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:get/get.dart';
|
||||
//import 'package:vm_service/vm_service.dart';
|
||||
//import 'package:dart_vm_info/dart_vm_info.dart';
|
||||
@ -23,6 +27,10 @@ import 'package:rogapp/services/error_service.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
//import 'dart:async';
|
||||
//import 'package:get/get.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
|
||||
Map<String, dynamic> deviceInfo = {};
|
||||
|
||||
@ -114,6 +122,8 @@ void main() async {
|
||||
|
||||
//Get.put(LocationController());
|
||||
|
||||
requestLocationPermission();
|
||||
|
||||
// startMemoryMonitoring(); // 2024-4-8 Akira: メモリ使用量のチェックを開始 See #2810
|
||||
Get.put(SettingsController()); // これを追加
|
||||
|
||||
@ -126,6 +136,21 @@ void main() async {
|
||||
//runApp(const MyApp());
|
||||
}
|
||||
|
||||
Future<void> requestLocationPermission() async {
|
||||
try {
|
||||
final status = await Permission.locationAlways.request();
|
||||
if (status == PermissionStatus.granted) {
|
||||
print('Location permission granted');
|
||||
} else {
|
||||
print('Location permission denied');
|
||||
//await showLocationPermissionDeniedDialog(); // 追加
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error requesting location permission: $e');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// メモリ使用量の解説:https://qiita.com/hukusuke1007/items/e4e987836412e9bc73b9
|
||||
|
||||
/*
|
||||
@ -192,6 +217,99 @@ void showMemoryWarningDialog() {
|
||||
}
|
||||
}
|
||||
|
||||
StreamSubscription<Position>? positionStream;
|
||||
bool background=false;
|
||||
DateTime lastGPSCollectedTime=DateTime.now();
|
||||
String team_name="";
|
||||
String event_code="";
|
||||
|
||||
Future<void> startBackgroundTracking() async {
|
||||
if (Platform.isIOS && background==false) {
|
||||
|
||||
final IndexController indexController = Get.find<IndexController>();
|
||||
if(indexController.currentUser.length>0) {
|
||||
team_name = indexController.currentUser[0]["user"]['team_name'];
|
||||
event_code = indexController.currentUser[0]["user"]["event_code"];
|
||||
}
|
||||
background = true;
|
||||
debugPrint("バックグラウンド処理を開始しました。");
|
||||
final LocationSettings locationSettings = LocationSettings(
|
||||
accuracy: LocationAccuracy.high,
|
||||
distanceFilter: 100,
|
||||
);
|
||||
|
||||
try {
|
||||
positionStream = Geolocator.getPositionStream(locationSettings: locationSettings)
|
||||
.listen((Position? position) async {
|
||||
if (position != null) {
|
||||
final lat = position.latitude;
|
||||
final lng = position.longitude;
|
||||
//final timestamp = DateTime.now();
|
||||
final accuracy = position.accuracy;
|
||||
|
||||
// GPS信号強度がlowの場合はスキップ
|
||||
if (accuracy > 100) {
|
||||
debugPrint("GPS signal strength is low. Skipping data saving.");
|
||||
return;
|
||||
}
|
||||
|
||||
Duration difference = lastGPSCollectedTime.difference(DateTime.now())
|
||||
.abs();
|
||||
// 最後にGPS信号を取得した時刻から10秒以上経過、かつ10m以上経過(普通に歩くスピード)
|
||||
//debugPrint("時間差:${difference}");
|
||||
if (difference.inSeconds >= 10 ) {
|
||||
debugPrint("バックグラウンドでのGPS取得時の処理(10secおき) count=${difference.inSeconds}, time=${DateTime.now()}");
|
||||
|
||||
// DBにGPSデータを保存 pages/destination/destination_controller.dart
|
||||
await addGPStoDB(lat, lng);
|
||||
|
||||
lastGPSCollectedTime = DateTime.now();
|
||||
}
|
||||
}
|
||||
}, onError: (error) {
|
||||
if (error is LocationServiceDisabledException) {
|
||||
print('Location services are disabled');
|
||||
} else if (error is PermissionDeniedException) {
|
||||
print('Location permissions are denied');
|
||||
} else {
|
||||
print('Location Error: $error');
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
print('Error starting background tracking: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> addGPStoDB(double la, double ln) async {
|
||||
//debugPrint("in addGPStoDB ${indexController.currentUser}");
|
||||
GpsDatabaseHelper db = GpsDatabaseHelper.instance;
|
||||
try {
|
||||
GpsData gps_data = GpsData(
|
||||
id: 0,
|
||||
team_name: team_name,
|
||||
event_code: event_code,
|
||||
lat: la,
|
||||
lon: ln,
|
||||
is_checkin: 0,
|
||||
created_at: DateTime.now().millisecondsSinceEpoch);
|
||||
var res = await db.insertGps(gps_data);
|
||||
//debugPrint("バックグラウンドでのGPS保存:");
|
||||
} catch (err) {
|
||||
print("errr ready gps ${err}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stopBackgroundTracking() async {
|
||||
if (Platform.isIOS && background==true) {
|
||||
background=false;
|
||||
debugPrint("バックグラウンド処理:停止しました。");
|
||||
await positionStream?.cancel();
|
||||
positionStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
class MyApp extends StatefulWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
@ -209,8 +327,11 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
||||
restoreGame();
|
||||
}
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
|
||||
debugPrint("Start MyAppState...");
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
@ -227,37 +348,69 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
LocationController locationController = Get.find<LocationController>();
|
||||
DestinationController destinationController = Get.find<DestinationController>();
|
||||
|
||||
//DestinationController destinationController =
|
||||
// Get.find<DestinationController>();
|
||||
switch (state) {
|
||||
case AppLifecycleState.resumed:
|
||||
// Foreground に戻った時の処理
|
||||
debugPrint(" ==(Status Changed)==> RESUMED. フォアグラウンドに戻りました");
|
||||
locationController.resumePositionStream();
|
||||
//print("RESUMED");
|
||||
restoreGame();
|
||||
|
||||
// バックグラウンド処理を停止
|
||||
if (Platform.isIOS && destinationController.isRunningBackgroundGPS) {
|
||||
stopBackgroundTracking();
|
||||
destinationController.isRunningBackgroundGPS=false;
|
||||
destinationController.restartGPS();
|
||||
|
||||
} else if (Platform.isAndroid) {
|
||||
const platform = MethodChannel('location');
|
||||
platform.invokeMethod('stopLocationService');
|
||||
}
|
||||
break;
|
||||
case AppLifecycleState.inactive:
|
||||
locationController.resumePositionStream();
|
||||
//print("INACTIVE");
|
||||
// アプリが非アクティブになったときに発生します。
|
||||
// これは、別のアプリやシステムのオーバーレイ(着信通話やアラームなど)によって一時的に中断された状態です。
|
||||
debugPrint(" ==(Status Changed)==> PAUSED. 非アクティブ処理。");
|
||||
//locationController.resumePositionStream();
|
||||
|
||||
// 追加: フロントエンドのGPS信号のlistenを停止
|
||||
locationController.stopPositionStream();
|
||||
|
||||
if (Platform.isIOS ) { // iOSはバックグラウンドでもフロントの処理が生きている。
|
||||
destinationController.isRunningBackgroundGPS=true;
|
||||
startBackgroundTracking();
|
||||
}else if(Platform.isAndroid){
|
||||
const platform = MethodChannel('location');
|
||||
platform.invokeMethod('startLocationService');
|
||||
}
|
||||
saveGameState();
|
||||
break;
|
||||
case AppLifecycleState.paused:
|
||||
locationController.resumePositionStream();
|
||||
//print("PAUSED");
|
||||
// バックグラウンドに移行したときの処理
|
||||
//locationController.resumePositionStream();
|
||||
debugPrint(" ==(Status Changed)==> PAUSED. バックグラウンド処理。");
|
||||
saveGameState();
|
||||
break;
|
||||
case AppLifecycleState.detached:
|
||||
locationController.resumePositionStream();
|
||||
//print("DETACHED");
|
||||
// アプリが終了する直前に発生します。この状態では、アプリはメモリから解放される予定です。
|
||||
//locationController.resumePositionStream();
|
||||
debugPrint(" ==(Status Changed)==> DETACHED アプリは終了します。");
|
||||
saveGameState();
|
||||
break;
|
||||
case AppLifecycleState.hidden:
|
||||
locationController.resumePositionStream();
|
||||
//print("DETACHED");
|
||||
// Web用の特殊な状態で、モバイルアプリでは発生しません。
|
||||
//locationController.resumePositionStream();
|
||||
debugPrint(" ==(Status Changed)==> Hidden アプリが隠れた");
|
||||
saveGameState();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GetMaterialApp(
|
||||
|
||||
Reference in New Issue
Block a user