You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have carefully read the documentation and verified I have added the required platform specific configuration.
Please select affected platform(s)
Android
iOS
Linux
macOS
Web
Windows
Steps to reproduce
In my case first of all i get user current location and start streaming for my application purpose.
Expected results
I want accurate current location and streaming
Actual results
I got accurate current location but in rare case some time even though I killed the app and enter into that it show my last cached location after few minutes or sometime few around 20 seconds it update.
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
}
switch (permission) {
case LocationPermission.whileInUse:
case LocationPermission.always:
await _getInitialLocation();
_getStream();
break;
case LocationPermission.deniedForever:
// Check if the alert has already been shown
if (!_hasShownPermissionDeniedAlert) {
_hasShownPermissionDeniedAlert = true; // Set the flag
// Show the alert dialog
if (mounted) {
await _showPermanentDenialDialog();
}
}
break;
case LocationPermission.denied:
// User explicitly denied permission
if (mounted) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.deniedForever) {
openAppSettings();
}
// _showPermissionDeniedSnackbar();
}
break;
default:
break;
}
Future _handleBiometricAuth() async {
if (!dbProvider.enforceBiometric) return true;
try {
// First check if device is capable of biometric authentication
final bool canAuthWithBiometrics = await _auth.canCheckBiometrics;
final bool canAuth =
canAuthWithBiometrics || await _auth.isDeviceSupported();
if (!canAuth) {
if (mounted) {
Utils.showSnackBar(
AppLocalizations.of(context)!.devwithbiocap,
context,
);
}
return false;
}
// Get available biometrics
final List<BiometricType> availableBiometrics =
await _auth.getAvailableBiometrics();
// Check if there are any biometrics enrolled
if (availableBiometrics.isEmpty) {
if (mounted) {
Utils.showSnackBar(
AppLocalizations.of(context)!.bfreattempttochckIn,
context,
);
}
return false;
}
// Attempt authentication
if (mounted) {
final bool didAuthenticate = await _auth.authenticate(
localizedReason: AppLocalizations.of(context)!.bioisreqttend,
options: const AuthenticationOptions(
biometricOnly:
true, // Force biometric only, no PIN/pattern fallback
stickyAuth: true,
sensitiveTransaction: true,
),
);
if (!didAuthenticate) {
if (mounted) {
Utils.showSnackBar(
AppLocalizations.of(context)!.authfailed,
context,
);
}
return false;
}
}
return true;
} catch (e) {
// Handle specific platform exceptions
if (e is PlatformException && mounted) {
String message = "";
switch (e.code) {
case 'NotAvailable':
case 'NotEnrolled':
message = AppLocalizations.of(context)!.biomandatory;
break;
case 'LockedOut':
case 'PermanentlyLockedOut':
message = AppLocalizations.of(context)!.manyfailedattemp;
break;
default:
message = AppLocalizations.of(context)!.autherror;
}
if (mounted) {
Utils.showSnackBar(
message,
context,
);
}
return false;
}
// For any other unexpected errors
debugPrint("Biometric error: $e");
if (mounted) {
Utils.showSnackBar(
AppLocalizations.of(context)!.ensurebiomet,
context,
);
}
return false;
}
}
// Handle location check and check-in/out process
Future _handleLocationCheck(
TrackerServices attendanceServiceProvider) async {
if (userLocation == null) return;
bool isWithinAnyRadius = false;
// Sales mode allows check-in/out from anywhere
if (dbProvider.isSales) {
isWithinAnyRadius = true;
// Set a default "Sales" location model for tracking
locationProvider.setNearestLocationModel(
LocationModel(
id: 1,
customerName: "Sales",
locationName: "Sales",
locationLat: userLocation!.latitude,
locationLong: userLocation!.longitude,
radius: 0, // No radius restriction for sales
),
);
} else {
// Regular mode: Check if within any designated location radius
if (designatedLocations.isEmpty) {
if (context.mounted) {
Utils.showSnackBar(
AppLocalizations.of(context)!.nodesignatedloc,
context,
);
}
return;
}
for (LocationModel location in locationProvider.locationModelsList) {
if (await _isWithinLocationRadius(location)) {
isWithinAnyRadius = true;
locationProvider.setNearestLocationModel(location);
break;
}
}
}
if (isWithinAnyRadius) {
await _performCheckInOut(attendanceServiceProvider);
} else {
if (mounted) {
Utils.showSnackBar(
AppLocalizations.of(context)!.outside,
context,
);
}
}
}
// Check if user is within radius of a specific location
Future _isWithinLocationRadius(LocationModel location) async {
LatLng locationLatLng = LatLng(location.locationLat, location.locationLong);
double distance = _calculateDistance(userLocation!, locationLatLng);
return distance <= location.radius!.toDouble();
}
// Perform the actual check-in/out operation
Future _performCheckInOut(
TrackerServices attendanceServiceProvider) async {
if (!context.mounted) return;
Doctor output
mohamedraasith@Mohameds-Laptop aqattendance_ios % flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.27.0, on macOS 15.2 24C101 darwin-arm64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 16.2)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2024.1)
[✓] VS Code (version 1.96.0)
[✓] Connected device (3 available)
! Error: Browsing on the local area network for Rasi09. Ensure the device is unlocked and attached
with a cable or associated with the same local area network as this Mac.
The device must be opted into Developer Mode to connect wirelessly. (code -27)
[✓] Network resources
• No issues found!
[Paste your output here]
The text was updated successfully, but these errors were encountered:
Please check the following before submitting a new issue.
Please select affected platform(s)
Steps to reproduce
In my case first of all i get user current location and start streaming for my application purpose.
Expected results
I want accurate current location and streaming
Actual results
I got accurate current location but in rare case some time even though I killed the app and enter into that it show my last cached location after few minutes or sometime few around 20 seconds it update.
Code sample
Code sample
[Paste your code here]
class MapCio extends StatefulWidget {
const MapCio({super.key});
@OverRide
State createState() => _MapCioState();
}
class _MapCioState extends State with WidgetsBindingObserver {
bool _hasShownPermissionDeniedAlert = false;
StreamSubscription? _positionStreamSubscription;
final LocalAuthentication _auth = LocalAuthentication();
LatLng? userLocation;
bool _isLoading = true;
bool _isDisposed = false;
bool _isMockDetected = false;
GoogleMapController? mapController;
late LocationService locationProvider;
late UserModel dbProvider;
List designatedLocations = [];
CameraPosition? currentCameraPosition;
String _buttonLabel = "";
String? lastCheckInRecordId;
Future _cancelPositionStream() async {
await _positionStreamSubscription?.cancel();
_positionStreamSubscription = null;
}
@OverRide
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_initializeAttendance();
}
@OverRide
void dispose() {
_isDisposed = true;
WidgetsBinding.instance.removeObserver(this);
_cancelPositionStream();
mapController?.dispose();
super.dispose();
}
void setStateIfMounted(VoidCallback fn) {
if (mounted && !_isDisposed) {
setState(fn);
}
}
void _initializeAttendance() async {
if (await NetworkProvider().checkInternetConnection()) {
if (mounted && !_isDisposed) {
Provider.of(context, listen: false).getUserData();
Future.delayed(const Duration(seconds: 2));
locationProvider = Provider.of(context, listen: false);
if (Provider.of(context, listen: false).userModel ==
null) {
Provider.of(context, listen: false).getUserData();
dbProvider =
Provider.of(context, listen: false).userModel!;
} else {
dbProvider =
Provider.of(context, listen: false).userModel!;
}
}
Future _checkLocationPermission() async {
if (_isDisposed) return;
LocationPermission permission = await Geolocator.checkPermission();
}
Future _getInitialLocation() async {
try {
Position position = await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.bestForNavigation,
distanceFilter: 10));
setState(() {
userLocation = LatLng(position.latitude, position.longitude);
_isLoading = false;
});
} catch (e) {
debugPrint("Error fetching initial location: $e");
setState(() => _isLoading = false);
}
}
Future _showPermanentDenialDialog() async {
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: const Text("Permission required"),
content: Text(AppLocalizations.of(context)!.deniedloc),
actions: [
TextButton(
child: const Text("Ok"),
onPressed: () {
openAppSettings();
Navigator.of(context).pop();
},
),
],
);
},
);
}
Future _getStream() async {
if (_isDisposed || _isMockDetected) return;
try {
await _fetchData();
}
void _handleLocationError(dynamic error) {
debugPrint("Location stream error: $error");
_cancelPositionStream();
Utils.showSnackBar("Location error: ${error.message}", context);
}
LocationSettings _getPlatformSpecificSettings() {
if (defaultTargetPlatform == TargetPlatform.android) {
return AndroidSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 15,
intervalDuration: const Duration(seconds: 15),
);
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
return AppleSettings(
accuracy: LocationAccuracy.high, // Most precise accuracy
distanceFilter: 5, // Reduce distance filter
activityType: ActivityType.fitness,
showBackgroundLocationIndicator: true,
);
}
return const LocationSettings(
accuracy: LocationAccuracy.high, distanceFilter: 10);
}
void _handleMockLocation() async {
if (_isDisposed) return;
}
void _onPositionUpdate(Position position) async {
if (_isDisposed) {
_cancelPositionStream();
return;
}
}
Future _fetchData() async {
final latestRecord =
await AttendanceServices().getLastCheckInRecordForToday();
if (latestRecord != null) {
setState(() {
_buttonLabel = latestRecord.checkIn && !latestRecord.checkOut
? AppLocalizations.of(context)!.checkout
: AppLocalizations.of(context)!.checkin;
});
} else {
setState(() {
_buttonLabel = AppLocalizations.of(context)!.checkin;
});
}
}
@OverRide
void didChangeAppLifecycleState(AppLifecycleState state) {
if (_isDisposed) return;
}
@OverRide
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: CustomAppBar(title: buttonLabel, from: "page"),
body: isLoading
? const Center(child: CircularProgressIndicator())
: Padding(
padding: const EdgeInsets.all(16.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15)),
height: 500,
child: GoogleMap(
myLocationButtonEnabled: true,
mapType: MapType.normal,
onMapCreated: (controller) {
mapController = controller;
},
onCameraMove: (cameraPosition) {
currentCameraPosition = cameraPosition;
},
initialCameraPosition: userLocation != null
? CameraPosition(target: userLocation!, zoom: 17)
: const CameraPosition(
target: LatLng(0, 0), zoom: 1),
markers: {
if (userLocation != null)
Marker(
markerId: const MarkerId("user"),
icon: BitmapDescriptor.defaultMarkerWithHue(
BitmapDescriptor.hueBlue),
position: userLocation!,
),
...designatedLocations.map((location) => Marker(
markerId: MarkerId(
'designated_location${location.latitude}${location.longitude}'),
position: location,
infoWindow: const InfoWindow(
title: "Designated Location"),
)),
},
circles: {
...locationProvider.locationModelsList
.map((model) => Circle(
circleId: CircleId(
'circle_${model.locationLat}_${model.locationLong}'),
center: LatLng(
model.locationLat, model.locationLong),
radius: model.radius!.toDouble(),
fillColor:
Colors.lightBlue.withOpacity(0.4),
strokeColor: Colors.lightBlue,
strokeWidth: 2,
)),
},
),
),
15.kH,
Text(
AppLocalizations.of(context)!.note,
style: Theme.of(context).textTheme.labelLarge!.copyWith(
color: AppThemeColors.grey500,
fontWeight: FontWeight.w400),
),
15.kH,
Consumer(
builder: (context, trackerService, child) {
return trackerService.isLoading
? const Center(child: CircularProgressIndicator())
: GestureDetector(
onTap: () async {
if (userLocation != null) {
if (!await _handleBiometricAuth()) return;
await _handleLocationCheck(trackerService);
}
},
child: MainButton(
text: Text(
_buttonLabel,
style: Theme.of(context)
.textTheme
.bodyLarge!
.copyWith(
color: AppThemeColors.white500),
),
),
);
},
),
],
),
),
),
);
}
double _calculateDistance(LatLng start, LatLng end) {
const double earthRadius = 6371000; // meters
double dLat = _degreeToRadian(end.latitude - start.latitude);
double dLon = _degreeToRadian(end.longitude - start.longitude);
}
double _degreeToRadian(double degree) {
return degree * pi / 180;
}
Future _handleBiometricAuth() async {
if (!dbProvider.enforceBiometric) return true;
}
// Handle location check and check-in/out process
Future _handleLocationCheck(
TrackerServices attendanceServiceProvider) async {
if (userLocation == null) return;
}
// Check if user is within radius of a specific location
Future _isWithinLocationRadius(LocationModel location) async {
LatLng locationLatLng = LatLng(location.locationLat, location.locationLong);
double distance = _calculateDistance(userLocation!, locationLatLng);
return distance <= location.radius!.toDouble();
}
// Perform the actual check-in/out operation
Future _performCheckInOut(
TrackerServices attendanceServiceProvider) async {
if (!context.mounted) return;
}
}
Screenshots or video
Screenshots or video demonstration
[Upload media here]
Version
geolocator: ^13.0.2
Flutter Doctor output
Doctor output
mohamedraasith@Mohameds-Laptop aqattendance_ios % flutter doctor Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 3.27.0, on macOS 15.2 24C101 darwin-arm64, locale en-US) [✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 16.2) [✓] Chrome - develop for the web [✓] Android Studio (version 2024.1) [✓] VS Code (version 1.96.0) [✓] Connected device (3 available) ! Error: Browsing on the local area network for Rasi09. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac. The device must be opted into Developer Mode to connect wirelessly. (code -27) [✓] Network resources• No issues found!
[Paste your output here]
The text was updated successfully, but these errors were encountered: