Update: 2026-06-30 23:08:15
This commit is contained in:
@@ -4,6 +4,9 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import 'firebase_options.dart';
|
|||||||
import 'models/db_sql.dart';
|
import 'models/db_sql.dart';
|
||||||
import 'print.dart';
|
import 'print.dart';
|
||||||
import 'splash_screen_page.dart';
|
import 'splash_screen_page.dart';
|
||||||
|
import 'services/geofencing_service.dart';
|
||||||
|
|
||||||
// -- Global instances for easy access --
|
// -- Global instances for easy access --
|
||||||
final box = GetStorage();
|
final box = GetStorage();
|
||||||
@@ -55,6 +56,11 @@ void main() {
|
|||||||
// ✅ التعديل هنا: تهيئة خدمة الـ Live Activity للآيفون
|
// ✅ التعديل هنا: تهيئة خدمة الـ Live Activity للآيفون
|
||||||
IosLiveActivityService.init();
|
IosLiveActivityService.init();
|
||||||
|
|
||||||
|
// Initialize Geofencing Service
|
||||||
|
if (Platform.isAndroid || Platform.isIOS) {
|
||||||
|
await SiroGeofencingService.initAndStart();
|
||||||
|
}
|
||||||
|
|
||||||
// Lock screen orientation.
|
// Lock screen orientation.
|
||||||
await SystemChrome.setPreferredOrientations([
|
await SystemChrome.setPreferredOrientations([
|
||||||
DeviceOrientation.portraitUp,
|
DeviceOrientation.portraitUp,
|
||||||
|
|||||||
98
siro_rider/lib/services/geofencing_service.dart
Normal file
98
siro_rider/lib/services/geofencing_service.dart
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:native_geofence/native_geofence.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:get_storage/get_storage.dart';
|
||||||
|
import 'package:siro_rider/constant/links.dart';
|
||||||
|
|
||||||
|
// Top-level function for background execution
|
||||||
|
@pragma('vm:entry-point')
|
||||||
|
Future<void> geofenceBackgroundCallback(GeofenceCallbackParams params) async {
|
||||||
|
if (params.event == GeofenceEvent.enter) {
|
||||||
|
// Note: GetStorage might need to be initialized in the background isolate
|
||||||
|
await GetStorage.init();
|
||||||
|
final storage = GetStorage();
|
||||||
|
final passengerId = storage.read('passenger_id') ?? '';
|
||||||
|
if (passengerId.toString().isEmpty) return;
|
||||||
|
|
||||||
|
for (var geofence in params.geofences) {
|
||||||
|
debugPrint('Entered Geofence: ${geofence.id}');
|
||||||
|
|
||||||
|
try {
|
||||||
|
final url = Uri.parse('${AppLink.server}/api/location/sync_location.php');
|
||||||
|
await http.post(url, body: {
|
||||||
|
'passenger_id': passengerId.toString(),
|
||||||
|
'lat': geofence.location.latitude.toString(),
|
||||||
|
'lng': geofence.location.longitude.toString(),
|
||||||
|
'source': 'geofence',
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Geofence API Error: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SiroGeofencingService {
|
||||||
|
static final _storage = GetStorage();
|
||||||
|
|
||||||
|
static Future<void> initAndStart() async {
|
||||||
|
try {
|
||||||
|
await NativeGeofenceManager.instance.initialize();
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Error initializing NativeGeofenceManager: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> syncZonesWithServer(double lat, double lng) async {
|
||||||
|
try {
|
||||||
|
final passengerId = _storage.read('passenger_id') ?? '';
|
||||||
|
if (passengerId.toString().isEmpty) return;
|
||||||
|
|
||||||
|
final url = Uri.parse('${AppLink.server}/api/location/sync_location.php');
|
||||||
|
final response = await http.post(url, body: {
|
||||||
|
'passenger_id': passengerId.toString(),
|
||||||
|
'lat': lat.toString(),
|
||||||
|
'lng': lng.toString(),
|
||||||
|
'source': 'app_usage',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final data = json.decode(response.body);
|
||||||
|
if (data['status'] == 'success' && data['update_geofences'] != null) {
|
||||||
|
await _updateLocalGeofences(data['update_geofences']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Error syncing geofence zones: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> _updateLocalGeofences(List<dynamic> regions) async {
|
||||||
|
try {
|
||||||
|
for (var region in regions) {
|
||||||
|
final geofence = Geofence(
|
||||||
|
id: region['zone_name'],
|
||||||
|
location: Location(
|
||||||
|
latitude: double.parse(region['latitude'].toString()),
|
||||||
|
longitude: double.parse(region['longitude'].toString())),
|
||||||
|
radiusMeters: double.parse(region['radius_meters'].toString()),
|
||||||
|
triggers: {GeofenceEvent.enter},
|
||||||
|
iosSettings: const IosGeofenceSettings(
|
||||||
|
initialTrigger: true,
|
||||||
|
),
|
||||||
|
androidSettings: const AndroidGeofenceSettings(
|
||||||
|
initialTriggers: {GeofenceEvent.enter},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await NativeGeofenceManager.instance.createGeofence(
|
||||||
|
geofence,
|
||||||
|
geofenceBackgroundCallback,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Error updating local geofences: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// This is a generated file; do not edit or check into version control.
|
||||||
|
FLUTTER_ROOT=/Users/hamzaaleghwairyeen/flutter
|
||||||
|
FLUTTER_APPLICATION_PATH=/Users/hamzaaleghwairyeen/development/App/Siro/siro_rider/packages/get/example_nav2
|
||||||
|
COCOAPODS_PARALLEL_CODE_SIGN=true
|
||||||
|
FLUTTER_TARGET=lib/main.dart
|
||||||
|
FLUTTER_BUILD_DIR=build
|
||||||
|
FLUTTER_BUILD_NAME=1.0.0
|
||||||
|
FLUTTER_BUILD_NUMBER=1
|
||||||
|
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
|
||||||
|
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
|
||||||
|
DART_OBFUSCATION=false
|
||||||
|
TRACK_WIDGET_CREATION=true
|
||||||
|
TREE_SHAKE_ICONS=false
|
||||||
|
PACKAGE_CONFIG=.dart_tool/package_config.json
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#
|
||||||
|
# Generated file, do not edit.
|
||||||
|
#
|
||||||
|
|
||||||
|
import lldb
|
||||||
|
|
||||||
|
def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict):
|
||||||
|
"""Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages."""
|
||||||
|
base = frame.register["x0"].GetValueAsAddress()
|
||||||
|
page_len = frame.register["x1"].GetValueAsUnsigned()
|
||||||
|
|
||||||
|
# Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the
|
||||||
|
# first page to see if handled it correctly. This makes diagnosing
|
||||||
|
# misconfiguration (e.g. missing breakpoint) easier.
|
||||||
|
data = bytearray(page_len)
|
||||||
|
data[0:8] = b'IHELPED!'
|
||||||
|
|
||||||
|
error = lldb.SBError()
|
||||||
|
frame.GetThread().GetProcess().WriteMemory(base, data, error)
|
||||||
|
if not error.Success():
|
||||||
|
print(f'Failed to write into {base}[+{page_len}]', error)
|
||||||
|
return
|
||||||
|
|
||||||
|
def __lldb_init_module(debugger: lldb.SBDebugger, _):
|
||||||
|
target = debugger.GetDummyTarget()
|
||||||
|
# Caveat: must use BreakpointCreateByRegEx here and not
|
||||||
|
# BreakpointCreateByName. For some reasons callback function does not
|
||||||
|
# get carried over from dummy target for the later.
|
||||||
|
bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$")
|
||||||
|
bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__))
|
||||||
|
bp.SetAutoContinue(True)
|
||||||
|
print("-- LLDB integration loaded --")
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#
|
||||||
|
# Generated file, do not edit.
|
||||||
|
#
|
||||||
|
|
||||||
|
command script import --relative-to-command-file flutter_lldb_helper.py
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# This is a generated file; do not edit or check into version control.
|
||||||
|
export "FLUTTER_ROOT=/Users/hamzaaleghwairyeen/flutter"
|
||||||
|
export "FLUTTER_APPLICATION_PATH=/Users/hamzaaleghwairyeen/development/App/Siro/siro_rider/packages/get/example_nav2"
|
||||||
|
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
|
||||||
|
export "FLUTTER_TARGET=lib/main.dart"
|
||||||
|
export "FLUTTER_BUILD_DIR=build"
|
||||||
|
export "FLUTTER_BUILD_NAME=1.0.0"
|
||||||
|
export "FLUTTER_BUILD_NUMBER=1"
|
||||||
|
export "DART_OBFUSCATION=false"
|
||||||
|
export "TRACK_WIDGET_CREATION=true"
|
||||||
|
export "TREE_SHAKE_ICONS=false"
|
||||||
|
export "PACKAGE_CONFIG=.dart_tool/package_config.json"
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// This is a generated file; do not edit or check into version control.
|
||||||
|
FLUTTER_ROOT=/Users/hamzaaleghwairyeen/flutter
|
||||||
|
FLUTTER_APPLICATION_PATH=/Users/hamzaaleghwairyeen/development/App/Siro/siro_rider/packages/get_storage/example
|
||||||
|
COCOAPODS_PARALLEL_CODE_SIGN=true
|
||||||
|
FLUTTER_TARGET=lib/main.dart
|
||||||
|
FLUTTER_BUILD_DIR=build
|
||||||
|
FLUTTER_BUILD_NAME=1.0.0
|
||||||
|
FLUTTER_BUILD_NUMBER=1
|
||||||
|
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
|
||||||
|
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
|
||||||
|
DART_OBFUSCATION=false
|
||||||
|
TRACK_WIDGET_CREATION=true
|
||||||
|
TREE_SHAKE_ICONS=false
|
||||||
|
PACKAGE_CONFIG=.dart_tool/package_config.json
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#
|
||||||
|
# Generated file, do not edit.
|
||||||
|
#
|
||||||
|
|
||||||
|
import lldb
|
||||||
|
|
||||||
|
def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict):
|
||||||
|
"""Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages."""
|
||||||
|
base = frame.register["x0"].GetValueAsAddress()
|
||||||
|
page_len = frame.register["x1"].GetValueAsUnsigned()
|
||||||
|
|
||||||
|
# Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the
|
||||||
|
# first page to see if handled it correctly. This makes diagnosing
|
||||||
|
# misconfiguration (e.g. missing breakpoint) easier.
|
||||||
|
data = bytearray(page_len)
|
||||||
|
data[0:8] = b'IHELPED!'
|
||||||
|
|
||||||
|
error = lldb.SBError()
|
||||||
|
frame.GetThread().GetProcess().WriteMemory(base, data, error)
|
||||||
|
if not error.Success():
|
||||||
|
print(f'Failed to write into {base}[+{page_len}]', error)
|
||||||
|
return
|
||||||
|
|
||||||
|
def __lldb_init_module(debugger: lldb.SBDebugger, _):
|
||||||
|
target = debugger.GetDummyTarget()
|
||||||
|
# Caveat: must use BreakpointCreateByRegEx here and not
|
||||||
|
# BreakpointCreateByName. For some reasons callback function does not
|
||||||
|
# get carried over from dummy target for the later.
|
||||||
|
bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$")
|
||||||
|
bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__))
|
||||||
|
bp.SetAutoContinue(True)
|
||||||
|
print("-- LLDB integration loaded --")
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#
|
||||||
|
# Generated file, do not edit.
|
||||||
|
#
|
||||||
|
|
||||||
|
command script import --relative-to-command-file flutter_lldb_helper.py
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# This is a generated file; do not edit or check into version control.
|
||||||
|
export "FLUTTER_ROOT=/Users/hamzaaleghwairyeen/flutter"
|
||||||
|
export "FLUTTER_APPLICATION_PATH=/Users/hamzaaleghwairyeen/development/App/Siro/siro_rider/packages/get_storage/example"
|
||||||
|
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
|
||||||
|
export "FLUTTER_TARGET=lib/main.dart"
|
||||||
|
export "FLUTTER_BUILD_DIR=build"
|
||||||
|
export "FLUTTER_BUILD_NAME=1.0.0"
|
||||||
|
export "FLUTTER_BUILD_NUMBER=1"
|
||||||
|
export "DART_OBFUSCATION=false"
|
||||||
|
export "TRACK_WIDGET_CREATION=true"
|
||||||
|
export "TREE_SHAKE_ICONS=false"
|
||||||
|
export "PACKAGE_CONFIG=.dart_tool/package_config.json"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/Users/hamzaaleghwairyeen/.pub-cache/hosted/pub.dev/jni-1.0.0/
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/Users/hamzaaleghwairyeen/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/
|
||||||
@@ -1325,6 +1325,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
|
native_geofence:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: native_geofence
|
||||||
|
sha256: "472c33abe8dc2eb9e2021e1db7964952a1781582ad2e716182edfbbdff346597"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.1"
|
||||||
nested:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ environment:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
native_geofence: ^1.1.0
|
||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
flutter_webrtc: ^1.4.1
|
flutter_webrtc: ^1.4.1
|
||||||
secure_string_operations:
|
secure_string_operations:
|
||||||
|
|||||||
Reference in New Issue
Block a user