Fixed Location Permission issue on Android - 1
This commit is contained in:
@ -9,6 +9,7 @@
|
|||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
||||||
<application
|
<application
|
||||||
android:label="岐阜ナビ"
|
android:label="岐阜ナビ"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import com.google.android.gms.location.LocationCallback
|
|||||||
import com.google.android.gms.location.LocationRequest
|
import com.google.android.gms.location.LocationRequest
|
||||||
import com.google.android.gms.location.LocationResult
|
import com.google.android.gms.location.LocationResult
|
||||||
import com.google.android.gms.location.LocationServices
|
import com.google.android.gms.location.LocationServices
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
@ -27,6 +28,7 @@ import java.util.Date
|
|||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
|
|
||||||
|
|
||||||
data class GpsData(
|
data class GpsData(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
val team_name: String,
|
val team_name: String,
|
||||||
@ -54,6 +56,7 @@ class GpsDatabaseHelper(private val context: Context) {
|
|||||||
|
|
||||||
class LocationService : Service() {
|
class LocationService : Service() {
|
||||||
private lateinit var fusedLocationClient: FusedLocationProviderClient
|
private lateinit var fusedLocationClient: FusedLocationProviderClient
|
||||||
|
private lateinit var gpsDatabaseHelper: GpsDatabaseHelper
|
||||||
|
|
||||||
override fun onBind(intent: Intent?): IBinder? {
|
override fun onBind(intent: Intent?): IBinder? {
|
||||||
return null
|
return null
|
||||||
@ -61,12 +64,13 @@ class LocationService : Service() {
|
|||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
Log.d("LocationService", "Android: onCreate.")
|
|
||||||
|
|
||||||
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
|
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
|
||||||
|
gpsDatabaseHelper = GpsDatabaseHelper.getInstance(applicationContext)
|
||||||
|
|
||||||
// 位置情報の権限チェックとGPS有効化の確認を行う
|
// 位置情報の権限チェックとGPS有効化の確認を行う
|
||||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
|
||||||
|
ContextCompat.checkSelfPermission(this, Manifest.permission.FOREGROUND_SERVICE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||||
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||||
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
|
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
|
||||||
val locationRequest = LocationRequest.create().apply {
|
val locationRequest = LocationRequest.create().apply {
|
||||||
@ -75,45 +79,37 @@ class LocationService : Service() {
|
|||||||
fastestInterval = 5000
|
fastestInterval = 5000
|
||||||
}
|
}
|
||||||
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
|
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
|
||||||
} else {
|
|
||||||
Log.d("LocationService", "GPS is disabled.")
|
|
||||||
// GPSが無効の場合の処理を追加する(例: ユーザーにGPSを有効にするように促すなど)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.d("LocationService", "Location permission is not granted.")
|
|
||||||
// 位置情報の権限が許可されていない場合の処理を追加する
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
// GPSデバイスが有効になっているか確認する
|
|
||||||
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
|
||||||
if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
|
|
||||||
Log.d("LocationService", "GPS is disabled.")
|
|
||||||
// GPSが無効の場合の処理を追加する(例: ユーザーにGPSを有効にするように促すなど)
|
|
||||||
}else{
|
|
||||||
Log.d("LocationService", "GPS is enabled.")
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// フォアグラウンドサービスの設定
|
// フォアグラウンドサービスの設定
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
val CHANNEL_ID = "location"
|
|
||||||
val channel = NotificationChannel(CHANNEL_ID, "Location", NotificationManager.IMPORTANCE_DEFAULT)
|
val channel = NotificationChannel(CHANNEL_ID, "Location", NotificationManager.IMPORTANCE_DEFAULT)
|
||||||
val notificationManager = getSystemService(NotificationManager::class.java) // この行を追加
|
val notificationManager = getSystemService(NotificationManager::class.java)
|
||||||
|
|
||||||
Log.d("LocationService", "Android: Foreground service.")
|
|
||||||
|
|
||||||
notificationManager?.createNotificationChannel(channel)
|
notificationManager?.createNotificationChannel(channel)
|
||||||
}
|
}
|
||||||
val notification = NotificationCompat.Builder(this, "location")
|
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
|
||||||
.setContentTitle("Tracking location...")
|
.setContentTitle("Tracking location...")
|
||||||
.setContentText("Location: null")
|
.setContentText("Location: null")
|
||||||
.setSmallIcon(android.R.drawable.ic_menu_mylocation) // リソースが存在しないため0を設定
|
.setSmallIcon(android.R.drawable.ic_menu_mylocation)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.build()
|
.build()
|
||||||
Log.d("LocationService", "Android: Foreground service 2.")
|
|
||||||
|
|
||||||
startForeground(1, notification)
|
startForeground(NOTIFICATION_ID, notification)
|
||||||
|
} else {
|
||||||
|
Log.d("LocationService", "GPS is disabled.")
|
||||||
|
// GPSが無効の場合の処理を追加する(例: ユーザーにGPSを有効にするように促すなど)
|
||||||
|
stopSelf() // サービスを停止する
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.d("LocationService", "Location permission or Foreground service location permission is not granted.")
|
||||||
|
// 位置情報の権限またはフォアグラウンドサービスの位置情報の権限が許可されていない場合の処理を追加する
|
||||||
|
stopSelf() // サービスを停止する
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
return START_STICKY
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
@ -170,8 +166,6 @@ class LocationService : Service() {
|
|||||||
private val locationCallback = object : LocationCallback() {
|
private val locationCallback = object : LocationCallback() {
|
||||||
override fun onLocationResult(locationResult: LocationResult) {
|
override fun onLocationResult(locationResult: LocationResult) {
|
||||||
val currentLocation = locationResult.lastLocation
|
val currentLocation = locationResult.lastLocation
|
||||||
//Log.d("LocationService", "Android: onLocationResult.")
|
|
||||||
|
|
||||||
if (currentLocation != null) {
|
if (currentLocation != null) {
|
||||||
val accuracy = currentLocation.accuracy
|
val accuracy = currentLocation.accuracy
|
||||||
if (accuracy <= 30) {
|
if (accuracy <= 30) {
|
||||||
@ -184,10 +178,9 @@ class LocationService : Service() {
|
|||||||
// GPSデータをデバッグ用に表示
|
// GPSデータをデバッグ用に表示
|
||||||
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
||||||
val formattedTime = sdf.format(Date(currentTime))
|
val formattedTime = sdf.format(Date(currentTime))
|
||||||
//Log.d("LocationService", "Latitude: $lat, Longitude: $lon, Time: $formattedTime, Accuracy: $accuracy")
|
|
||||||
|
|
||||||
// GPSデータをデータベースに保存
|
// GPSデータをデータベースに保存
|
||||||
GlobalScope.launch {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
addGPStoDB(lat, lon, currentTime)
|
addGPStoDB(lat, lon, currentTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,36 +196,16 @@ class LocationService : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
Log.d("LocationService", "Android: onStartCommand.")
|
Log.d("LocationService", "Android: onStartCommand.")
|
||||||
|
|
||||||
/* onCreate でやってるので除外。
|
|
||||||
// 位置情報の権限チェックとGPS有効化の確認を行う
|
|
||||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
|
||||||
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
|
||||||
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
|
|
||||||
val locationRequest = LocationRequest.create().apply {
|
|
||||||
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
|
|
||||||
interval = 10000
|
|
||||||
fastestInterval = 5000
|
|
||||||
}
|
|
||||||
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
|
|
||||||
} else {
|
|
||||||
Log.d("LocationService", "GPS is disabled.")
|
|
||||||
// GPSが無効の場合の処理を追加する(例: ユーザーにGPSを有効にするように促すなど)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.d("LocationService", "Location permission is not granted.")
|
|
||||||
// 位置情報の権限が許可されていない場合の処理を追加する
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Foregroundサービスを開始
|
// Foregroundサービスを開始
|
||||||
startForeground(NOTIFICATION_ID, createNotification())
|
startForeground(NOTIFICATION_ID, createNotification())
|
||||||
|
|
||||||
return START_STICKY
|
return START_STICKY
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
private suspend fun addGPStoDB(lat: Double, lng: Double, timestamp: Long, isCheckin: Int = 0) {
|
private suspend fun addGPStoDB(lat: Double, lng: Double, timestamp: Long, isCheckin: Int = 0) {
|
||||||
try {
|
try {
|
||||||
@ -241,7 +214,6 @@ class LocationService : Service() {
|
|||||||
val teamName = preferences.getString("team_name", "") ?: ""
|
val teamName = preferences.getString("team_name", "") ?: ""
|
||||||
val eventCode = preferences.getString("event_code", "") ?: ""
|
val eventCode = preferences.getString("event_code", "") ?: ""
|
||||||
|
|
||||||
|
|
||||||
if (teamName.isNotEmpty() && eventCode.isNotEmpty()) {
|
if (teamName.isNotEmpty() && eventCode.isNotEmpty()) {
|
||||||
val gpsData = GpsData(
|
val gpsData = GpsData(
|
||||||
id = 0,
|
id = 0,
|
||||||
@ -253,13 +225,12 @@ class LocationService : Service() {
|
|||||||
created_at = timestamp
|
created_at = timestamp
|
||||||
)
|
)
|
||||||
|
|
||||||
val db = GpsDatabaseHelper.getInstance(context)
|
gpsDatabaseHelper.insertGps(gpsData)
|
||||||
db.insertGps(gpsData)
|
|
||||||
Log.d("LocationService", "Android: addGPStoDB.")
|
Log.d("LocationService", "Android: addGPStoDB.")
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("LocationService", "Error adding GPS data to DB", e)
|
Log.e("LocationService", "Error adding GPS data to DB", e)
|
||||||
|
// エラーメッセージをユーザーに表示するなどの処理を追加
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,6 +36,11 @@ class MainActivity: FlutterActivity() {
|
|||||||
stopLocationService()
|
stopLocationService()
|
||||||
result.success(null)
|
result.success(null)
|
||||||
}
|
}
|
||||||
|
"isLocationServiceRunning" -> {
|
||||||
|
Log.d("MainActivity", "Android: called isLocationServiceRunnung.")
|
||||||
|
val isRunning = isServiceRunning(LocationService::class.java)
|
||||||
|
result.success(isRunning)
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
result.notImplemented()
|
result.notImplemented()
|
||||||
}
|
}
|
||||||
@ -75,9 +80,8 @@ class MainActivity: FlutterActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun startLocationService() {
|
private fun startLocationService() {
|
||||||
Log.d("MainActivity", "Android: startLocationService.")
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
|
||||||
|
ContextCompat.checkSelfPermission(this, Manifest.permission.FOREGROUND_SERVICE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
|
||||||
if (!isServiceRunning(LocationService::class.java)) {
|
if (!isServiceRunning(LocationService::class.java)) {
|
||||||
val intent = Intent(this, LocationService::class.java)
|
val intent = Intent(this, LocationService::class.java)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
@ -91,16 +95,19 @@ class MainActivity: FlutterActivity() {
|
|||||||
Log.d("MainActivity", "Location service is already running.")
|
Log.d("MainActivity", "Location service is already running.")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d("MainActivity", "Location permission is not granted.")
|
Log.d("MainActivity", "Location permission or Foreground service location permission is not granted.")
|
||||||
// 位置情報の権限が許可されていない場合の処理を追加する
|
// 位置情報の権限またはフォアグラウンドサービスの位置情報の権限が許可されていない場合の処理を追加する
|
||||||
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), PERMISSION_REQUEST_CODE)
|
// 例: ユーザーに権限の必要性を説明し、許可を求めるダイアログを表示するなど
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stopLocationService() {
|
private fun stopLocationService() {
|
||||||
Log.d("MainActivity", "Android: stopLocationService.")
|
if (isServiceRunning(LocationService::class.java)) {
|
||||||
val intent = Intent(this, LocationService::class.java)
|
val intent = Intent(this, LocationService::class.java)
|
||||||
stopService(intent)
|
stopService(intent)
|
||||||
|
} else {
|
||||||
|
Log.d("MainActivity", "Location service is not running.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isServiceRunning(serviceClass: Class<*>): Boolean {
|
private fun isServiceRunning(serviceClass: Class<*>): Boolean {
|
||||||
|
|||||||
@ -8,6 +8,32 @@ import Flutter
|
|||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
|
|
||||||
|
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
|
||||||
|
let locationServiceChannel = FlutterMethodChannel(name: "location",
|
||||||
|
binaryMessenger: controller.binaryMessenger)
|
||||||
|
locationServiceChannel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
|
||||||
|
if call.method == "isLocationServiceRunning" {
|
||||||
|
result(self.isLocationServiceRunning())
|
||||||
|
} else {
|
||||||
|
result(FlutterMethodNotImplemented)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
locationManager = CLLocationManager()
|
||||||
|
locationManager?.delegate = self
|
||||||
|
locationManager?.requestAlwaysAuthorization()
|
||||||
|
locationManager?.startUpdatingLocation()
|
||||||
|
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func isLocationServiceRunning() -> Bool {
|
||||||
|
guard let locationManager = locationManager else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let isRunning = locationManager.monitoredRegions.count > 0 || locationManager.location != nil
|
||||||
|
return isRunning
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import 'dart:io';
|
|||||||
//import 'dart:convert';
|
//import 'dart:convert';
|
||||||
//import 'dart:developer';
|
//import 'dart:developer';
|
||||||
import 'package:rogapp/model/gps_data.dart';
|
import 'package:rogapp/model/gps_data.dart';
|
||||||
|
import 'package:rogapp/pages/home/home_page.dart';
|
||||||
import 'package:rogapp/utils/database_gps.dart';
|
import 'package:rogapp/utils/database_gps.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart';
|
import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart';
|
||||||
@ -31,6 +32,8 @@ import 'package:flutter/services.dart';
|
|||||||
|
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
|
import 'pages/permission/permission.dart';
|
||||||
|
|
||||||
|
|
||||||
Map<String, dynamic> deviceInfo = {};
|
Map<String, dynamic> deviceInfo = {};
|
||||||
|
|
||||||
@ -129,7 +132,10 @@ void main() async {
|
|||||||
|
|
||||||
//Get.put(LocationController());
|
//Get.put(LocationController());
|
||||||
|
|
||||||
requestLocationPermission();
|
//await PermissionController.checkAndRequestPermissions();
|
||||||
|
//requestLocationPermission();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// startMemoryMonitoring(); // 2024-4-8 Akira: メモリ使用量のチェックを開始 See #2810
|
// startMemoryMonitoring(); // 2024-4-8 Akira: メモリ使用量のチェックを開始 See #2810
|
||||||
Get.put(SettingsController()); // これを追加
|
Get.put(SettingsController()); // これを追加
|
||||||
@ -143,10 +149,11 @@ void main() async {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
runApp(const ProviderScope(child: MyApp()));
|
runApp(const ProviderScope(child: MyApp()));
|
||||||
|
//runApp(HomePage()); // MyApp()からHomePage()に変更
|
||||||
//runApp(const MyApp());
|
//runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
Future<void> requestLocationPermission() async {
|
Future<void> requestLocationPermission() async {
|
||||||
try {
|
try {
|
||||||
final status = await Permission.locationAlways.request();
|
final status = await Permission.locationAlways.request();
|
||||||
@ -160,6 +167,7 @@ Future<void> requestLocationPermission() async {
|
|||||||
print('Error requesting location permission: $e');
|
print('Error requesting location permission: $e');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
// メモリ使用量の解説:https://qiita.com/hukusuke1007/items/e4e987836412e9bc73b9
|
// メモリ使用量の解説:https://qiita.com/hukusuke1007/items/e4e987836412e9bc73b9
|
||||||
@ -289,6 +297,16 @@ Future<void> startBackgroundTracking() async {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error starting background tracking: $e');
|
print('Error starting background tracking: $e');
|
||||||
}
|
}
|
||||||
|
}else if (Platform.isAndroid && background == false) {
|
||||||
|
background = true;
|
||||||
|
debugPrint("バックグラウンド処理を開始しました。");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 位置情報の権限が許可されているかを確認
|
||||||
|
await PermissionController.checkAndRequestPermissions();
|
||||||
|
}catch(e){
|
||||||
|
print('Error starting background tracking: $e');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,8 +339,12 @@ Future<void> stopBackgroundTracking() async {
|
|||||||
}else if(Platform.isAndroid && background==true){
|
}else if(Platform.isAndroid && background==true){
|
||||||
background=false;
|
background=false;
|
||||||
debugPrint("バックグラウンド処理:停止しました。");
|
debugPrint("バックグラウンド処理:停止しました。");
|
||||||
await positionStream?.cancel();
|
const platform = MethodChannel('location');
|
||||||
positionStream = null;
|
try {
|
||||||
|
await platform.invokeMethod('stopLocationService');
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
print("Failed to stop location service: '${e.message}'.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,6 +366,12 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
}
|
}
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
|
|
||||||
|
/*
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
|
await PermissionController.checkAndRequestPermissions();
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
debugPrint("Start MyAppState...");
|
debugPrint("Start MyAppState...");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,6 +486,7 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return GetMaterialApp(
|
return GetMaterialApp(
|
||||||
translations: StringValues(),
|
translations: StringValues(),
|
||||||
locale: const Locale('ja', 'JP'),
|
locale: const Locale('ja', 'JP'),
|
||||||
@ -480,4 +509,7 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||||||
enableLog: true,
|
enableLog: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,8 @@ import 'package:image_gallery_saver/image_gallery_saver.dart';
|
|||||||
import 'package:rogapp/utils/const.dart';
|
import 'package:rogapp/utils/const.dart';
|
||||||
import 'package:logger/logger.dart';
|
import 'package:logger/logger.dart';
|
||||||
|
|
||||||
|
import 'package:rogapp/pages/permission/permission.dart';
|
||||||
|
|
||||||
// 目的地に関連する状態管理とロジックを担当するクラスです。
|
// 目的地に関連する状態管理とロジックを担当するクラスです。
|
||||||
//
|
//
|
||||||
class DestinationController extends GetxController {
|
class DestinationController extends GetxController {
|
||||||
@ -1265,6 +1267,12 @@ class DestinationController extends GetxController {
|
|||||||
void onInit() async {
|
void onInit() async {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
|
|
||||||
|
/*
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
|
await PermissionController.checkAndRequestPermissions();
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
startGPSCheckTimer();
|
startGPSCheckTimer();
|
||||||
|
|
||||||
// MapControllerの初期化完了を待機するフラグを設定
|
// MapControllerの初期化完了を待機するフラグを設定
|
||||||
@ -1715,6 +1723,7 @@ class DestinationController extends GetxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// 位置情報の許可を確認する関数です。
|
// 位置情報の許可を確認する関数です。
|
||||||
//
|
//
|
||||||
void checkPermission() async {
|
void checkPermission() async {
|
||||||
@ -1726,6 +1735,7 @@ class DestinationController extends GetxController {
|
|||||||
permission = await Geolocator.requestPermission();
|
permission = await Geolocator.requestPermission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// IDに基づいて目的地を取得する関数です。
|
// IDに基づいて目的地を取得する関数です。
|
||||||
//
|
//
|
||||||
|
|||||||
@ -15,6 +15,11 @@ class _HomePageState extends State<HomePage> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
/*
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
_checkLocationService(); // 非同期的に呼び出す
|
||||||
|
});
|
||||||
|
*/
|
||||||
_checkLocationService();
|
_checkLocationService();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -190,11 +190,15 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
void checkPermission()
|
void checkPermission()
|
||||||
{
|
{
|
||||||
debugPrint("MapControllerの初期化が完了したら、位置情報の許可をチェックする");
|
debugPrint("MapControllerの初期化が完了したら、位置情報の許可をチェックする");
|
||||||
_checkLocationPermission();
|
_checkLocationPermission();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
|
|||||||
@ -1,78 +1,156 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:rogapp/routes/app_pages.dart';
|
import 'package:rogapp/services/location_service.dart';
|
||||||
|
import 'dart:developer' as developer;
|
||||||
|
|
||||||
class PermissionHandlerScreen extends StatefulWidget {
|
|
||||||
const PermissionHandlerScreen({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
class PermissionController {
|
||||||
_PermissionHandlerScreenState createState() =>
|
|
||||||
_PermissionHandlerScreenState();
|
static Future<bool> checkLocationPermissions() async {
|
||||||
|
debugPrint("(gifunavi)== checkLocationPermissions ==");
|
||||||
|
final alwaysPermission = await Permission.locationAlways.status;
|
||||||
|
final whenInUsePermission = await Permission.locationWhenInUse.status;
|
||||||
|
final locationPermission = await Permission.location.status;
|
||||||
|
|
||||||
|
return (alwaysPermission == PermissionStatus.granted || whenInUsePermission == PermissionStatus.granted) &&
|
||||||
|
(locationPermission == PermissionStatus.granted);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PermissionHandlerScreenState extends State<PermissionHandlerScreen> {
|
static Future<bool> checkLocationBasicPermission() async {
|
||||||
@override
|
debugPrint("(gifunavi)== checkLocationBasicPermission ==");
|
||||||
void initState() {
|
final locationPermission = await Permission.location.status;
|
||||||
super.initState();
|
return locationPermission == PermissionStatus.granted;
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
_checkPermissionStatus();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _checkPermissionStatus() async {
|
static Future<bool> checkLocationWhenInUsePermission() async {
|
||||||
PermissionStatus status = await Permission.location.status;
|
debugPrint("(gifunavi)== checkLocationWhenInUsePermission ==");
|
||||||
|
final whenInUsePermission = await Permission.locationWhenInUse.status;
|
||||||
if (status.isGranted) {
|
return whenInUsePermission == PermissionStatus.granted;
|
||||||
if (context.mounted) {
|
|
||||||
Get.offNamed(AppPages.LOGIN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<bool> checkLocationAlwaysPermission() async {
|
||||||
|
debugPrint("(gifunavi)== checkLocationAlwaysPermission ==");
|
||||||
|
final alwaysPermission = await Permission.locationAlways.status;
|
||||||
|
return alwaysPermission == PermissionStatus.granted;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isBasicPermission=false;
|
||||||
|
static Future<void> requestLocationBasicPermissions() async {
|
||||||
|
debugPrint("(gifunavi)== requestLocationBasicPermissions ==");
|
||||||
|
try{
|
||||||
|
if(!isBasicPermission){
|
||||||
|
isBasicPermission=true;
|
||||||
|
final locationStatus = await Permission.location.request();
|
||||||
|
|
||||||
|
if (locationStatus != PermissionStatus.granted) {
|
||||||
|
showPermissionDeniedDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch (e, stackTrace){
|
||||||
|
print('Exception: $e');
|
||||||
|
print('Stack trace: $stackTrace');
|
||||||
|
debugPrintStack(label: 'Exception occurred', stackTrace: stackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isLocationServiceRunning = false;
|
||||||
|
static bool isRequestedWhenInUsePermission = false;
|
||||||
|
|
||||||
|
static Future<void> requestLocationWhenInUsePermissions() async {
|
||||||
|
debugPrint("(gifunavi)== requestLocationWhenInUsePermissions ==");
|
||||||
|
|
||||||
|
try{
|
||||||
|
if(!isRequestedWhenInUsePermission){
|
||||||
|
isRequestedWhenInUsePermission=true;
|
||||||
|
final whenInUseStatus = await Permission.locationWhenInUse.request();
|
||||||
|
|
||||||
|
if (whenInUseStatus != PermissionStatus.granted) {
|
||||||
|
showPermissionDeniedDialog();
|
||||||
}else{
|
}else{
|
||||||
if (context.mounted) {
|
if( !isLocationServiceRunning ){
|
||||||
_showPermissionRequestDialog();
|
isLocationServiceRunning=true;
|
||||||
|
const platform = MethodChannel('location');
|
||||||
|
try {
|
||||||
|
await platform.invokeMethod('startLocationService'); // Location Service を開始する。
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
debugPrint("Failed to start location service: '${e.message}'.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}catch (e, stackTrace){
|
||||||
|
debugPrint('Exception: $e');
|
||||||
|
debugPrint('Stack trace: $stackTrace');
|
||||||
|
debugPrintStack(label: 'Exception occurred', stackTrace: stackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isRequestedAlwaysPermission = false;
|
||||||
|
|
||||||
|
static Future<void> requestLocationAlwaysPermissions() async {
|
||||||
|
debugPrint("(gifunavi)== requestLocationAlwaysPermissions ==");
|
||||||
|
|
||||||
|
try {
|
||||||
|
if( !isRequestedAlwaysPermission ){
|
||||||
|
isRequestedAlwaysPermission=true;
|
||||||
|
final alwaysStatus = await Permission.locationAlways.request();
|
||||||
|
|
||||||
|
if (alwaysStatus != PermissionStatus.granted) {
|
||||||
|
showPermissionDeniedDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch (e, stackTrace){
|
||||||
|
print('Exception: $e');
|
||||||
|
print('Stack trace: $stackTrace');
|
||||||
|
debugPrintStack(label: 'Exception occurred', stackTrace: stackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> checkAndRequestPermissions() async {
|
||||||
|
final hasPermissions = await checkLocationBasicPermission();
|
||||||
|
if (!hasPermissions) {
|
||||||
|
await requestLocationBasicPermissions();
|
||||||
|
}
|
||||||
|
|
||||||
|
final hasWIUPermissions = await checkLocationWhenInUsePermission();
|
||||||
|
if (!hasWIUPermissions) {
|
||||||
|
await requestLocationWhenInUsePermissions();
|
||||||
|
}
|
||||||
|
|
||||||
|
final hasAlwaysPermissions = await checkLocationAlwaysPermission();
|
||||||
|
if (!hasAlwaysPermissions) {
|
||||||
|
await requestLocationAlwaysPermissions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _showPermissionRequestDialog() {
|
static void showPermissionDeniedDialog() {
|
||||||
showDialog(
|
Get.dialog(
|
||||||
context: context,
|
AlertDialog(
|
||||||
builder: (BuildContext context) {
|
title: Text('location_permission_needed_title'.tr),
|
||||||
return AlertDialog(
|
// 位置情報への許可が必要です
|
||||||
title: Text('location_permission_required_title'.tr),
|
content: Text('location_permission_needed_main'.tr),
|
||||||
content: Text('location_permission_required_message'.tr),
|
// 岐阜ロゲでは、位置情報を使用してスタート・チェックイン・ゴール等の通過照明及び移動手段の記録のために、位置情報のトラッキングを行なっています。このためバックグラウンドでもトラッキングができるように位置情報の権限が必要です。
|
||||||
|
// 設定画面で、「岐阜ナビ」に対して、常に位置情報を許可するように設定してください。
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text('cancel'.tr),
|
child: Text('キャンセル'),
|
||||||
onPressed: () {
|
onPressed: () => Get.back(),
|
||||||
Navigator.of(context).pop();
|
|
||||||
Get.offNamed(AppPages.HOME);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text('ok'.tr),
|
child: Text('設定'),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Get.back();
|
||||||
_requestLocationPermission();
|
openAppSettings();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
),
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _requestLocationPermission() async {
|
|
||||||
final status = await Permission.location.request();
|
|
||||||
if (status.isGranted) {
|
|
||||||
Get.offNamed(AppPages.LOGIN);
|
|
||||||
} else {
|
|
||||||
Get.offNamed(AppPages.HOME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(body: Container());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,188 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
|
||||||
import 'package:rogapp/routes/app_pages.dart';
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
class PermissionHandlerScreen extends StatefulWidget {
|
|
||||||
const PermissionHandlerScreen({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<PermissionHandlerScreen> createState() =>
|
|
||||||
_PermissionHandlerScreenState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PermissionHandlerScreenState extends State<PermissionHandlerScreen> {
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
_checkPermissionStatus();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _checkPermissionStatus() async {
|
|
||||||
PermissionStatus status = await Permission.location.status;
|
|
||||||
|
|
||||||
if (status.isGranted) {
|
|
||||||
if (context.mounted) {
|
|
||||||
Get.toNamed(AppPages.LOGIN);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (context.mounted) {
|
|
||||||
Get.toNamed(AppPages.HOME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
_checkPermissionStatus() async {
|
|
||||||
PermissionStatus status = await Permission.location.status;
|
|
||||||
|
|
||||||
if (status.isGranted == false) {
|
|
||||||
if (context.mounted) {
|
|
||||||
showAlert(context);
|
|
||||||
}
|
|
||||||
} else if (status.isPermanentlyDenied) {
|
|
||||||
await requestPermission();
|
|
||||||
} else {
|
|
||||||
if (mounted) {
|
|
||||||
Get.toNamed(AppPages.LOGIN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void showAlert(BuildContext context) {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (_) => AlertDialog(
|
|
||||||
title: Text('location_permission_title'.tr),
|
|
||||||
content: SingleChildScrollView(
|
|
||||||
child: Text('location_permission_content'.tr),
|
|
||||||
|
|
||||||
),
|
|
||||||
actions: <Widget>[
|
|
||||||
ElevatedButton(
|
|
||||||
child: const Text('OK'),
|
|
||||||
onPressed: () {
|
|
||||||
Get.back();
|
|
||||||
requestPermission();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 要検討:位置情報の許可が拒否された場合、適切なエラーメッセージを表示することを検討してください。
|
|
||||||
//
|
|
||||||
/*
|
|
||||||
Future<void> requestPermission() async {
|
|
||||||
PermissionStatus permission = await Permission.location.status;
|
|
||||||
if (permission == PermissionStatus.permanentlyDenied) {
|
|
||||||
showPermanentAlert();
|
|
||||||
} else {
|
|
||||||
PermissionStatus newPermission = await Permission.location.request();
|
|
||||||
if (newPermission != PermissionStatus.granted) {
|
|
||||||
exit(0);
|
|
||||||
} else {
|
|
||||||
if (context.mounted) {
|
|
||||||
Get.toNamed(AppPages.LOGIN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Future<void> requestPermission() async {
|
|
||||||
PermissionStatus permission = await Permission.location.request();
|
|
||||||
if (permission == PermissionStatus.granted) {
|
|
||||||
if (context.mounted) {
|
|
||||||
Get.toNamed(AppPages.LOGIN);
|
|
||||||
}
|
|
||||||
} else if (permission == PermissionStatus.denied) {
|
|
||||||
await showLocationPermissionDeniedDialog();
|
|
||||||
} else if (permission == PermissionStatus.permanentlyDenied) {
|
|
||||||
await showPermanentlyDeniedDialog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> showLocationPermissionDeniedDialog() async {
|
|
||||||
await showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return AlertDialog(
|
|
||||||
title: Text('location_permission_denied_title'.tr),
|
|
||||||
content: Text('location_permission_denied_message'.tr),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
child: Text('ok'.tr),
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> showPermanentlyDeniedDialog() async {
|
|
||||||
await showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return AlertDialog(
|
|
||||||
title: Text('location_permission_permanently_denied_title'.tr),
|
|
||||||
content: Text('location_permission_permanently_denied_message'.tr),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
child: Text('open_settings'.tr),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
openAppSettings();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return const Scaffold(
|
|
||||||
body: Text(""),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 要検討:ユーザーが位置情報の許可を拒否し続けた場合の対処方法を明確にすることをお勧めします。
|
|
||||||
//
|
|
||||||
void showPermanentAlert() {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (_) => AlertDialog(
|
|
||||||
title: Text('location_disabled_title'.tr),
|
|
||||||
content: SingleChildScrollView(
|
|
||||||
child: Text('location_disabled_content'.tr),
|
|
||||||
|
|
||||||
),
|
|
||||||
actions: <Widget>[
|
|
||||||
ElevatedButton(
|
|
||||||
child: const Text('OK'),
|
|
||||||
onPressed: () async {
|
|
||||||
await openAppSettings().then(
|
|
||||||
(value) async {
|
|
||||||
if (value) {
|
|
||||||
if (await Permission
|
|
||||||
.location.status.isPermanentlyDenied ==
|
|
||||||
true &&
|
|
||||||
await Permission.location.status.isGranted ==
|
|
||||||
false) {
|
|
||||||
requestPermission(); /* opens app settings until permission is granted */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -26,6 +26,7 @@ import 'package:rogapp/pages/debug/debug_binding.dart';
|
|||||||
import 'package:rogapp/pages/subperf/subperf_page.dart';
|
import 'package:rogapp/pages/subperf/subperf_page.dart';
|
||||||
import 'package:rogapp/spa/spa_binding.dart';
|
import 'package:rogapp/spa/spa_binding.dart';
|
||||||
import 'package:rogapp/spa/spa_page.dart';
|
import 'package:rogapp/spa/spa_page.dart';
|
||||||
|
import 'package:rogapp/widgets/permission_handler_screen.dart';
|
||||||
|
|
||||||
part 'app_routes.dart';
|
part 'app_routes.dart';
|
||||||
|
|
||||||
@ -42,6 +43,7 @@ class AppPages {
|
|||||||
static const DESTINATION_MAP = Routes.DESTINATION_MAP;
|
static const DESTINATION_MAP = Routes.DESTINATION_MAP;
|
||||||
static const HOME = Routes.HOME;
|
static const HOME = Routes.HOME;
|
||||||
static const PERMISSION = Routes.PERMISSION;
|
static const PERMISSION = Routes.PERMISSION;
|
||||||
|
//static const PERMISSION = Routes.HOME;
|
||||||
static const SEARCH = Routes.SEARCH;
|
static const SEARCH = Routes.SEARCH;
|
||||||
static const MAINPERF = Routes.MAINPERF;
|
static const MAINPERF = Routes.MAINPERF;
|
||||||
static const SUBPERF = Routes.SUBPERF;
|
static const SUBPERF = Routes.SUBPERF;
|
||||||
@ -88,7 +90,7 @@ class AppPages {
|
|||||||
),
|
),
|
||||||
GetPage(
|
GetPage(
|
||||||
name: Routes.PERMISSION,
|
name: Routes.PERMISSION,
|
||||||
page: () => const PermissionHandlerScreen(),
|
page: () => PermissionHandlerScreen(),
|
||||||
),
|
),
|
||||||
GetPage(
|
GetPage(
|
||||||
name: Routes.SEARCH,
|
name: Routes.SEARCH,
|
||||||
@ -127,4 +129,5 @@ class AppPages {
|
|||||||
),
|
),
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:geojson_vi/geojson_vi.dart';
|
import 'package:geojson_vi/geojson_vi.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
@ -9,6 +10,7 @@ import 'package:rogapp/utils/const.dart';
|
|||||||
class LocationService {
|
class LocationService {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Future<GeoJSONFeatureCollection?> loadLocationsFor(
|
static Future<GeoJSONFeatureCollection?> loadLocationsFor(
|
||||||
String perfecture, String cat) async {
|
String perfecture, String cat) async {
|
||||||
final IndexController indexController = Get.find<IndexController>();
|
final IndexController indexController = Get.find<IndexController>();
|
||||||
@ -187,4 +189,16 @@ class LocationService {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const platform = MethodChannel('location');
|
||||||
|
|
||||||
|
static Future<bool> isLocationServiceRunning() async {
|
||||||
|
try {
|
||||||
|
final bool isRunning = await platform.invokeMethod('isLocationServiceRunning');
|
||||||
|
return isRunning;
|
||||||
|
} catch (e) {
|
||||||
|
print("Failed to check if location service is running: $e");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import 'package:latlong2/latlong.dart';
|
|||||||
//import 'package:rogapp/widgets/debug_widget.dart';
|
//import 'package:rogapp/widgets/debug_widget.dart';
|
||||||
import 'package:flutter_map_location_marker/flutter_map_location_marker.dart';
|
import 'package:flutter_map_location_marker/flutter_map_location_marker.dart';
|
||||||
import 'package:rogapp/pages/destination/destination_controller.dart';
|
import 'package:rogapp/pages/destination/destination_controller.dart';
|
||||||
|
import 'package:rogapp/pages/permission/permission.dart';
|
||||||
|
|
||||||
// LocationControllerクラスは、GetxControllerを継承したクラスであり、位置情報の管理を担当しています。
|
// LocationControllerクラスは、GetxControllerを継承したクラスであり、位置情報の管理を担当しています。
|
||||||
// LocationControllerは以下の機能を提供しています。
|
// LocationControllerは以下の機能を提供しています。
|
||||||
@ -188,6 +189,18 @@ class LocationController extends GetxController {
|
|||||||
// Check for location service and permissions before starting the stream
|
// Check for location service and permissions before starting the stream
|
||||||
// 位置情報サービスの有効性をチェックし、無効な場合はエラーハンドリングを行います。
|
// 位置情報サービスの有効性をチェックし、無効な場合はエラーハンドリングを行います。
|
||||||
//
|
//
|
||||||
|
|
||||||
|
await PermissionController.checkAndRequestPermissions();
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool isPermissionGranted = await PermissionController.checkLocationPermissions();
|
||||||
|
if (!isPermissionGranted) {
|
||||||
|
PermissionController.showPermissionDeniedDialog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||||
if (!serviceEnabled) {
|
if (!serviceEnabled) {
|
||||||
// Use GetX's context to show a dialog
|
// Use GetX's context to show a dialog
|
||||||
@ -262,6 +275,7 @@ class LocationController extends GetxController {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// 位置情報の設定を行います。z11
|
// 位置情報の設定を行います。z11
|
||||||
// Set up the location options
|
// Set up the location options
|
||||||
|
|||||||
@ -391,7 +391,7 @@ class StringValues extends Translations{
|
|||||||
'location_permission_permanently_denied_message': '位置情報の許可が永久に拒否されました。位置情報の許可を付与するには、アプリ設定を開いてください。',
|
'location_permission_permanently_denied_message': '位置情報の許可が永久に拒否されました。位置情報の許可を付与するには、アプリ設定を開いてください。',
|
||||||
'open_settings': '設定を開く',
|
'open_settings': '設定を開く',
|
||||||
'location_permission_needed_title': '位置情報への許可が必要です',
|
'location_permission_needed_title': '位置情報への許可が必要です',
|
||||||
'location_permission_needed_main': '位置情報への許可が拒否されています。設定を開いて、位置情報の許可を「岐阜ナビ」に与えてください。',
|
'location_permission_needed_main': '岐阜ロゲでは、位置情報を使用してスタート・チェックイン・ゴール等の通過照明及び移動手段の記録のために、位置情報のトラッキングを行なっています。このためバックグラウンドでもトラッキングができるように位置情報の権限が必要です。設定画面で、「岐阜ナビ」に対して、常に位置情報を許可するように設定してください。',
|
||||||
'open_settings': '設定を開く',
|
'open_settings': '設定を開く',
|
||||||
'location_permission_denied_title': '位置情報へのアクセスが拒否されています。',
|
'location_permission_denied_title': '位置情報へのアクセスが拒否されています。',
|
||||||
'location_permission_denied_main': 'この岐阜ナビアプリは正常に動かすには位置情報への許可が必要です。「設定」画面で位置情報の許可を指定してください。',
|
'location_permission_denied_main': 'この岐阜ナビアプリは正常に動かすには位置情報への許可が必要です。「設定」画面で位置情報の許可を指定してください。',
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:rogapp/pages/destination/destination_controller.dart';
|
import 'package:rogapp/pages/destination/destination_controller.dart';
|
||||||
import 'package:rogapp/routes/app_pages.dart'; // これを追加
|
import 'package:rogapp/routes/app_pages.dart'; // これを追加
|
||||||
|
|
||||||
@ -14,8 +15,34 @@ class _CurrentPositionState extends State<CurrentPosition> {
|
|||||||
final DestinationController destinationController =
|
final DestinationController destinationController =
|
||||||
Get.find<DestinationController>();
|
Get.find<DestinationController>();
|
||||||
|
|
||||||
void _onLongPress() {
|
void _onLongPress() async {
|
||||||
Get.toNamed(AppPages.SETTINGS); // これを追加
|
PermissionStatus status = await Permission.location.status;
|
||||||
|
if (!status.isGranted) {
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text('位置情報の許可が必要です'),
|
||||||
|
content: Text('現在位置を表示するには、位置情報の許可が必要です。「設定」からアプリの権限を許可してください。'),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: Text('キャンセル'),
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: Text('設定'),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
openAppSettings();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Get.toNamed(AppPages.SETTINGS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import 'package:flutter_polyline_points/flutter_polyline_points.dart';
|
|||||||
import 'package:geojson_vi/geojson_vi.dart';
|
import 'package:geojson_vi/geojson_vi.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
|
import 'package:rogapp/pages/permission/permission.dart';
|
||||||
import 'package:rogapp/pages/settings/settings_binding.dart';
|
import 'package:rogapp/pages/settings/settings_binding.dart';
|
||||||
import 'package:rogapp/model/destination.dart';
|
import 'package:rogapp/model/destination.dart';
|
||||||
import 'package:rogapp/pages/destination/destination_controller.dart';
|
import 'package:rogapp/pages/destination/destination_controller.dart';
|
||||||
@ -75,7 +76,8 @@ class _MapWidgetState extends State<MapWidget> with WidgetsBindingObserver {
|
|||||||
indexController.isMapControllerReady.value = true;
|
indexController.isMapControllerReady.value = true;
|
||||||
});
|
});
|
||||||
// MapControllerの初期化が完了したら、IndexControllerのonInitを呼び出す
|
// MapControllerの初期化が完了したら、IndexControllerのonInitを呼び出す
|
||||||
indexController.checkPermission();
|
//indexController.checkPermission();
|
||||||
|
PermissionController.checkAndRequestPermissions();
|
||||||
});
|
});
|
||||||
|
|
||||||
late MapResetController mapResetController = MapResetController();
|
late MapResetController mapResetController = MapResetController();
|
||||||
|
|||||||
31
lib/widgets/permission_handler_screen.dart
Normal file
31
lib/widgets/permission_handler_screen.dart
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:rogapp/pages/permission/permission.dart';
|
||||||
|
|
||||||
|
class PermissionHandlerScreen extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_PermissionHandlerScreenState createState() => _PermissionHandlerScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PermissionHandlerScreenState extends State<PermissionHandlerScreen> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
|
await PermissionController.checkAndRequestPermissions();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text('権限の確認'),
|
||||||
|
),
|
||||||
|
body: Center(
|
||||||
|
child: Text('権限の確認中...'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -760,6 +760,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2+1"
|
version: "2.0.2+1"
|
||||||
|
logging:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: logging
|
||||||
|
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@ -38,6 +38,7 @@ dependencies:
|
|||||||
flutter_map: ^6.0.1
|
flutter_map: ^6.0.1
|
||||||
geolocator: ^10.1.0
|
geolocator: ^10.1.0
|
||||||
permission_handler: ^11.3.1
|
permission_handler: ^11.3.1
|
||||||
|
logging: ^1.0.2
|
||||||
# flutter_dev_tools: ^0.0.2
|
# flutter_dev_tools: ^0.0.2
|
||||||
# permission_handler: ^11.1.0 <== older
|
# permission_handler: ^11.1.0 <== older
|
||||||
# permission_handler 11.2.0 (11.3.1 available)
|
# permission_handler 11.2.0 (11.3.1 available)
|
||||||
|
|||||||
Reference in New Issue
Block a user