Files
rog_app/lib/pages/permission/permission.dart
2024-09-08 18:16:51 +09:00

502 lines
16 KiB
Dart
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:geolocator/geolocator.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'dart:async';
import 'package:shared_preferences/shared_preferences.dart';
class PermissionController {
static bool? _locationPermissionGranted;
/*
bool? _isRequestingPermission=false;
final Completer<PermissionController> _permissionCompleter = Completer<PermissionController>();
*/
static Future<bool> checkAndRequestPermissions_new() async {
try {
if (_locationPermissionGranted != null) {
return _locationPermissionGranted!;
}
var serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
Get.snackbar(
'エラー', '位置情報サービスが無効です。設定から有効にしてください。');
// 位置情報サービスが無効の場合、ユーザーに有効化を促す
return false;
}
debugPrint("====> Geolocator.checkPermission");
var permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
Get.snackbar('エラー', '位置情報の許可が拒否されました。');
return false;
}
}
if (permission == LocationPermission.deniedForever) {
Get.snackbar('エラー',
'位置情報の許可が永久に拒否されました。設定から許可してください。');
return false;
}
_locationPermissionGranted = true;
return true;
} catch (e) {
print('Error checking permissions: $e');
Get.snackbar('エラー', '権限の確認中にエラーが発生しました。');
return false;
}
}
static void resetPermissionCache() {
_locationPermissionGranted = null;
}
static Future<bool> _requestLocationPermission() async {
BuildContext? context;
int attempts = 0;
const maxAttempts = 10;
debugPrint("====> _requestLocationPermission");
// コンテキストが利用可能になるまで待機するロジック
while (Get.context == null && attempts < maxAttempts) {
context = Get.context;
if (context == null) {
await Future.delayed(const Duration(milliseconds: 500));
attempts++;
}
}
if (Get.context == null) {
print('Context is still null after waiting, cannot proceed with permission check');
return false;
}
try {
bool hasPermissions = await _checkLocationPermissions();
if (!hasPermissions) {
bool userAgreed = await showLocationDisclosure();
if (userAgreed) {
if (Platform.isAndroid && !await _isAndroid13OrAbove()) {
hasPermissions = await _requestAndroidPreS();
} else {
hasPermissions = await _requestAllLocationPermissions();
}
} else {
print('User did not agree to location usage');
hasPermissions = false;
SystemNavigator.pop();
}
}
return hasPermissions;
} catch (e) {
print('Error in permission request: $e');
return false;
}
}
static Future<bool> _checkLocationPermissions() async {
final locationPermission = await Permission.location.status;
final whenInUsePermission = await Permission.locationWhenInUse.status;
final alwaysPermission = await Permission.locationAlways.status;
return locationPermission == PermissionStatus.granted &&
(whenInUsePermission == PermissionStatus.granted || alwaysPermission == PermissionStatus.granted);
}
static Future<bool> _requestAllLocationPermissions() async {
await Permission.location.request();
await Permission.locationWhenInUse.request();
final alwaysStatus = await Permission.locationAlways.request();
return alwaysStatus == PermissionStatus.granted;
}
static Future<bool> _requestAndroidPreS() async {
await Permission.location.request();
await Permission.locationWhenInUse.request();
// Android 13以前では、ユーザーに設定画面で権限を許可するように促す
await showDialog(
context: Get.context!,
builder: (context) => AlertDialog(
title: Text('バックグラウンド位置情報の許可'),
content: Text('アプリの設定画面で「常に許可」を選択してください。'),
actions: [
TextButton(
child: Text('設定を開く'),
onPressed: () {
openAppSettings();
Navigator.of(context).pop();
},
),
],
),
);
// 設定画面から戻ってきた後、再度権限をチェック
return await Permission.locationAlways.isGranted;
}
static Future<bool> _isAndroid13OrAbove() async {
if (Platform.isAndroid) {
final androidVersion = int.tryParse(Platform.operatingSystemVersion.split('.').first) ?? 0;
return androidVersion >= 13;
}
return false;
}
static Future<bool> checkLocationPermissions_old() async {
final locationPermission = await Permission.location.status;
if (locationPermission.isDenied) {
await showLocationDisclosure();
final result = await Permission.location.request();
if (result.isDenied) {
await openAppSettings();
}
}
final whenInUsePermission = await Permission.locationWhenInUse.status;
final alwaysPermission = await Permission.locationAlways.status;
return locationPermission == PermissionStatus.granted &&
(whenInUsePermission == PermissionStatus.granted || alwaysPermission == PermissionStatus.granted);
}
static Future<bool> checkAndRequestPermissions() async {
/*
if (_isRequestingPermission) {
return _permissionCompleter!.future;
}
_isRequestingPermission = true;
_permissionCompleter = Completer<bool>();
*/
try {
if (_locationPermissionGranted != null) {
return _locationPermissionGranted!;
}
bool hasPermissions = await _checkLocationPermissions();
if (!hasPermissions) {
bool userAgreed = await showLocationDisclosure();
if (userAgreed) {
hasPermissions = await _requestAllLocationPermissions();
_locationPermissionGranted = true;
debugPrint("Finish checkAndRequestPermissions...");
return true;
} else {
print('User did not agree to location usage');
hasPermissions = false;
// アプリを終了
SystemNavigator.pop();
}
}
//_isRequestingPermission = false;
//_permissionCompleter!.complete(hasPermissions);
} catch( e ) {
print('Error in permission request: $e');
//_isRequestingPermission = false;
//_permissionCompleter!.complete(false);
}
debugPrint("Finish checkAndRequestPermissions...");
//return _permissionCompleter!.future;
return false;
}
static Future<void> requestAllLocationPermissions() async {
await Permission.location.request();
await Permission.locationWhenInUse.request();
await Permission.locationAlways.request();
if (await Permission.locationAlways.isGranted) {
const platform = MethodChannel('location');
try {
await platform.invokeMethod('startLocationService');
} on PlatformException catch (e) {
debugPrint("Failed to start location service: '${e.message}'.");
}
}
}
static Future<bool> showLocationDisclosure() async {
if (Get.context == null) {
print('Context is null, cannot show dialog');
return false;
}
//if (Get.isDialogOpen ?? false) {
// print('A dialog is already open');
// return false;
//}
try {
final result = await Get.dialog<bool>(
AlertDialog(
title: const Text('位置情報の使用について'),
content: const SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('このアプリでは、以下の目的で位置情報を使用します:'),
Text(
'• チェックポイントの自動チェックイン(アプリが閉じているときも含む)'),
Text('• 移動履歴の記録(バックグラウンドでも継続)'),
Text('• 現在地周辺の情報表示'),
Text('\nバックグラウンドでも位置情報を継続的に取得します。'),
Text('これにより、バッテリーの消費が増加する可能性があります。'),
Text('同意しない場合には、アプリは終了します。'),
],
),
),
actions: <Widget>[
TextButton(
child: const Text('同意しない'),
onPressed: () => Get.back(result: false),
),
TextButton(
child: const Text('同意する'),
onPressed: () => Get.back(result: true),
),
],
),
barrierDismissible: false,
);
return result ?? false;
}catch(e){
print('Dialog error: $e');
return false;
}
}
static void showPermissionDeniedDialog(String title,String message) {
Get.dialog(
AlertDialog(
//title: Text('location_permission_needed_title'.tr),
title: Text(title.tr),
// 位置情報への許可が必要です
//content: Text('location_permission_needed_main'.tr),
content: Text(message.tr),
// 岐阜ロゲでは、位置情報を使用してスタート・チェックイン・ゴール等の通過照明及び移動手段の記録のために、位置情報のトラッキングを行なっています。このためバックグラウンドでもトラッキングができるように位置情報の権限が必要です。
// 設定画面で、「岐阜ナビ」に対して、常に位置情報を許可するように設定してください。
actions: [
TextButton(
child: const Text('キャンセル'),
onPressed: () => Get.back(),
),
TextButton(
child: const Text('設定'),
onPressed: () {
Get.back();
openAppSettings();
},
),
],
),
);
}
/*
static Future<bool> requestLocationPermissions(BuildContext context) async {
if (_isRequestingPermission) {
// If a request is already in progress, wait for it to complete
return _permissionCompleter!.future;
}
_isRequestingPermission = true;
_permissionCompleter = Completer<bool>();
bool userAgreed = await showLocationDisclosure(context);
if (userAgreed) {
try {
final locationStatus = await Permission.location.request();
final whenInUseStatus = await Permission.locationWhenInUse.request();
final alwaysStatus = await Permission.locationAlways.request();
if (locationStatus == PermissionStatus.granted &&
(whenInUseStatus == PermissionStatus.granted || alwaysStatus == PermissionStatus.granted)) {
_permissionCompleter!.complete(true);
} else {
showPermissionDeniedDialog('location_permission_needed_title', 'location_permission_needed_main');
_permissionCompleter!.complete(false);
}
} catch (e) {
print('Error requesting location permission: $e');
_permissionCompleter!.complete(false);
}
} else {
print('User did not agree to location usage');
_permissionCompleter!.complete(false);
// Exit the app
SystemNavigator.pop();
}
_isRequestingPermission = false;
return _permissionCompleter!.future;
}
*/
static Future<bool> checkStoragePermission() async {
//debugPrint("(gifunavi)== checkStoragePermission ==");
final storagePermission = await Permission.storage.status;
return storagePermission == PermissionStatus.granted;
}
static Future<void> requestStoragePermission() async {
//debugPrint("(gifunavi)== requestStoragePermission ==");
final storagePermission = await Permission.storage.request();
if (storagePermission == PermissionStatus.granted) {
return;
}
if (storagePermission == PermissionStatus.permanentlyDenied) {
// リクエストが完了するまで待機
await Future.delayed(const Duration(milliseconds: 500));
showPermissionDeniedDialog('storage_permission_needed_title','storage_permission_needed_main');
}
}
/*
static Future<bool> checkLocationBasicPermission() async {
//debugPrint("(gifunavi)== checkLocationBasicPermission ==");
final locationPermission = await Permission.location.status;
return locationPermission == PermissionStatus.granted;
}
static Future<bool> checkLocationWhenInUsePermission() async {
//debugPrint("(gifunavi)== checkLocationWhenInUsePermission ==");
final whenInUsePermission = await Permission.locationWhenInUse.status;
return whenInUsePermission == PermissionStatus.granted;
}
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('location_permission_needed_title','location_permission_needed_main');
}
}
}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('location_permission_needed_title','location_permission_needed_main');
}else{
if( !isLocationServiceRunning ){
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('location_permission_needed_title','location_permission_needed_main');
}
}
}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();
}
}
*/
}