From f3da392cbb083539ae0399c085aed6a5472f6092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Chudziak?= Date: Tue, 29 Aug 2023 22:39:00 +0200 Subject: [PATCH] Release 3.10 (#271) * use latest play services version 21.0.1 (#249) Thanks, I'll test this out and include in the next version * work in Headless JS (#254) Co-authored-by: lavrik acer * Default `maximumAge` to 0 on iOS. (#268) * Example updates (#270) * chore: headless js + example updates * chore: revert ts changes * chore: fix background location timer types * chore: move types package --------- Co-authored-by: Brian Rojas Co-authored-by: valery-lavrik Co-authored-by: lavrik acer Co-authored-by: Justin Kaufman <57186+jkaufman@users.noreply.github.com> --- README.md | 2 + android/build.gradle | 2 +- .../PlayServicesLocationManager.java | 54 ++++++++------- example/ios/GeolocationExample/Info.plist | 6 +- example/ios/Podfile.lock | 6 ++ example/package.json | 1 + .../src/configs/BackgroundLocationUpdates.tsx | 68 +++++++++++++++++++ example/src/configs/SetConfiguration.tsx | 62 ++++++++++------- example/src/configs/index.tsx | 9 +++ example/src/examples/WatchPosition.tsx | 1 + example/yarn.lock | 5 ++ ios/RNCGeolocation.mm | 5 +- js/NativeRNCGeolocation.ts | 2 + js/implementation.native.ts | 2 + package.json | 1 + yarn.lock | 5 ++ 16 files changed, 178 insertions(+), 53 deletions(-) create mode 100644 example/src/configs/BackgroundLocationUpdates.tsx diff --git a/README.md b/README.md index 3a00f8d..11021d5 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,7 @@ Geolocation.setRNConfiguration( config: { skipPermissionRequests: boolean; authorizationLevel?: 'always' | 'whenInUse' | 'auto'; + enableBackgroundLocationUpdates?: boolean; locationProvider?: 'playServices' | 'android' | 'auto'; } ) => void @@ -173,6 +174,7 @@ Supported options: * `skipPermissionRequests` (boolean) - Defaults to `false`. If `true`, you must request permissions before using Geolocation APIs. * `authorizationLevel` (string, iOS-only) - Either `"whenInUse"`, `"always"`, or `"auto"`. Changes whether the user will be asked to give "always" or "when in use" location services permission. Any other value or `auto` will use the default behaviour, where the permission level is based on the contents of your `Info.plist`. +* `enableBackgroundLocationUpdates` (boolean, iOS-only) - When using `skipPermissionRequests`, toggle wether to automatically enableBackgroundLocationUpdates. Defaults to true. * `locationProvider` (string, Android-only) - Either `"playServices"`, `"android"`, or `"auto"`. Determines wether to use `Google’s Location Services API` or `Android’s Location API`. The `"auto"` mode defaults to `android`, and falls back to Android's Location API if play services aren't available. --- diff --git a/android/build.gradle b/android/build.gradle index a489454..06c8bd1 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -133,7 +133,7 @@ repositories { dependencies { //noinspection GradleDynamicVersion implementation 'com.facebook.react:react-native:+' - implementation 'com.google.android.gms:play-services-location:20.0.0' + implementation 'com.google.android.gms:play-services-location:21.0.1' } if (isNewArchitectureEnabled()) { diff --git a/android/src/main/java/com/reactnativecommunity/geolocation/PlayServicesLocationManager.java b/android/src/main/java/com/reactnativecommunity/geolocation/PlayServicesLocationManager.java index 4b9e004..362c7e6 100644 --- a/android/src/main/java/com/reactnativecommunity/geolocation/PlayServicesLocationManager.java +++ b/android/src/main/java/com/reactnativecommunity/geolocation/PlayServicesLocationManager.java @@ -49,8 +49,9 @@ public void getCurrentLocationData(ReadableMap options, Callback success, Callba Activity currentActivity = mReactContext.getCurrentActivity(); if (currentActivity == null) { - error.invoke(PositionError.buildError(PositionError.ACTIVITY_NULL, "mReactContext.getCurrentActivity() returned null but should be non-null in getCurrentLocationData")); - return; + mSingleLocationCallback = createSingleLocationCallback(success, error); + checkLocationSettings(options, mSingleLocationCallback); + return; } try { @@ -59,29 +60,7 @@ public void getCurrentLocationData(ReadableMap options, Callback success, Callba if (location != null && (SystemClock.currentTimeMillis() - location.getTime()) < locationOptions.maximumAge) { success.invoke(locationToMap(location)); } else { - mSingleLocationCallback = new LocationCallback() { - @Override - public void onLocationResult(LocationResult locationResult) { - if (locationResult == null) { - emitError(PositionError.POSITION_UNAVAILABLE, "No location provided (FusedLocationProvider/lastLocation)."); - return; - } - - AndroidLocationManager.LocationOptions locationOptions = AndroidLocationManager.LocationOptions.fromReactMap(options); - Location location = locationResult.getLastLocation(); - success.invoke(locationToMap(location)); - - mFusedLocationClient.removeLocationUpdates(mSingleLocationCallback); - mSingleLocationCallback = null; - } - - @Override - public void onLocationAvailability(LocationAvailability locationAvailability) { - if (!locationAvailability.isLocationAvailable()) { - emitError(PositionError.POSITION_UNAVAILABLE, "Location not available (FusedLocationProvider/lastLocation)."); - } - } - }; + mSingleLocationCallback = createSingleLocationCallback(success, error); checkLocationSettings(options, mSingleLocationCallback); } }); @@ -151,4 +130,29 @@ private void requestLocationUpdates(LocationRequest locationRequest, LocationCal throw e; } } + + private LocationCallback createSingleLocationCallback(Callback success, Callback error){ + return new LocationCallback() { + @Override + public void onLocationResult(LocationResult locationResult) { + if (locationResult == null) { + error.invoke(PositionError.buildError(PositionError.POSITION_UNAVAILABLE, "No location provided (FusedLocationProvider/lastLocation).")); + return; + } + + Location location = locationResult.getLastLocation(); + success.invoke(locationToMap(location)); + + mFusedLocationClient.removeLocationUpdates(mSingleLocationCallback); + mSingleLocationCallback = null; + } + + @Override + public void onLocationAvailability(LocationAvailability locationAvailability) { + if (!locationAvailability.isLocationAvailable()) { + error.invoke(PositionError.buildError(PositionError.POSITION_UNAVAILABLE, "Location not available (FusedLocationProvider/lastLocation).")); + } + } + }; + } } diff --git a/example/ios/GeolocationExample/Info.plist b/example/ios/GeolocationExample/Info.plist index 1a0be27..48e46cd 100644 --- a/example/ios/GeolocationExample/Info.plist +++ b/example/ios/GeolocationExample/Info.plist @@ -35,8 +35,6 @@ - NSLocationWhenInUseUsageDescription - UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities @@ -51,5 +49,9 @@ UIViewControllerBasedStatusBarAppearance + NSLocationAlwaysAndWhenInUseUsageDescription + Testing purposes + NSLocationWhenInUseUsageDescription + Testing purposes diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index d97f610..8745c22 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -562,6 +562,8 @@ PODS: - React-jsinspector (0.70.10) - React-logger (0.70.10): - glog + - react-native-background-timer (2.4.1): + - React-Core - react-native-geolocation (3.0.6): - RCT-Folly (= 2021.07.22.00) - RCTRequired @@ -711,6 +713,7 @@ DEPENDENCIES: - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) - React-logger (from `../node_modules/react-native/ReactCommon/logger`) + - react-native-background-timer (from `../node_modules/react-native-background-timer`) - react-native-geolocation (from `../..`) - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) @@ -782,6 +785,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/jsinspector" React-logger: :path: "../node_modules/react-native/ReactCommon/logger" + react-native-background-timer: + :path: "../node_modules/react-native-background-timer" react-native-geolocation: :path: "../.." react-native-safe-area-context: @@ -845,6 +850,7 @@ SPEC CHECKSUMS: React-jsiexecutor: 1457c7bb2f08f257e6b5ece8b62348da43c4ccf2 React-jsinspector: 2a1985769123b199c195a96f46478b35db139712 React-logger: 7fbdc3576b2ed3834360c8ea3c1c2ec54ac3043a + react-native-background-timer: 17ea5e06803401a379ebf1f20505b793ac44d0fe react-native-geolocation: a4df6c9ef98f624737b40c9e3d709eec1bff6ea7 react-native-safe-area-context: 0dfc8e3a7d5ff115d100bafe4269d64a2c0a1456 React-perflogger: f86e85eb59151d09e9b44b8931f5c088e4f08bbc diff --git a/example/package.json b/example/package.json index 75f3e86..9ee0c64 100644 --- a/example/package.json +++ b/example/package.json @@ -16,6 +16,7 @@ "@react-navigation/native-stack": "^6.7.0", "react": "18.1.0", "react-native": "0.70.10", + "react-native-background-timer": "^2.4.1", "react-native-safe-area-context": "4.5.1", "react-native-screens": "3.17.0" }, diff --git a/example/src/configs/BackgroundLocationUpdates.tsx b/example/src/configs/BackgroundLocationUpdates.tsx new file mode 100644 index 0000000..9d2bd16 --- /dev/null +++ b/example/src/configs/BackgroundLocationUpdates.tsx @@ -0,0 +1,68 @@ +/** + * Copyright (c) React Native Community + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +'use strict'; + +import React, { useEffect, useRef, useState } from 'react'; +import { View, Button, AppState } from 'react-native'; +import BackgroundTimer from 'react-native-background-timer'; +import Geolocation from '@react-native-community/geolocation'; + +export default function BackgroundLocationUpdates() { + const appState = useRef(AppState.currentState); + const [backgroundListener, setBackgroundListener] = useState(false); + + useEffect(() => { + if (!backgroundListener) { + return; + } + + const subscription = AppState.addEventListener('change', (nextAppState) => { + if (nextAppState.match(/inactive|background/)) { + BackgroundTimer.runBackgroundTimer(() => { + Geolocation.getCurrentPosition( + (position) => { + console.log( + 'getCurrentPosition background', + JSON.stringify(position) + ); + }, + (error) => + console.log( + 'getCurrentPosition background error', + JSON.stringify(error) + ), + { enableHighAccuracy: true } + ); + }, 1000); + + console.log('App has come to the foreground!'); + } else { + BackgroundTimer.stopBackgroundTimer(); + } + + appState.current = nextAppState; + }); + + return () => { + subscription.remove(); + }; + }, [backgroundListener]); + + return ( + +