diff --git a/client/android/app/build.gradle b/client/android/app/build.gradle
index 9e9f2b028..5fea8634e 100644
--- a/client/android/app/build.gradle
+++ b/client/android/app/build.gradle
@@ -27,6 +27,12 @@ android {
     compileSdkVersion flutter.compileSdkVersion
     ndkVersion "25.1.8937393"
 
+    packagingOptions {
+        jniLibs {
+            useLegacyPackaging true
+        }
+    }
+
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_8
         targetCompatibility JavaVersion.VERSION_1_8
@@ -42,11 +48,10 @@ android {
 
     defaultConfig {
         applicationId "com.appveyor.flet"
-        minSdkVersion flutter.minSdkVersion
+        minSdkVersion 23
         targetSdkVersion flutter.targetSdkVersion
         versionCode flutterVersionCode.toInteger()
         versionName flutterVersionName
-        minSdkVersion 23
     }
 
     buildTypes {
@@ -60,4 +65,4 @@ flutter {
     source '../..'
 }
 
-dependencies {}
\ No newline at end of file
+dependencies {}
diff --git a/client/android/app/src/main/AndroidManifest.xml b/client/android/app/src/main/AndroidManifest.xml
index 8e5c26ce2..d7c4db353 100644
--- a/client/android/app/src/main/AndroidManifest.xml
+++ b/client/android/app/src/main/AndroidManifest.xml
@@ -1,38 +1,58 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.appveyor.flet">
-  <uses-permission android:name="android.permission.INTERNET" />
-  <!-- Media access permissions.
-      Android 13 or higher.
-      https://developer.android.com/about/versions/13/behavior-changes-13#granular-media-permissions -->
-  <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
-  <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
-  <!-- Storage access permissions. Android 12 or lower. -->
-  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
-  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-  <uses-permission android:name="android.permission.RECORD_AUDIO" />
-  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
-  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
-  <application android:label="Flet" android:name="${applicationName}"
-    android:icon="@mipmap/ic_launcher">
-    <meta-data
-            android:name="io.flutter.embedding.android.EnableImpeller"
-            android:value="true"/>
-    <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop"
-      android:theme="@style/LaunchTheme"
-      android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
-      android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
-      <!-- Specifies an Android theme to apply to this Activity as soon as
+    <uses-permission android:name="android.permission.INTERNET" />
+    <!-- Media access permissions.
+    Android 13 or higher.
+    https://developer.android.com/about/versions/13/behavior-changes-13#granular-media-permissions -->
+    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
+    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
+    <!-- Storage access permissions. Android 12 or lower. -->
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+    <!-- Google TV -->
+    <uses-feature android:name="android.software.leanback" android:required="false" />
+    <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
+
+    <application
+        android:label="Flet"
+        android:name="${applicationName}"
+        android:enableOnBackInvokedCallback="true"
+        android:icon="@mipmap/ic_launcher">
+        <meta-data
+                android:name="io.flutter.embedding.android.EnableImpeller"
+                android:value="false"/>
+        <activity
+            android:name=".MainActivity"
+            android:exported="true"
+            android:launchMode="singleTop"
+            android:theme="@style/LaunchTheme"
+            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+            android:hardwareAccelerated="true"
+            android:windowSoftInputMode="adjustResize">
+            <!-- Specifies an Android theme to apply to this Activity as soon as
                  the Android process has started. This theme is visible to the user
                  while the Flutter UI initializes. After that, this theme continues
                  to determine the Window background behind the Flutter UI. -->
-      <meta-data android:name="io.flutter.embedding.android.NormalTheme"
-        android:resource="@style/NormalTheme" />
-      <intent-filter>
-        <action android:name="android.intent.action.MAIN" />
-        <category android:name="android.intent.category.LAUNCHER" />
-      </intent-filter>
-    </activity>
-    <!-- Don't delete the meta-data below.
+            <meta-data
+                android:name="io.flutter.embedding.android.NormalTheme"
+                android:resource="@style/NormalTheme"
+            />
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+                <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>   <!-- Google TV -->
+            </intent-filter>
+        </activity>
+        <!-- Don't delete the meta-data below.
              This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
-    <meta-data android:name="flutterEmbedding" android:value="2" />
-  </application>
+        <meta-data
+            android:name="flutterEmbedding"
+            android:value="2" />
+    </application>
 </manifest>
\ No newline at end of file
diff --git a/client/android/build.gradle b/client/android/build.gradle
index 2dcf86f90..52d31f376 100644
--- a/client/android/build.gradle
+++ b/client/android/build.gradle
@@ -1,5 +1,5 @@
 buildscript {
-    ext.kotlin_version = '1.7.10'
+    ext.kotlin_version = '1.9.24'
     repositories {
         google()
         mavenCentral()
@@ -27,4 +27,4 @@ subprojects {
 
 tasks.register("clean", Delete) {
     delete rootProject.buildDir
-}
\ No newline at end of file
+}
diff --git a/client/android/gradle/wrapper/gradle-wrapper.properties b/client/android/gradle/wrapper/gradle-wrapper.properties
index 6b665338b..a35eb1fa3 100644
--- a/client/android/gradle/wrapper/gradle-wrapper.properties
+++ b/client/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
diff --git a/client/android/settings.gradle b/client/android/settings.gradle
index 45d92d220..b64b2eb73 100644
--- a/client/android/settings.gradle
+++ b/client/android/settings.gradle
@@ -23,7 +23,7 @@ pluginManagement {
 
 plugins {
     id "dev.flutter.flutter-plugin-loader" version "1.0.0"
-    id "com.android.application" version "7.3.0" apply false
+    id "com.android.application" version "8.3.1" apply false
 }
 
-include ":app"
\ No newline at end of file
+include ":app"
diff --git a/packages/flet_geolocator/lib/src/geolocator.dart b/packages/flet_geolocator/lib/src/geolocator.dart
index 9653e90ca..353a97d44 100644
--- a/packages/flet_geolocator/lib/src/geolocator.dart
+++ b/packages/flet_geolocator/lib/src/geolocator.dart
@@ -1,3 +1,5 @@
+import 'dart:async';
+import 'dart:convert';
 import 'package:flet/flet.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/widgets.dart';
@@ -22,6 +24,8 @@ class GeolocatorControl extends StatefulWidget {
 
 class _GeolocatorControlState extends State<GeolocatorControl>
     with FletStoreMixin {
+  StreamSubscription<Position>? _positionStream;
+
   @override
   void initState() {
     super.initState();
@@ -41,10 +45,81 @@ class _GeolocatorControlState extends State<GeolocatorControl>
     super.deactivate();
   }
 
+  void _onPosition(Position position) {
+    debugPrint("Geolocator onPosition: $position");
+    final jsonData = jsonEncode({
+      "latitude": position.latitude,
+      "longitude": position.longitude,
+    });
+    widget.backend.triggerControlEvent(widget.control.id, "position", jsonData);
+  }
+
+  Future<bool> _enableLocationService() async {
+    late LocationSettings locationSettings;
+    if (defaultTargetPlatform == TargetPlatform.android) {
+      locationSettings = AndroidSettings(
+          accuracy: LocationAccuracy.high,
+          distanceFilter: 0,
+          forceLocationManager: true,
+          intervalDuration: const Duration(seconds: 30),
+          // Needs this or when app goes in background, background service stops working
+          foregroundNotificationConfig: const ForegroundNotificationConfig(
+            notificationText:
+            "Location Updates",
+            notificationTitle: "Running in Background",
+            enableWakeLock: true,
+          )
+      );
+    } else if (defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.macOS) {
+      locationSettings = AppleSettings(
+        accuracy: LocationAccuracy.bestForNavigation,
+        activityType: ActivityType.automotiveNavigation,
+        distanceFilter: 0,
+        pauseLocationUpdatesAutomatically: false,
+        showBackgroundLocationIndicator: true,
+        allowBackgroundLocationUpdates: true,
+      );
+    } else if (kIsWeb) {
+      locationSettings = WebSettings(
+        accuracy: LocationAccuracy.high,
+        distanceFilter: 0,
+        // maximumAge: Duration(minutes: 5)
+        maximumAge: Duration.zero,
+      );
+    } else {
+      locationSettings = LocationSettings(
+        accuracy: LocationAccuracy.high,
+        distanceFilter: 0,
+      );
+    }
+
+    _positionStream = Geolocator.getPositionStream(locationSettings: locationSettings,
+    ).listen(
+      (Position? position) {
+        if (position != null) {
+          _onPosition(position);
+          debugPrint('Geolocator: ${position.latitude}, ${position.longitude}, ${position}');
+        } else {
+          debugPrint('Geolocator: Position is null.');
+        }
+      },
+      onError: (e) {
+        debugPrint('Geolocator: Error getting stream position: $e');
+      },
+    );
+    return true;
+  }
+
+  Future<bool> _disableLocationService() async {
+    await _positionStream?.cancel();
+    return true;
+  }
+
   @override
   Widget build(BuildContext context) {
     debugPrint(
         "Geolocator build: ${widget.control.id} (${widget.control.hashCode})");
+    bool onPosition = widget.control.attrBool("onPosition", false)!;
 
     () async {
       widget.backend.subscribeMethods(widget.control.id,
@@ -59,6 +134,15 @@ class _GeolocatorControlState extends State<GeolocatorControl>
           case "is_location_service_enabled":
             var serviceEnabled = await Geolocator.isLocationServiceEnabled();
             return serviceEnabled.toString();
+          case "service_enable":
+            var serviceEnabled = false;
+            if (onPosition) {
+              serviceEnabled = await _enableLocationService();
+            }
+            return serviceEnabled.toString();
+          case "service_disable":
+            var serviceDisabled = await _disableLocationService();
+            return serviceDisabled.toString();
           case "open_app_settings":
             if (!kIsWeb) {
               var opened = await Geolocator.openAppSettings();
diff --git a/packages/flet_geolocator/pubspec.yaml b/packages/flet_geolocator/pubspec.yaml
index 3d9c40bab..d10a279ad 100644
--- a/packages/flet_geolocator/pubspec.yaml
+++ b/packages/flet_geolocator/pubspec.yaml
@@ -12,7 +12,7 @@ dependencies:
   flutter:
     sdk: flutter
 
-  geolocator: ^11.0.0
+  geolocator: ^13.0.1
 
   flet:
     path: ../flet/
@@ -20,4 +20,4 @@ dependencies:
 dev_dependencies:
   flutter_test:
     sdk: flutter
-  flutter_lints: ^2.0.0
\ No newline at end of file
+  flutter_lints: ^2.0.0
diff --git a/packages/flet_permission_handler/pubspec.yaml b/packages/flet_permission_handler/pubspec.yaml
index a39b7abb9..98375f8d4 100644
--- a/packages/flet_permission_handler/pubspec.yaml
+++ b/packages/flet_permission_handler/pubspec.yaml
@@ -14,6 +14,7 @@ dependencies:
 
   collection: ^1.16.0
   permission_handler: ^11.3.1
+  permission_handler_html: ^0.1.3+2
 
   flet:
     path: ../flet/
@@ -21,4 +22,4 @@ dependencies:
 dev_dependencies:
   flutter_test:
     sdk: flutter
-  flutter_lints: ^2.0.0
\ No newline at end of file
+  flutter_lints: ^2.0.0
diff --git a/sdk/python/packages/flet-core/src/flet_core/geolocator.py b/sdk/python/packages/flet-core/src/flet_core/geolocator.py
index 5f6c7bab3..c53ec6a9a 100644
--- a/sdk/python/packages/flet-core/src/flet_core/geolocator.py
+++ b/sdk/python/packages/flet-core/src/flet_core/geolocator.py
@@ -1,10 +1,16 @@
-import json
 from dataclasses import dataclass, field
 from enum import Enum
 from typing import Any, Optional
 
 from flet_core.control import Control
 from flet_core.ref import Ref
+from flet_core.types import (
+    OptionalEventCallable,
+    OptionalControlEventCallable,
+)
+from flet_core.event_handler import EventHandler
+from flet_core.control_event import ControlEvent
+import json
 
 
 class GeolocatorPositionAccuracy(Enum):
@@ -58,12 +64,17 @@ def __init__(
         #
         ref: Optional[Ref] = None,
         data: Any = None,
+        on_position: OptionalEventCallable["PositionEvent"] = None,
+
     ):
         Control.__init__(
             self,
             ref=ref,
             data=data,
         )
+        self.__on_position = EventHandler(lambda e: PositionEvent(e))
+        self._add_event_handler("position", self.__on_position.get_handler())
+        self.on_position = on_position
 
     def _get_control_name(self):
         return "geolocator"
@@ -192,7 +203,7 @@ async def request_permission_async(
 
     def is_location_service_enabled(self, wait_timeout: Optional[float] = 10) -> bool:
         enabled = self.invoke_method(
-            "request_permission",
+            "is_location_service_enabled",
             wait_for_result=True,
             wait_timeout=wait_timeout,
         )
@@ -245,3 +256,56 @@ async def open_location_settings_async(
             wait_timeout=wait_timeout,
         )
         return opened == "true"
+
+    def service_enable(self, wait_timeout: Optional[float] = 10) -> bool:
+        opened = self.invoke_method(
+            "service_enable",
+            wait_for_result=True,
+            wait_timeout=wait_timeout,
+        )
+        return opened == "true"
+
+    async def service_enable_async(
+        self, wait_timeout: Optional[float] = 10
+    ) -> bool:
+        opened = await self.invoke_method_async(
+            "service_enable",
+            wait_for_result=True,
+            wait_timeout=wait_timeout,
+        )
+        return opened == "true"
+
+    def service_disable(self, wait_timeout: Optional[float] = 10) -> bool:
+        opened = self.invoke_method(
+            "service_disable",
+            wait_for_result=True,
+            wait_timeout=wait_timeout,
+        )
+        return opened == "true"
+
+    async def service_disable_async(
+        self, wait_timeout: Optional[float] = 10
+    ) -> bool:
+        opened = await self.invoke_method_async(
+            "service_disable",
+            wait_for_result=True,
+            wait_timeout=wait_timeout,
+        )
+        return opened == "true"
+
+    @property
+    def on_position(self) -> OptionalEventCallable["PositionEvent"]:
+        return self.__on_position.handler
+
+    @on_position.setter
+    def on_position(self, handler: OptionalEventCallable["PositionEvent"]):
+        self.__on_position.handler = handler
+        self._set_attr("onPosition", True if handler is not None else None)
+
+
+class PositionEvent(ControlEvent):
+    def __init__(self, e: ControlEvent):
+        super().__init__(e.target, e.name, e.data, e.control, e.page)
+        d = json.loads(e.data)
+        self.latitude: float = d.get("latitude")
+        self.longitude: float = d.get("longitude")