Skip to content

Commit

Permalink
Adding Background/Foreground Services to GeoLocator UPDATE (#3803)
Browse files Browse the repository at this point in the history
* Adding Background/Foreground Services to GeoLocator UPDATE

* Removing filepicker from pubspec.yaml devel area

* Adding geolocator min version to flet_geolocator instead

* Adding geolocator min version to flet_geolocator instead 2

* Permission_handler_html web 1.0.0 fix

* Updating on_position to new format
  • Loading branch information
syleishere authored Aug 27, 2024
1 parent edf1fb6 commit 5cbbdff
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 45 deletions.
11 changes: 8 additions & 3 deletions client/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -60,4 +65,4 @@ flutter {
source '../..'
}

dependencies {}
dependencies {}
84 changes: 52 additions & 32 deletions client/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -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>
4 changes: 2 additions & 2 deletions client/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.7.10'
ext.kotlin_version = '1.9.24'
repositories {
google()
mavenCentral()
Expand Down Expand Up @@ -27,4 +27,4 @@ subprojects {

tasks.register("clean", Delete) {
delete rootProject.buildDir
}
}
2 changes: 1 addition & 1 deletion client/android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions client/android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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"
include ":app"
84 changes: 84 additions & 0 deletions packages/flet_geolocator/lib/src/geolocator.dart
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -22,6 +24,8 @@ class GeolocatorControl extends StatefulWidget {

class _GeolocatorControlState extends State<GeolocatorControl>
with FletStoreMixin {
StreamSubscription<Position>? _positionStream;

@override
void initState() {
super.initState();
Expand All @@ -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,
Expand All @@ -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();
Expand Down
4 changes: 2 additions & 2 deletions packages/flet_geolocator/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ dependencies:
flutter:
sdk: flutter

geolocator: ^11.0.0
geolocator: ^13.0.1

flet:
path: ../flet/

dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter_lints: ^2.0.0
3 changes: 2 additions & 1 deletion packages/flet_permission_handler/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ dependencies:

collection: ^1.16.0
permission_handler: ^11.3.1
permission_handler_html: ^0.1.3+2

flet:
path: ../flet/

dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter_lints: ^2.0.0
Loading

0 comments on commit 5cbbdff

Please sign in to comment.