Commit eff64c98 authored by Sai Srinivas's avatar Sai Srinivas
Browse files

21-11-2025 tracking location services

parent d2939607
......@@ -22,6 +22,7 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:name="${applicationName}"
......@@ -77,6 +78,12 @@
</intent-filter>
</activity>
<service
android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
android:foregroundServiceType="location"
android:exported="false"/>
<meta-data
android:name="flutter_deeplinking_enabled"
android:value="true" />
......
......@@ -14,6 +14,7 @@ import 'package:provider/provider.dart';
import '../Utils/BackgroundLocationService.dart';
import '../Utils/SharedpreferencesService.dart';
import '../Utils/backgroundServiceNew.dart';
import '../Utils/background_service.dart';
import '../Utils/commonServices.dart';
import '../services/api_calling.dart';
......@@ -229,6 +230,8 @@ class CheckInOutProvider with ChangeNotifier {
if (data.error == 0) {
toast(context, "CheckedIn Successfully");
await BackgroundLocationService.startLocationService(context);
await BackgroundLocationServiceNew.init();
await BackgroundLocationServiceNew.start();
locationController.clear();
dispose();
Navigator.pop(context, true);
......@@ -266,6 +269,7 @@ class CheckInOutProvider with ChangeNotifier {
if (data.error == 0) {
toast(context, "Check-Out Successful");
await BackgroundLocationService.stopLocationService();
await BackgroundLocationServiceNew.stop();
locationController.clear();
dispose();
Navigator.pop(context, true);
......
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:generp/Utils/SharedpreferencesService.dart';
import 'package:generp/Utils/backgroundServiceNew.dart';
import 'package:generp/screens/LoginScreen.dart';
import 'package:generp/services/api_calling.dart';
import 'package:intl/intl.dart';
......@@ -77,6 +78,8 @@ class HomescreenNotifier extends ChangeNotifier {
var lastLocationTime = await SharedpreferencesService().getString(
"lastLocationTime",
);
notifyListeners();
print("lastLocationTime:$lastLocationTime");
......@@ -112,6 +115,7 @@ class HomescreenNotifier extends ChangeNotifier {
if (_att_status == 0) {
webSocketManager.close();
await BackgroundLocationService.stopLocationService();
BackgroundLocationServiceNew.stop();
_onlineStatus = "Offline";
......@@ -151,11 +155,14 @@ class HomescreenNotifier extends ChangeNotifier {
// print("Status knlknn offine");
}
await BackgroundLocationService.startLocationService(context);
await BackgroundLocationServiceNew.init();
await BackgroundLocationServiceNew.start();
// print("setstatus:$setstatus");
} else if (_att_status == 2) {
// print("att_status:$att_status");
webSocketManager.close();
await BackgroundLocationService.stopLocationService();
await BackgroundLocationServiceNew.stop();
_onlineStatus = "Offline";
......
......@@ -5,6 +5,7 @@ import 'package:generp/screens/LoginScreen.dart';
import 'package:generp/services/api_calling.dart';
import '../Utils/BackgroundLocationService.dart';
import '../Utils/backgroundServiceNew.dart';
class LogoutNotifier extends ChangeNotifier {
bool _logoutButtonClicked = false;
......@@ -33,6 +34,8 @@ class LogoutNotifier extends ChangeNotifier {
_isLoading = false;
_logoutButtonClicked = false;
await BackgroundLocationService.stopLocationService();
await BackgroundLocationServiceNew.stop();
SharedpreferencesService().clearPreferences();
Navigator.push(
context,
......
......@@ -184,6 +184,12 @@ class Loginnotifier extends ChangeNotifier {
SharedpreferencesService().saveString("UserName", data.name!);
SharedpreferencesService().saveString("UserEmail", data.emailId!);
SharedpreferencesService().saveString("Session_id", data.sessionId!);
SharedpreferencesService().saveString("user", data.userId!);
SharedpreferencesService().saveString("session", data.sessionId!);
print("USER ID : ${data.userId}");
print("SESSISON ID: ${data.sessionId}");
var roles = data.permissions!.toString();
SharedpreferencesService().saveString("roles", roles);
......
// lib/services/background_location_service.dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
import 'package:geolocator/geolocator.dart';
import 'package:provider/provider.dart';
import '../Notifiers/HomeScreenNotifier.dart';
import '../services/api_calling.dart';
import 'SharedpreferencesService.dart';
@pragma('vm:entry-point')
void startCallback() {
FlutterForegroundTask.setTaskHandler(LocationTaskHandler());
}
class LocationTaskHandler extends TaskHandler {
StreamSubscription<Position>? _stream;
String? _empId;
String? _sessionId;
@override
Future<void> onStart(DateTime timestamp, TaskStarter starter) async {
// Load user data
_empId = await SharedpreferencesService().getString("user");
_sessionId = await SharedpreferencesService().getString("session");
// var prov = Provider.of<HomescreenNotifier>(context, listen: false);
// _empId = prov.empId;
// _sessionId = prov.session;
print("DATA : ${_empId}");
print("DATA : ${_sessionId}");
if (_empId == null || _sessionId == null) {
FlutterForegroundTask.updateService(
notificationTitle: "GEN ERP",
notificationText: "Please login first",
);
return;
}
// Start real-time location stream (when moving)
_stream = Geolocator.getPositionStream(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 20, // Only send if moved 20 meters
),
).listen((position) {
_sendLocationToApi(position);
});
// Send first location immediately
_sendCurrentLocationOnce();
FlutterForegroundTask.updateService(
notificationTitle: "GEN ERP",
notificationText: "Live tracking active",
);
}
Future<void> _sendCurrentLocationOnce() async {
try {
final position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high,
timeLimit: const Duration(seconds: 15),
);
await _sendLocationToApi(position);
} catch (e) {
if (kDebugMode) print("Initial location failed: $e");
}
}
Future<void> _sendLocationToApi(Position position) async {
final location = "${position.latitude},${position.longitude}";
_empId = await SharedpreferencesService().getString("user");
_sessionId = await SharedpreferencesService().getString("session");
print("DATA111 : ${_empId}");
print("DATA111 : ${_sessionId}");
try {
final result = await ApiCalling.trackLiveLocationEmpolyeeAPI(
_empId!,
_sessionId!,
location,
);
if (result != null && result.error == "0") {
FlutterForegroundTask.updateService(
notificationTitle: "GEN ERP",
notificationText: "Location sent • ${DateTime.now().toString().substring(11, 19)}",
);
} else {
FlutterForegroundTask.updateService(
notificationText: "Sync failed • Retrying...",
);
}
} catch (e) {
FlutterForegroundTask.updateService(
notificationText: "No network • Retrying...",
);
}
// Save last sent time
final time = DateTime.now().toString().substring(11, 19);
SharedpreferencesService().saveString("lastLocationTime", time);
}
// This runs every 6 minutes (fallback when not moving)
@override
void onRepeatEvent(DateTime timestamp) {
_sendCurrentLocationOnce();
}
@override
Future<void> onDestroy(DateTime timestamp, bool isTimeout) async {
_stream?.cancel();
}
}
// Main Service Controller
class BackgroundLocationServiceNew {
static Future<void> init() async {
FlutterForegroundTask.init(
androidNotificationOptions: AndroidNotificationOptions(
channelId: 'gen_erp_location_channel',
channelName: 'GEN ERP Tracking',
channelDescription: 'Sends location every 6 minutes',
channelImportance: NotificationChannelImportance.HIGH,
priority: NotificationPriority.HIGH,
showBadge: true,
visibility: NotificationVisibility.VISIBILITY_SECRET
),
iosNotificationOptions: const IOSNotificationOptions(),
foregroundTaskOptions: ForegroundTaskOptions(
eventAction: ForegroundTaskEventAction.repeat(360000), // Every 6 minutes
autoRunOnBoot: false, // Prevents crash on boot
allowWakeLock: true,
allowWifiLock: true,
),
);
}
static Future<bool> get isRunning => FlutterForegroundTask.isRunningService;
static Future<void> start() async {
if (await isRunning) {
await FlutterForegroundTask.restartService();
} else {
await FlutterForegroundTask.startService(
notificationTitle: 'GEN ERP',
notificationText: 'Starting location tracking...',
callback: startCallback,
);
}
}
static Future<void> stop() async {
await FlutterForegroundTask.stopService();
}
}
\ No newline at end of file
......@@ -5821,4 +5821,29 @@ class ApiCalling {
// return null;
// }
// }
static Future<CommonResponse?> trackLiveLocationEmpolyeeAPI(empId, session,location) async {
try {
Map<String, String> data = {
'emp_id': (empId).toString(),
'session_id': (session).toString(),
'location': (location),
};
// print(data);
final res = await post(data, liveLocationStatusUrl, {});
if (res != null) {
print("BACKGROUND LOCATION DATA : ${data}");
debugPrint("BACKGROUND LOCATION: ${res.body}");
// print("check_session: ${res.body}");
return CommonResponse.fromJson(jsonDecode(res.body));
} else {
debugPrint("Null Response");
return null;
}
} catch (e) {
debugPrint('hello bev=bug $e ');
return null;
}
}
}
const baseUrl = "https://erp.gengroup.in/ci/app/";
const baseUrl_test = "https://erp.gengroup.in/ci/app/Api_home/";
const trackingUrl = "https://erp.gengroup.in/ci/app/Home/";
// var WEB_SOCKET_URL = "wss://ws.erp.gengroup.in/?type=user&route=employe_live_location_update&session_id=${Sessionid}";
const getAppVersionUrl = "https://erp.gengroup.in/ci/assets/appversion.json";
......@@ -212,3 +213,4 @@ const AdvanceListUrl ="${baseUrl_test}advance_list";
const createRazorpayUpiQrUrl ="${baseUrl_test}create_razorpay_upi_qr";
const fetchRazorpayUpiQrStatusUrl ="${baseUrl_test}fetch_razorpay_upi_qr_status";
const liveLocationStatusUrl ="${trackingUrl}sattendance_live_location_update";
\ No newline at end of file
......@@ -598,6 +598,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.12.0"
flutter_foreground_task:
dependency: "direct main"
description:
name: flutter_foreground_task
sha256: "9f1b25a81db95d7119d2c5cffc654048cbdd49d4056183e1beadc1a6a38f3e29"
url: "https://pub.dev"
source: hosted
version: "9.1.0"
flutter_html:
dependency: "direct main"
description:
......
......@@ -95,6 +95,7 @@ dependencies:
photo_view: ^0.14.0
flutter_contacts: ^1.1.9+2
open_filex: ^4.7.0
flutter_foreground_task: ^9.1.0
dev_dependencies:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment