From 3fdd17ccaab2ef2ef430943703d2c358e3cf7ee8 Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Thu, 18 Sep 2025 16:17:36 +0300 Subject: [PATCH 1/2] code added to get the location for gms hms and iphone. fallback added if the last known location is null. --- lib/core/app_state.dart | 5 + lib/core/dependencies.dart | 3 +- lib/core/location_util.dart | 174 +++++++++++++----- .../book_appointments_view_model.dart | 39 ++-- lib/main.dart | 1 + .../appointment_checkin_bottom_sheet.dart | 2 +- .../hospital_bottom_sheet_body.dart | 2 +- .../book_appointment_page.dart | 1 + pubspec.yaml | 2 + 9 files changed, 169 insertions(+), 60 deletions(-) diff --git a/lib/core/app_state.dart b/lib/core/app_state.dart index f4c0fd8..e9abeaa 100644 --- a/lib/core/app_state.dart +++ b/lib/core/app_state.dart @@ -133,5 +133,10 @@ class AppState { _userRegistrationPayload = value; } + ///this will be called if there is any problem in getting the user location + void resetLocation(){ + userLong = 0.0; + userLong = 0.0; + } } diff --git a/lib/core/dependencies.dart b/lib/core/dependencies.dart index f5b3d05..4de7c5f 100644 --- a/lib/core/dependencies.dart +++ b/lib/core/dependencies.dart @@ -158,7 +158,8 @@ class AppDependencies { bookAppointmentsRepo: getIt(), errorHandlerService: getIt(), navigationService: getIt(), - myAppointmentsViewModel: getIt() + myAppointmentsViewModel: getIt(), + locationUtils: getIt() ), ); diff --git a/lib/core/location_util.dart b/lib/core/location_util.dart index d556034..2104078 100644 --- a/lib/core/location_util.dart +++ b/lib/core/location_util.dart @@ -1,12 +1,23 @@ import 'dart:io'; +import 'dart:ui'; import 'package:geolocator/geolocator.dart'; +import 'package:gms_check/gms_check.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/cache_consts.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; -import 'package:permission_handler/permission_handler.dart'; +import 'package:huawei_location/huawei_location.dart' as HmsLocation + show + FusedLocationProviderClient, + Location, + LocationSettingsRequest, + LocationRequest; +import 'package:location/location.dart' + show Location, PermissionStatus, LocationData; +import 'package:permission_handler/permission_handler.dart' + show Permission, PermissionListActions, PermissionStatusGetters; class LocationUtils { NavigationService navigationService; @@ -16,6 +27,7 @@ class LocationUtils { bool isShowLocationTimeoutDialog; bool isHuawei; final GeolocatorPlatform _geolocatorPlatform = GeolocatorPlatform.instance; + Future? isGMSDevice; LocationUtils({ required this.isShowConfirmDialog, @@ -23,49 +35,62 @@ class LocationUtils { required this.appState, this.isHuawei = false, this.isShowLocationTimeoutDialog = true, - }); - - void getCurrentLocation({Function(LatLng)? callBack}) async { - Geolocator.isLocationServiceEnabled().then((value) async { - if (value) { - await Geolocator.checkPermission().then((permission) async { - if (permission == LocationPermission.always || permission == LocationPermission.whileInUse) { - Geolocator.getLastKnownPosition().then((value) { - setLocation(value); - if (callBack != null) callBack(LatLng(value?.latitude ?? 24.7101433, value?.longitude ?? 46.6757709)); - }).catchError((err) { - if (isShowConfirmDialog && isShowLocationTimeoutDialog) {} - }); - } + }) { + isGMSDevice = GmsCheck().checkGmsAvailability(); + } - if (permission == LocationPermission.denied || permission == LocationPermission.deniedForever) { - if (Platform.isAndroid) { - // Utils.showPermissionConsentDialog(context, TranslationBase.of(context).locationPermissionDialog, () async { - final hasPermission = await _handlePermission(); - if (hasPermission) { - // Geolocator.getCurrentPosition(locationSettings: LocationSettings(accuracy: LocationAccuracy.medium, timeLimit: Duration(seconds: 5))).then((value) { - Geolocator.getLastKnownPosition().then((value) { - setLocation(value); - if (callBack != null) callBack(LatLng(value?.latitude ?? 24.7101433, value?.longitude ?? 46.6757709)); - }); - } else { - // if (isShowConfirmDialog) showErrorLocationDialog(false, failureCallBack: () {}); - } - // }); - } else { - if (await Permission.location.request().isGranted) { - getCurrentLocation(callBack: callBack); - } else { - setZeroLocation(); - if (isShowConfirmDialog) showErrorLocationDialog(false, failureCallBack: () {}); - } - } - } - }).catchError((err) {}); - } else { - if (isShowConfirmDialog) showErrorLocationDialog(false, failureCallBack: () {}); + void getLocation( + {Function(LatLng)? onSuccess, VoidCallback? onFailure}) async { + if (Platform.isIOS) { + getCurrentLocation(onFailure: onFailure, onSuccess: onSuccess); + return; + } + + if (await isGMSDevice ?? true) { + getCurrentLocation(onFailure: onFailure, onSuccess: onSuccess); + return; + } + + getHMSLocation(onFailure: onFailure, onSuccess: onSuccess); + } + + void getCurrentLocation( + {Function(LatLng)? onSuccess, VoidCallback? onFailure}) async { + var location = Location(); + + bool isLocationEnabled = await location.serviceEnabled(); + //if the location service is not enabled, ask the user to enable it + if (!isLocationEnabled) { + isLocationEnabled = await location.requestService(); + if (!isLocationEnabled) { + appState.resetLocation(); + onFailure?.call(); + return; + } + } + + LocationPermission permissionGranted = await Geolocator.checkPermission(); + if (permissionGranted == LocationPermission.denied) { + permissionGranted = await Geolocator.requestPermission(); + if (permissionGranted != LocationPermission.whileInUse && + permissionGranted != LocationPermission.always) { + appState.resetLocation(); + onFailure?.call(); + return; } - }).catchError((err) {}); + } + + Position? currentLocation = await Geolocator.getLastKnownPosition(); + + if(currentLocation?.latitude == null || currentLocation?.longitude == null){ + currentLocation = await Geolocator.getCurrentPosition( + desiredAccuracy: LocationAccuracy.low); + } + + LatLng locationData = LatLng( + currentLocation?.latitude ?? 0.0, currentLocation?.longitude ?? 0.0); + saveLatLngToAppState(locationData); + onSuccess?.call(locationData); } Future checkIfGPSIsEnabled() async { @@ -166,4 +191,69 @@ class LocationUtils { ].request(); return (result[Permission.location]!.isGranted || result[Permission.locationAlways]!.isGranted); } + + void saveLatLngToAppState(LatLng locationData) { + appState.userLat = locationData.latitude; + appState.userLong = locationData.longitude; + } + + void getHMSLocation( + {VoidCallback? onFailure, Function(LatLng p1)? onSuccess}) async { + try { + var location = Location(); + HmsLocation.FusedLocationProviderClient locationService = + HmsLocation.FusedLocationProviderClient()..initFusedLocationService(); + + bool isLocationEnabled = await Geolocator.isLocationServiceEnabled(); + //if the location service is not enabled, ask the user to enable it + if (!isLocationEnabled) { + HmsLocation.LocationRequest locationRequest = + HmsLocation.LocationRequest() + ..priority = HmsLocation.LocationRequest.PRIORITY_HIGH_ACCURACY; + + HmsLocation.LocationSettingsRequest request = + HmsLocation.LocationSettingsRequest( + alwaysShow: true, + needBle: false, + requests: [locationRequest], + ); + + await locationService.checkLocationSettings(request); + } + LocationPermission permissionGranted = await Geolocator.checkPermission(); + if (permissionGranted == LocationPermission.denied) { + permissionGranted = await Geolocator.requestPermission(); + if (permissionGranted != LocationPermission.whileInUse && + permissionGranted != LocationPermission.always) { + appState.resetLocation(); + onFailure?.call(); + return; + } + } + + HmsLocation.Location data = await locationService.getLastLocation(); + if (data.latitude == null || data.longitude == null) { + appState.resetLocation(); + HmsLocation.LocationRequest request = HmsLocation.LocationRequest() + ..priority = HmsLocation.LocationRequest.PRIORITY_HIGH_ACCURACY + ..interval = 1000 // 1 second + ..numUpdates = 1; + locationService.requestLocationUpdates(request); + locationService.onLocationData?.listen((location) { + data = location; + if (data.latitude == null || data.longitude == null) { + appState.resetLocation(); + onFailure?.call(); + return; + } + saveLatLngToAppState( + LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0)); + }); + } + saveLatLngToAppState(LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0)); + } catch (e) { + appState.resetLocation(); + onFailure?.call(); + } + } } diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart index c74b176..7dc1e68 100644 --- a/lib/features/book_appointments/book_appointments_view_model.dart +++ b/lib/features/book_appointments/book_appointments_view_model.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/cache_consts.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/core/location_util.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/doctor_response_mapper.dart'; import 'package:hmg_patient_app_new/core/utils/loading_utils.dart'; @@ -37,6 +38,8 @@ class BookAppointmentsViewModel extends ChangeNotifier { int initialSlotDuration = 0; + LocationUtils locationUtils; + List clinicsList = []; List _filteredClinicsList = []; @@ -74,7 +77,9 @@ class BookAppointmentsViewModel extends ChangeNotifier { bool shouldLoadSpecificClinic = false; String? currentlySelectedHospitalFromRegionFlow; - BookAppointmentsViewModel({required this.bookAppointmentsRepo, required this.errorHandlerService, required this.navigationService, required this.myAppointmentsViewModel}); + BookAppointmentsViewModel({required this.bookAppointmentsRepo, required this.errorHandlerService, required this.navigationService, required this.myAppointmentsViewModel, required this.locationUtils}) {; + initBookAppointmentViewModel(); + } void initializeFilteredList() { _filteredClinicsList = List.from(clinicsList); @@ -97,6 +102,7 @@ class BookAppointmentsViewModel extends ChangeNotifier { isDoctorProfileLoading = true; clinicsList.clear(); doctorsList.clear(); + // getLocation(); notifyListeners(); } @@ -408,10 +414,10 @@ class BookAppointmentsViewModel extends ChangeNotifier { Future getRegionMappedProjectList() async { //todo handle the case in the location is switch on - if(hospitalList != null && hospitalList!.registeredDoctorMap != null && hospitalList!.registeredDoctorMap!.isNotEmpty){ - filteredHospitalList = hospitalList; - return; - } + // if(hospitalList != null && hospitalList!.registeredDoctorMap != null && hospitalList!.registeredDoctorMap!.isNotEmpty){ + // filteredHospitalList = hospitalList; + // return; + // } isRegionListLoading = true; notifyListeners(); final result = await bookAppointmentsRepo.getProjectList(); @@ -429,10 +435,8 @@ class BookAppointmentsViewModel extends ChangeNotifier { lat: _appState.userLat, lng: _appState.userLong, ); - var lat = await Utils.getNumFromPrefs(CacheConst.userLat); - var lng = await Utils.getNumFromPrefs(CacheConst.userLong); - var isLocationEnabled = (lat != 0) && (lng != 0); + var isLocationEnabled = (_appState.userLat != 0) && (_appState.userLong != 0); hospitalList = await DoctorMapper.sortList(isLocationEnabled, hospitalList!); @@ -480,15 +484,15 @@ class BookAppointmentsViewModel extends ChangeNotifier { notifyListeners(); } - Future isLocationEnabled() async{ - return await Location().serviceEnabled(); + bool isLocationEnabled() { + return _appState.userLong != 0.0 && _appState.userLong != 0.0; } - bool getLocationStatus() { - bool isLocationAvaiable = false; - isLocationEnabled().then((value) => isLocationAvaiable = value); - return isLocationAvaiable; - } + // bool getLocationStatus() { + // bool isLocationAvaiable = false; + // isLocationEnabled().then((value) => isLocationAvaiable = value); + // return isLocationAvaiable; + // } void setLoadSpecificClinic(bool status) { shouldLoadSpecificClinic = status; @@ -518,4 +522,9 @@ class BookAppointmentsViewModel extends ChangeNotifier { void resetFilterList(){ filteredHospitalList = hospitalList; } + + + void getLocation(){ + locationUtils.getLocation(); + } } diff --git a/lib/main.dart b/lib/main.dart index c75cf91..6abde55 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -132,6 +132,7 @@ void main() async { errorHandlerService: getIt(), navigationService: getIt(), myAppointmentsViewModel: getIt(), + locationUtils: getIt(), ), ), ChangeNotifierProvider( diff --git a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart index 77fec61..b701f69 100644 --- a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart +++ b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart @@ -51,7 +51,7 @@ class AppointmentCheckinBottomSheet extends StatelessWidget { // navigationService: myAppointmentsViewModel.navigationService, // appState: myAppointmentsViewModel.appState, // ); - locationUtils.getCurrentLocation(callBack: (value) { + locationUtils.getCurrentLocation(onSuccess: (value) { projectDetailListModel = Utils.getProjectDetailObj(_appState, patientAppointmentHistoryResponseModel.projectID); double dist = Utils.distance(value.latitude, value.longitude, double.parse(projectDetailListModel.latitude!), double.parse(projectDetailListModel.longitude!)).ceilToDouble() * 1000; print(dist); diff --git a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart index 71cc07d..8159abd 100644 --- a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart +++ b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart @@ -93,7 +93,7 @@ class HospitalBottomSheetBody extends StatelessWidget { ?.hmcDoctorList?[index]; return HospitalListItem( hospitalData: hospital, - isLocationEnabled: appointmentsViewModel.getLocationStatus(), + isLocationEnabled: appointmentsViewModel.isLocationEnabled(), ).onPress(() { regionalViewModel.setHospitalModel(hospital); regionalViewModel.setBottomSheetState(AppointmentViaRegionState.CLINIC_SELECTION); diff --git a/lib/presentation/book_appointment/book_appointment_page.dart b/lib/presentation/book_appointment/book_appointment_page.dart index 482d864..f0dee1e 100644 --- a/lib/presentation/book_appointment/book_appointment_page.dart +++ b/lib/presentation/book_appointment/book_appointment_page.dart @@ -44,6 +44,7 @@ class _BookAppointmentPageState extends State { void initState() { scheduleMicrotask(() { bookAppointmentsViewModel.initBookAppointmentViewModel(); + bookAppointmentsViewModel.getLocation(); }); super.initState(); } diff --git a/pubspec.yaml b/pubspec.yaml index e55d241..5423904 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -83,6 +83,8 @@ dependencies: family_bottom_sheet: ^0.1.0 location: ^8.0.1 + gms_check: ^1.0.4 + huawei_location: ^6.14.2+301 dev_dependencies: flutter_test: From 4473145c0045ec8d4d6c0fe308482121c15e5472 Mon Sep 17 00:00:00 2001 From: "taha.alam" Date: Thu, 18 Sep 2025 16:25:25 +0300 Subject: [PATCH 2/2] on success block added to the hms location block --- lib/core/location_util.dart | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/core/location_util.dart b/lib/core/location_util.dart index 2104078..ecfab62 100644 --- a/lib/core/location_util.dart +++ b/lib/core/location_util.dart @@ -246,11 +246,17 @@ class LocationUtils { onFailure?.call(); return; } - saveLatLngToAppState( - LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0)); + var locationData = + LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0); + saveLatLngToAppState(locationData); + onSuccess?.call(locationData); }); + } else { + var locationData = LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0); + + saveLatLngToAppState(locationData); + onSuccess?.call(locationData); } - saveLatLngToAppState(LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0)); } catch (e) { appState.resetLocation(); onFailure?.call();