feat: 초기 프로젝트 설정 및 LunchPick 앱 구현
LunchPick(오늘 뭐 먹Z?) Flutter 앱의 초기 구현입니다. 주요 기능: - 네이버 지도 연동 맛집 추가 - 랜덤 메뉴 추천 시스템 - 날씨 기반 거리 조정 - 방문 기록 관리 - Bluetooth 맛집 공유 - 다크모드 지원 기술 스택: - Flutter 3.8.1+ - Riverpod 상태 관리 - Hive 로컬 DB - Clean Architecture 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
133
lib/presentation/providers/location_provider.dart
Normal file
133
lib/presentation/providers/location_provider.dart
Normal file
@@ -0,0 +1,133 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
/// 위치 권한 상태 Provider
|
||||
final locationPermissionProvider = FutureProvider<PermissionStatus>((ref) async {
|
||||
return await Permission.location.status;
|
||||
});
|
||||
|
||||
/// 현재 위치 Provider
|
||||
final currentLocationProvider = FutureProvider<Position?>((ref) async {
|
||||
// 위치 권한 확인
|
||||
final permissionStatus = await Permission.location.status;
|
||||
|
||||
if (!permissionStatus.isGranted) {
|
||||
// 권한이 없으면 요청
|
||||
final result = await Permission.location.request();
|
||||
if (!result.isGranted) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 위치 서비스 활성화 확인
|
||||
final serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
throw Exception('위치 서비스가 비활성화되어 있습니다');
|
||||
}
|
||||
|
||||
// 현재 위치 가져오기
|
||||
try {
|
||||
return await Geolocator.getCurrentPosition(
|
||||
desiredAccuracy: LocationAccuracy.high,
|
||||
timeLimit: const Duration(seconds: 10),
|
||||
);
|
||||
} catch (e) {
|
||||
// 타임아웃이나 오류 발생 시 마지막 알려진 위치 반환
|
||||
return await Geolocator.getLastKnownPosition();
|
||||
}
|
||||
});
|
||||
|
||||
/// 위치 스트림 Provider
|
||||
final locationStreamProvider = StreamProvider<Position>((ref) {
|
||||
return Geolocator.getPositionStream(
|
||||
locationSettings: const LocationSettings(
|
||||
accuracy: LocationAccuracy.high,
|
||||
distanceFilter: 10, // 10미터 이상 이동 시 업데이트
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
/// 위치 관리 StateNotifier
|
||||
class LocationNotifier extends StateNotifier<AsyncValue<Position?>> {
|
||||
LocationNotifier() : super(const AsyncValue.loading());
|
||||
|
||||
/// 위치 권한 요청
|
||||
Future<bool> requestLocationPermission() async {
|
||||
try {
|
||||
final status = await Permission.location.request();
|
||||
return status.isGranted;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// 위치 서비스 활성화 요청
|
||||
Future<bool> requestLocationService() async {
|
||||
try {
|
||||
return await Geolocator.openLocationSettings();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// 현재 위치 가져오기
|
||||
Future<void> getCurrentLocation() async {
|
||||
state = const AsyncValue.loading();
|
||||
|
||||
try {
|
||||
// 권한 확인
|
||||
final permissionStatus = await Permission.location.status;
|
||||
if (!permissionStatus.isGranted) {
|
||||
final granted = await requestLocationPermission();
|
||||
if (!granted) {
|
||||
state = const AsyncValue.data(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 위치 서비스 확인
|
||||
final serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
state = AsyncValue.error('위치 서비스가 비활성화되어 있습니다', StackTrace.current);
|
||||
return;
|
||||
}
|
||||
|
||||
// 위치 가져오기
|
||||
final position = await Geolocator.getCurrentPosition(
|
||||
desiredAccuracy: LocationAccuracy.high,
|
||||
timeLimit: const Duration(seconds: 10),
|
||||
);
|
||||
|
||||
state = AsyncValue.data(position);
|
||||
} catch (e, stack) {
|
||||
// 오류 발생 시 마지막 알려진 위치 시도
|
||||
try {
|
||||
final lastPosition = await Geolocator.getLastKnownPosition();
|
||||
state = AsyncValue.data(lastPosition);
|
||||
} catch (_) {
|
||||
state = AsyncValue.error(e, stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 두 지점 간의 거리 계산 (미터 단위)
|
||||
double calculateDistance(
|
||||
double startLatitude,
|
||||
double startLongitude,
|
||||
double endLatitude,
|
||||
double endLongitude,
|
||||
) {
|
||||
return Geolocator.distanceBetween(
|
||||
startLatitude,
|
||||
startLongitude,
|
||||
endLatitude,
|
||||
endLongitude,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// LocationNotifier Provider
|
||||
final locationNotifierProvider = StateNotifierProvider<LocationNotifier, AsyncValue<Position?>>((ref) {
|
||||
return LocationNotifier();
|
||||
});
|
||||
Reference in New Issue
Block a user