message: remove `aws_crypto`

diff:
@@ -10,8 +10,6 @@ load(
cc_library(
name = "s3",
srcs = [
- "aws_crypto.cc",
- "aws_crypto.h",
"aws_logging.cc",
"aws_logging.h",
"s3_filesystem.cc",

change_type: DELETE

diff:
-/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-#include "tensorflow_io/core/plugins/s3/aws_crypto.h"
-
-#include <aws/core/utils/crypto/HashResult.h>
-#include <aws/s3/S3Client.h>
-#include <openssl/hmac.h>
-#include <openssl/rand.h>
-#include <openssl/sha.h>
-
-namespace tensorflow {
-namespace io {
-namespace s3 {
-namespace tf_s3_filesystem {
-
-namespace {
-class AWSSha256HMACOpenSSLImpl : public Aws::Utils::Crypto::HMAC {
- public:
- AWSSha256HMACOpenSSLImpl() {}
-
- virtual ~AWSSha256HMACOpenSSLImpl() = default;
-
- Aws::Utils::Crypto::HashResult Calculate(
- const Aws::Utils::ByteBuffer& toSign,
- const Aws::Utils::ByteBuffer& secret) override {
- unsigned int length = SHA256_DIGEST_LENGTH;
- Aws::Utils::ByteBuffer digest(length);
- memset(digest.GetUnderlyingData(), 0, length);
-
- HMAC_CTX ctx;
- HMAC_CTX_init(&ctx);
-
- HMAC_Init_ex(&ctx, secret.GetUnderlyingData(),
- static_cast<int>(secret.GetLength()), EVP_sha256(), NULL);
- HMAC_Update(&ctx, toSign.GetUnderlyingData(), toSign.GetLength());
- HMAC_Final(&ctx, digest.GetUnderlyingData(), &length);
- HMAC_CTX_cleanup(&ctx);
-
- return Aws::Utils::Crypto::HashResult(std::move(digest));
- }
-};
-
-class AWSSha256OpenSSLImpl : public Aws::Utils::Crypto::Hash {
- public:
- AWSSha256OpenSSLImpl() {}
-
- virtual ~AWSSha256OpenSSLImpl() = default;
-
- Aws::Utils::Crypto::HashResult Calculate(const Aws::String& str) override {
- SHA256_CTX sha256;
- SHA256_Init(&sha256);
- SHA256_Update(&sha256, str.data(), str.size());
-
- Aws::Utils::ByteBuffer hash(SHA256_DIGEST_LENGTH);
- SHA256_Final(hash.GetUnderlyingData(), &sha256);
-
- return Aws::Utils::Crypto::HashResult(std::move(hash));
- }
-
- Aws::Utils::Crypto::HashResult Calculate(Aws::IStream& stream) override {
- SHA256_CTX sha256;
- SHA256_Init(&sha256);
-
- auto currentPos = stream.tellg();
- if (currentPos == std::streampos(std::streamoff(-1))) {
- currentPos = 0;
- stream.clear();
- }
-
- stream.seekg(0, stream.beg);
-
- char streamBuffer
- [Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE];
- while (stream.good()) {
- stream.read(streamBuffer,
- Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE);
- auto bytesRead = stream.gcount();
-
- if (bytesRead > 0) {
- SHA256_Update(&sha256, streamBuffer, static_cast<size_t>(bytesRead));
- }
- }
-
- stream.clear();
- stream.seekg(currentPos, stream.beg);
-
- Aws::Utils::ByteBuffer hash(SHA256_DIGEST_LENGTH);
- SHA256_Final(hash.GetUnderlyingData(), &sha256);
-
- return Aws::Utils::Crypto::HashResult(std::move(hash));
- }
-};
-
-class AWSSecureRandomBytesImpl : public Aws::Utils::Crypto::SecureRandomBytes {
- public:
- AWSSecureRandomBytesImpl() {}
- virtual ~AWSSecureRandomBytesImpl() = default;
- void GetBytes(unsigned char* buffer, size_t bufferSize) override {
- assert(buffer);
- int success = RAND_bytes(buffer, static_cast<int>(bufferSize));
- if (success != 1) {
- m_failure = true;
- }
- }
-
- private:
- bool m_failure;
-};
-
-} // namespace
-
-std::shared_ptr<Aws::Utils::Crypto::Hash>
-AWSSHA256Factory::CreateImplementation() const {
- return Aws::MakeShared<AWSSha256OpenSSLImpl>(AWSCryptoAllocationTag);
-}
-
-std::shared_ptr<Aws::Utils::Crypto::HMAC>
-AWSSHA256HmacFactory::CreateImplementation() const {
- return Aws::MakeShared<AWSSha256HMACOpenSSLImpl>(AWSCryptoAllocationTag);
-}
-
-std::shared_ptr<Aws::Utils::Crypto::SecureRandomBytes>
-AWSSecureRandomFactory::CreateImplementation() const {
- return Aws::MakeShared<AWSSecureRandomBytesImpl>(AWSCryptoAllocationTag);
-}
-
-} // namespace tf_s3_filesystem
-} // namespace s3
-} // namespace io
-} // namespace tensorflow

diff:
-/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-#ifndef TENSORFLOW_C_EXPERIMENTAL_FILESYSTEM_PLUGINS_S3_AWS_CRYPTO_H_
-#define TENSORFLOW_C_EXPERIMENTAL_FILESYSTEM_PLUGINS_S3_AWS_CRYPTO_H_
-
-#include <aws/core/Aws.h>
-#include <aws/core/utils/crypto/Factories.h>
-#include <aws/core/utils/crypto/HMAC.h>
-#include <aws/core/utils/crypto/Hash.h>
-#include <aws/core/utils/crypto/SecureRandom.h>
-
-namespace tensorflow {
-namespace io {
-namespace s3 {
-namespace tf_s3_filesystem {
-constexpr char AWSCryptoAllocationTag[] = "AWSCryptoAllocation";
-
-class AWSSHA256Factory : public Aws::Utils::Crypto::HashFactory {
- public:
- std::shared_ptr<Aws::Utils::Crypto::Hash> CreateImplementation()
- const override;
-};
-
-class AWSSHA256HmacFactory : public Aws::Utils::Crypto::HMACFactory {
- public:
- std::shared_ptr<Aws::Utils::Crypto::HMAC> CreateImplementation()
- const override;
-};
-
-class AWSSecureRandomFactory : public Aws::Utils::Crypto::SecureRandomFactory {
- public:
- std::shared_ptr<Aws::Utils::Crypto::SecureRandomBytes> CreateImplementation()
- const override;
-};
-
-} // namespace tf_s3_filesystem
-} // namespace s3
-} // namespace io
-} // namespace tensorflow
-
-#endif // TENSORFLOW_C_EXPERIMENTAL_FILESYSTEM_PLUGINS_S3_AWS_CRYPTO_H_

diff:
@@ -39,7 +39,6 @@ limitations under the License.
#include "tensorflow/c/logging.h"
#include "tensorflow/c/tf_status.h"
#include "tensorflow_io/core/plugins/file_system_plugins.h"
-#include "tensorflow_io/core/plugins/s3/aws_crypto.h"
#include "tensorflow_io/core/plugins/s3/aws_logging.h"
namespace tensorflow {
@@ -193,18 +192,6 @@ static void GetS3Client(tf_s3_filesystem::S3File* s3_file) {
tf_s3_filesystem::AWSLogSystem::InitializeAWSLogging();
Aws::SDKOptions options;
- options.cryptoOptions.sha256Factory_create_fn = []() {
- return Aws::MakeShared<tf_s3_filesystem::AWSSHA256Factory>(
- tf_s3_filesystem::AWSCryptoAllocationTag);
- };
- options.cryptoOptions.sha256HMACFactory_create_fn = []() {
- return Aws::MakeShared<tf_s3_filesystem::AWSSHA256HmacFactory>(
- tf_s3_filesystem::AWSCryptoAllocationTag);
- };
- options.cryptoOptions.secureRandomFactory_create_fn = []() {
- return Aws::MakeShared<tf_s3_filesystem::AWSSecureRandomFactory>(
- tf_s3_filesystem::AWSCryptoAllocationTag);
- };
Aws::InitAPI(options);
// The creation of S3Client disables virtual addressing:
@@ -218,7 +205,7 @@ static void GetS3Client(tf_s3_filesystem::S3File* s3_file) {
Aws::New<Aws::S3::S3Client>(
kS3ClientAllocationTag, GetDefaultClientConfig(),
Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, false),
- [&options](Aws::S3::S3Client* s3_client) {
+ [options](Aws::S3::S3Client* s3_client) {
if (s3_client != nullptr) {
Aws::Delete(s3_client);
Aws::ShutdownAPI(options);

original_message: remove `aws_crypto` (#1385)


message: add missing symbol to `gcs_filesystem`

change_type: MODIFY

diff:
@@ -1249,6 +1249,11 @@ void ProvideFilesystemSupportFor(TF_FilesystemPluginOps* ops, const char* uri) {
ops->writable_file_ops = static_cast<TF_WritableFileOps*>(
plugin_memory_allocate(TF_WRITABLE_FILE_OPS_SIZE));
ops->writable_file_ops->cleanup = tf_writable_file::Cleanup;
+ ops->writable_file_ops->append = tf_writable_file::Append;
+ ops->writable_file_ops->tell = tf_writable_file::Tell;
+ ops->writable_file_ops->flush = tf_writable_file::Flush;
+ ops->writable_file_ops->sync = tf_writable_file::Sync;
+ ops->writable_file_ops->close = tf_writable_file::Close;
ops->read_only_memory_region_ops = static_cast<TF_ReadOnlyMemoryRegionOps*>(
plugin_memory_allocate(TF_READ_ONLY_MEMORY_REGION_OPS_SIZE));

license: Apache License 2.0

repo: tensorflow/io

original_message: add missing symbol to `gcs_filesystem` (#1396)


message: don't run tests on forks

diff:
@@ -13,6 +13,7 @@ env:
jobs:
macos:
+ if: github.repository == 'tensorflow/io' # Don't do this in forks
name: macOS ${{ matrix.python }} + ${{ matrix.version }}
runs-on: macos-latest
strategy:
@@ -53,6 +54,7 @@ jobs:
python -m pytest -s -v tests/test_filesystem.py
linux:
+ if: github.repository == 'tensorflow/io' # Don't do this in forks
name: Linux ${{ matrix.python }} + ${{ matrix.version }}
runs-on: ubuntu-20.04
strategy:
@@ -92,6 +94,7 @@ jobs:
python -m pytest -s -v tests/test_filesystem.py
windows:
+ if: github.repository == 'tensorflow/io' # Don't do this in forks
name: Windows ${{ matrix.python }} + ${{ matrix.version }}
runs-on: windows-latest
strategy:

diff:
@@ -7,6 +7,7 @@ on:
jobs:
macos:
+ if: github.repository == 'tensorflow/io' # Don't do this in forks
name: macOS ${{ matrix.python }} + ${{ matrix.version }}
runs-on: macos-latest
strategy:
@@ -40,6 +41,7 @@ jobs:
python -m pytest --benchmark-only -v --import-mode=append $(find . -type f \( -iname "test_*.py" ! \( -iname "test_*_v1.py" -o -iname "test_bigquery.py" \) \))
linux:
+ if: github.repository == 'tensorflow/io' # Don't do this in forks
name: Linux ${{ matrix.python }} + ${{ matrix.version }}
runs-on: ubuntu-20.04
strategy:

original_message: don't run tests on forks (#1406)


message: fix gcs compose mode

diff:
@@ -487,7 +487,7 @@ GCSFileSystemImplementation::GCSFileSystemImplementation(
google::cloud::storage::Client&& gcs_client)
: gcs_client(gcs_client), block_cache_lock() {
const char* append_mode = std::getenv(kAppendMode);
- compose = (append_mode != nullptr) && (!strcmp(kAppendMode, append_mode));
+ compose = (append_mode != nullptr) && (!strcmp(kComposeAppend, append_mode));
uint64_t value;
block_size = kDefaultBlockSize;

original_message: fix gcs compose mode (#1434)


message: bump `aws-sdk-cpp` to 1.8.186

old_path: WORKSPACE

new_path: WORKSPACE

diff:
@@ -82,11 +82,11 @@ http_archive(
"""sed -i.bak 's/UUID::RandomUUID/Aws::Utils::UUID::RandomUUID/g' aws-cpp-sdk-core/source/client/AWSClient.cpp""",
"""sed -i.bak 's/__attribute__((visibility("default")))//g' aws-cpp-sdk-core/include/aws/core/external/tinyxml2/tinyxml2.h """,
],
- sha256 = "758174f9788fed6cc1e266bcecb20bf738bd5ef1c3d646131c9ed15c2d6c5720",
- strip_prefix = "aws-sdk-cpp-1.7.336",
+ sha256 = "749322a8be4594472512df8a21d9338d7181c643a00e08a0ff12f07e831e3346",
+ strip_prefix = "aws-sdk-cpp-1.8.186",
urls = [
- "https://storage.googleapis.com/mirror.tensorflow.org/github.com/aws/aws-sdk-cpp/archive/1.7.336.tar.gz",
- "https://github.com/aws/aws-sdk-cpp/archive/1.7.336.tar.gz",
+ "https://storage.googleapis.com/mirror.tensorflow.org/github.com/aws/aws-sdk-cpp/archive/1.8.186.tar.gz",
+ "https://github.com/aws/aws-sdk-cpp/archive/1.8.186.tar.gz",
],
)

diff:
@@ -134,37 +134,6 @@ static Aws::Client::ClientConfiguration& GetDefaultClientConfig() {
absl::MutexLock l(&cfg_lock);
if (!init) {
- const char* region = getenv("AWS_REGION");
- // TODO (yongtang): `S3_REGION` should be deprecated after 2.0.
- if (!region) region = getenv("S3_REGION");
- if (region) {
- cfg.region = Aws::String(region);
- } else {
- // Load config file (e.g., ~/.aws/config) only if AWS_SDK_LOAD_CONFIG
- // is set with a truthy value.
- const char* load_config_env = getenv("AWS_SDK_LOAD_CONFIG");
- std::string load_config =
- load_config_env ? absl::AsciiStrToLower(load_config_env) : "";
- if (load_config == "true" || load_config == "1") {
- Aws::String config_file;
- // If AWS_CONFIG_FILE is set then use it, otherwise use ~/.aws/config.
- const char* config_file_env = getenv("AWS_CONFIG_FILE");
- if (config_file_env) {
- config_file = config_file_env;
- } else {
- const char* home_env = getenv("HOME");
- if (home_env) {
- config_file = home_env;
- config_file += "/.aws/config";
- }
- }
- Aws::Config::AWSConfigFileProfileConfigLoader loader(config_file);
- loader.Load();
- auto profiles = loader.GetProfiles();
- if (!profiles["default"].GetRegion().empty())
- cfg.region = profiles["default"].GetRegion();
- }
- }
// if these timeouts are low, you may see an error when
// uploading/downloading large files: Unable to connect to endpoint
int64_t timeout;


message: Wrapped positionStream in new StreamController

diff:
@@ -158,7 +158,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
);
}
- _positionStream = positionStream
+ _positionStream = _wrapStream(positionStream)
.map<Position>((dynamic element) =>
Position.fromMap(element.cast<String, dynamic>()))
.handleError(
@@ -175,6 +175,21 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
return _positionStream!;
}
+ Stream<dynamic> _wrapStream(Stream<dynamic> incoming) {
+ late StreamSubscription subscription;
+ late StreamController<dynamic> controller;
+ controller = StreamController<dynamic>(
+ onListen: () => subscription = incoming.listen((item) => controller.add(item)),
+ onPause: () => subscription.pause(),
+ onResume: () => subscription.resume(),
+ onCancel: () {
+ subscription.cancel();
+ _positionStream = null;
+ },
+ );
+ return controller.stream;
+ }
+
@override
Future<bool> openAppSettings() async => _methodChannel
.invokeMethod<bool>('openAppSettings')

license: MIT License

repo: baseflow/flutter-geolocator


message: Changed the method channel implementation

diff:
+## 2.0.3
+
+- Solved a bug which caused the distanceFilter/timeInterval not to update after initializing a new PositionStream (see issue [#703](https://github.com/Baseflow/flutter-geolocator/issues/703)).
+
## 2.0.2
- Added definition of the `ActivityMissingException`.

diff:
@@ -179,7 +179,8 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
late StreamSubscription subscription;
late StreamController<dynamic> controller;
controller = StreamController<dynamic>(
- onListen: () => subscription = incoming.listen((item) => controller.add(item)),
+ onListen: () =>
+ subscription = incoming.listen((item) => controller.add(item)),
onPause: () => subscription.pause(),
onResume: () => subscription.resume(),
onCancel: () {

diff:
@@ -3,7 +3,7 @@ description: A common platform interface for the geolocator plugin.
homepage: https://github.com/baseflow/flutter-geolocator
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
-version: 2.0.2
+version: 2.0.3
dependencies:
flutter:

diff:
@@ -558,8 +558,6 @@ void main() {
final methodChannelGeolocator = MethodChannelGeolocator();
final firstStream = methodChannelGeolocator.getPositionStream(
distanceFilter: 10);
- final secondStream = methodChannelGeolocator.getPositionStream(
- distanceFilter: 100);
// Start listening so u can cancel the stream subscription
StreamSubscription<Position>? firstSubscription =
@@ -569,13 +567,8 @@ void main() {
firstSubscription.cancel();
firstSubscription = null;
- // Start listening to second stream so u can cancel the subscription
- StreamSubscription<Position>? secondSubscription =
- secondStream.listen((event) { });
-
- // Cancel subscription
- secondSubscription.cancel();
- secondSubscription = null;
+ final secondStream = methodChannelGeolocator.getPositionStream(
+ distanceFilter: 100);
// Pro stream different options are used, thus the stream shouldn't
// be the same


message: Implementations issues fixed

diff:
@@ -135,14 +135,13 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
forceAndroidLocationManager: forceAndroidLocationManager,
timeInterval: timeInterval,
);
-
if (_positionStream != null) {
return _positionStream!;
}
-
- var positionStream = _eventChannel.receiveBroadcastStream(
+ var originalStream = _eventChannel.receiveBroadcastStream(
locationOptions.toJson(),
);
+ var positionStream = _wrapStream(originalStream);
if (timeLimit != null) {
positionStream = positionStream.timeout(
@@ -157,8 +156,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
},
);
}
-
- _positionStream = _wrapStream(positionStream)
+ _positionStream = positionStream
.map<Position>((dynamic element) =>
Position.fromMap(element.cast<String, dynamic>()))
.handleError(
@@ -167,11 +165,9 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
if (error is PlatformException) {
_handlePlatformException(error);
}
-
throw error;
},
);
-
return _positionStream!;
}

original_message: Implementations issues fixed


message: Added the locationServiceStream to the platform interface + edited pubspec.yaml and CHANGELOG

diff:
+## 2.1.0
+
+- Added the possibility to start a stream which will return an event when Location Services are manually enabled/disabled
+
## 2.0.2
- Added definition of the `ActivityMissingException`.

diff:
export 'location_accuracy.dart';
export 'location_permission.dart';
+export 'location_service_status.dart';

change_type: ADD

diff:
+/// Represents the possible Location Service Statuses
+enum LocationServiceStatus {
+ /// Location Services are enabled on the native device
+ enabled,
+
+ /// Location Servies are disabled on the native device
+ disabled
+}

diff:
@@ -107,6 +107,14 @@ abstract class GeolocatorPlatform extends PlatformInterface {
throw UnimplementedError('getCurrentPosition() has not been implemented.');
}
+ /// Fires when the Location Service is manually disabled or enabled f.e.
+ /// when Location Service in Settings is disabled, a event will be fired which
+ /// returns a [LocationServiceStatus].
+ Stream<LocationServiceStatus> getServiceStatusStream() {
+ throw UnimplementedError(
+ 'getServiceStatusStream() has not been implemented.');
+ }
+
/// Fires whenever the location changes inside the bounds of the
/// [desiredAccuracy].
///

diff:
@@ -21,6 +21,11 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
static const _eventChannel =
EventChannel('flutter.baseflow.com/geolocator_updates');
+ /// The event channel used to receive [LocationServiceStatus] updates from the
+ /// native platform.
+ static const _serviceStatusEventChannel =
+ EventChannel('flutter.baseflow.com/geolocator_service_updates');
+
/// On Android devices you can set [forceAndroidLocationManager]
/// to true to force the plugin to use the [LocationManager] to determine the
/// position instead of the [FusedLocationProviderClient]. On iOS this is
@@ -28,6 +33,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
bool forceAndroidLocationManager = false;
Stream<Position>? _positionStream;
+ Stream<LocationServiceStatus>? _serviceStatusStream;
@override
Future<LocationPermission> checkPermission() async {
@@ -121,6 +127,27 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
}
}
+ @override
+ Stream<LocationServiceStatus> getServiceStatusStream() {
+ if (_serviceStatusStream != null) {
+ return _serviceStatusStream!;
+ }
+ var serviceStatusStream =
+ _serviceStatusEventChannel.receiveBroadcastStream();
+
+ _serviceStatusStream = serviceStatusStream
+ .map((dynamic element) => element as LocationServiceStatus)
+ .handleError((error) {
+ _serviceStatusStream = null;
+ if (error is PlatformException) {
+ _handlePlatformException(error);
+ }
+ throw error;
+ });
+
+ return _serviceStatusStream!;
+ }
+
@override
Stream<Position> getPositionStream({
LocationAccuracy desiredAccuracy = LocationAccuracy.best,

diff:
@@ -3,7 +3,7 @@ description: A common platform interface for the geolocator plugin.
homepage: https://github.com/baseflow/flutter-geolocator
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
-version: 2.0.2
+version: 2.1.0
dependencies:
flutter:


message: Changed enum to bool

diff:
export 'location_accuracy.dart';
export 'location_permission.dart';
\ No newline at end of file
-export 'location_service_status.dart';

diff:
-/// Represents the possible Location Service Statuses
-enum LocationServiceStatus {
- /// Location Services are enabled on the native device
- enabled,
-
- /// Location Servies are disabled on the native device
- disabled
-}

diff:
@@ -110,7 +110,7 @@ abstract class GeolocatorPlatform extends PlatformInterface {
/// Fires when the Location Service is manually disabled or enabled f.e.
/// when Location Service in Settings is disabled, a event will be fired which
/// returns a [LocationServiceStatus].
- Stream<LocationServiceStatus> getServiceStatusStream() {
+ Stream<bool> getServiceStatusStream() {
throw UnimplementedError(
'getServiceStatusStream() has not been implemented.');
}

diff:
@@ -33,7 +33,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
bool forceAndroidLocationManager = false;
Stream<Position>? _positionStream;
- Stream<LocationServiceStatus>? _serviceStatusStream;
+ Stream<bool>? _serviceStatusStream;
@override
Future<LocationPermission> checkPermission() async {
@@ -128,7 +128,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
}
@override
- Stream<LocationServiceStatus> getServiceStatusStream() {
+ Stream<bool> getServiceStatusStream() {
if (_serviceStatusStream != null) {
return _serviceStatusStream!;
}
@@ -136,7 +136,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
_serviceStatusEventChannel.receiveBroadcastStream();
_serviceStatusStream = serviceStatusStream
- .map((dynamic element) => element as LocationServiceStatus)
+ .map((dynamic element) => element as bool)
.handleError((error) {
_serviceStatusStream = null;
if (error is PlatformException) {

original_message: Changed enum to bool


message: Example app changes and android implementation finished

diff:
+package com.baseflow.geolocator;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.location.LocationManager;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+
+import com.baseflow.geolocator.location.LocationServiceStatusReceiver;
+
+import io.flutter.plugin.common.BinaryMessenger;
+import io.flutter.plugin.common.EventChannel;
+
+public class LocationServiceHandlerImpl implements EventChannel.StreamHandler{
+
+ private static final String TAG = "LocationServiceHandler";
+
+ @Nullable private EventChannel channel;
+ @Nullable private Activity activity;
+ @Nullable private Context context;
+ @Nullable private LocationServiceStatusReceiver receiver;
+
+
+ void startListening(Context context, BinaryMessenger messenger){
+ if(channel != null){
+ Log.w(TAG, "Setting a event call handler before the last was disposed.");
+ stopListening();
+ }
+ channel = new EventChannel(messenger, "flutter.baseflow.com/geolocator_service_updates");
+ channel.setStreamHandler(this);
+ this.context = context;
+ }
+
+ void stopListening(){
+ if(channel == null){
+ return;
+ }
+ channel.setStreamHandler(null);
+ channel = null;
+ }
+
+ void setActivity(@Nullable Activity activity) { this.activity = activity;}
+
+ @Override
+ public void onListen(Object arguments, EventChannel.EventSink events) {
+ IntentFilter filter = new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION);
+ filter.addAction(Intent.ACTION_PROVIDER_CHANGED);
+ this.receiver = new LocationServiceStatusReceiver(arguments, events);
+ if(activity == null) return;
+ activity.registerReceiver(this.receiver, filter);
+ }
+
+ @Override
+ public void onCancel(Object arguments) {
+ activity.unregisterReceiver(this.receiver);
+ }
+
+}

diff:
+package com.baseflow.geolocator.location;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.location.LocationManager;
+
+import androidx.annotation.Nullable;
+
+import io.flutter.plugin.common.EventChannel;
+
+
+public class LocationServiceStatusReceiver extends BroadcastReceiver {
+ @Nullable
+ private final EventChannel.EventSink events;
+
+ private boolean isEnabled = false;
+
+ public LocationServiceStatusReceiver(@Nullable Object arguments, @Nullable EventChannel.EventSink events) {
+ this.events = events;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (LocationManager.PROVIDERS_CHANGED_ACTION.equals(intent.getAction())) {
+
+ LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
+ boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
+ boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
+
+
+ if (isGpsEnabled) {
+ /*
+ It may occur that the broadcastreceiver receives several events of the same type,
+ that's why u should check whether or not the event is fired more then one time.
+ This is realised by using the [isEnabled] boolean
+ */
+ if(!isEnabled){
+ isEnabled = true;
+ if (events != null) {
+ events.success(true);
+ }
+ }
+ } else {
+ if(isEnabled){
+ isEnabled = false;
+ if (events != null) {
+ events.success(false);
+ }
+ }
+
+ }
+ }
+ }
+}

diff:
@@ -32,6 +32,7 @@ class GeolocatorWidget extends StatefulWidget {
class _GeolocatorWidgetState extends State<GeolocatorWidget> {
final List<_PositionItem> _positionItems = <_PositionItem>[];
StreamSubscription<Position>? _positionStreamSubscription;
+ StreamSubscription<bool>? _locationServiceStatusSubscription;
@override
Widget build(BuildContext context) {
@@ -114,7 +115,7 @@ class _GeolocatorWidgetState extends State<GeolocatorWidget> {
onPressed: _toggleListening,
label: Text(() {
if (_positionStreamSubscription == null) {
- return "Start stream";
+ return "Start Position Updates stream";
} else {
final buttonText = _positionStreamSubscription!.isPaused
? "Resume"
@@ -126,6 +127,23 @@ class _GeolocatorWidgetState extends State<GeolocatorWidget> {
backgroundColor: _determineButtonColor(),
),
),
+ Positioned(
+ bottom: 430.0,
+ right: 10.0,
+ child: FloatingActionButton.extended(
+ onPressed: _toggleLocationServiceListener,
+ label: Text(() {
+ if(_locationServiceStatusSubscription == null) {
+ return "Start Location Service stream";
+ } else {
+ final buttonText = _locationServiceStatusSubscription!.isPaused
+ ? "Resume"
+ : "Pause";
+ return "$buttonText stream";
+ }
+ }())
+ )
+ ),
Positioned(
bottom: 290.0,
right: 10.0,
@@ -166,6 +184,29 @@ class _GeolocatorWidgetState extends State<GeolocatorWidget> {
return _isListening() ? Colors.green : Colors.red;
}
+ void _toggleLocationServiceListener() {
+ if(_locationServiceStatusSubscription == null){
+ final serviceStatusStream = Geolocator.getServiceStatusStream();
+ _locationServiceStatusSubscription = serviceStatusStream.handleError((error){
+ _locationServiceStatusSubscription?.cancel();
+ _locationServiceStatusSubscription = null;
+ }).listen((status) => setState(() => _positionItems.add(_PositionItem(
+ _PositionItemType.locationservicestatus, status.toString()))));
+ _locationServiceStatusSubscription?.pause();
+ }
+
+ setState((){
+ if(_locationServiceStatusSubscription == null){
+ return;
+ }
+ if(_locationServiceStatusSubscription!.isPaused) {
+ _locationServiceStatusSubscription!.resume();
+ }else{
+ _locationServiceStatusSubscription!.pause();
+ }
+ });
+ }
+
void _toggleListening() {
if (_positionStreamSubscription == null) {
final positionStream = Geolocator.getPositionStream();
@@ -204,6 +245,7 @@ class _GeolocatorWidgetState extends State<GeolocatorWidget> {
enum _PositionItemType {
permission,
position,
+ locationservicestatus
}
class _PositionItem {


message: Changed geolocator.dart

diff:
@@ -110,6 +110,10 @@ class Geolocator {
/// location when the user denied access.
/// Throws a [LocationServiceDisabledException] when the user allowed access,
/// but the location services of the device are disabled.
+
+ static Stream<bool> getServiceStatusStream() =>
+ GeolocatorPlatform.instance.getServiceStatusStream();
+
static Stream<Position> getPositionStream({
LocationAccuracy desiredAccuracy = LocationAccuracy.best,
int distanceFilter = 0,

original_message: Changed geolocator.dart


message: Last changes to iOS implementation

diff:
@@ -115,13 +115,13 @@ class _GeolocatorWidgetState extends State<GeolocatorWidget> {
onPressed: _toggleListening,
label: Text(() {
if (_positionStreamSubscription == null) {
- return "Start Position Updates stream";
+ return "Start position updates stream";
} else {
final buttonText = _positionStreamSubscription!.isPaused
? "Resume"
: "Pause";
- return "$buttonText stream";
+ return "$buttonText position updates stream";
}
}()),
backgroundColor: _determineButtonColor(),
@@ -134,16 +134,17 @@ class _GeolocatorWidgetState extends State<GeolocatorWidget> {
onPressed: _toggleLocationServiceListener,
label: Text(() {
if (_locationServiceStatusSubscription == null) {
- return "Start Location Service stream";
+ return "Start location service stream";
} else {
- final buttonText = _locationServiceStatusSubscription!.isPaused
+ final buttonText =
+ _locationServiceStatusSubscription!.isPaused
? "Resume"
: "Pause";
- return "$buttonText stream";
+ return "$buttonText location service stream";
}
- }())
- )
- ),
+ }()),
+ backgroundColor: _determineLocationServiceButtonColor(),
+ )),
Positioned(
bottom: 290.0,
right: 10.0,
@@ -180,14 +181,23 @@ class _GeolocatorWidgetState extends State<GeolocatorWidget> {
bool _isListening() => !(_positionStreamSubscription == null ||
_positionStreamSubscription!.isPaused);
+ bool _isLocationServiceListening() =>
+ !(_locationServiceStatusSubscription == null ||
+ _locationServiceStatusSubscription!.isPaused);
+
Color _determineButtonColor() {
return _isListening() ? Colors.green : Colors.red;
}
+ Color _determineLocationServiceButtonColor() {
+ return _isLocationServiceListening() ? Colors.green : Colors.red;
+ }
+
void _toggleLocationServiceListener() {
if (_locationServiceStatusSubscription == null) {
final serviceStatusStream = Geolocator.getServiceStatusStream();
- _locationServiceStatusSubscription = serviceStatusStream.handleError((error){
+ _locationServiceStatusSubscription = serviceStatusStream
+ .handleError((error) {
_locationServiceStatusSubscription?.cancel();
_locationServiceStatusSubscription = null;
}).listen((status) => setState(() => _positionItems.add(_PositionItem(
@@ -242,11 +252,7 @@ class _GeolocatorWidgetState extends State<GeolocatorWidget> {
}
}
-enum _PositionItemType {
- permission,
- position,
- locationservicestatus
-}
+enum _PositionItemType { permission, position, locationservicestatus }
class _PositionItem {
_PositionItem(this.type, this.displayValue);

diff:
#import "Utils/LocationDistanceMapper.h"
#import "Utils/LocationMapper.h"
-@interface GeolocatorPlugin() <FlutterStreamHandler>
+@interface GeolocatorPlugin() <FlutterStreamHandler, CLLocationManagerDelegate>
@property (strong, nonatomic) GeolocationHandler *geolocationHandler;
@property (strong, nonatomic) PermissionHandler *permissionHandler;
+@property (strong, nonatomic) CLLocationManager *locationManager;
@end
@implementation GeolocatorPlugin {
FlutterEventSink _eventSink;
+ FlutterEventSink _locationServiceEventSink;
}
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterEventChannel *eventChannel = [FlutterEventChannel
eventChannelWithName:@"flutter.baseflow.com/geolocator_updates"
binaryMessenger:registrar.messenger];
+ FlutterEventChannel *locationServiceEventChannel = [FlutterEventChannel
+ eventChannelWithName:@"flutter.baseflow.com/geolocator_service_updates"
+ binaryMessenger:registrar.messenger];
GeolocatorPlugin *instance = [[GeolocatorPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:methodChannel];
[eventChannel setStreamHandler:instance];
+ [locationServiceEventChannel setStreamHandler:instance];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
}
- (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(FlutterEventSink)eventSink {
+ if(arguments != nil){
if (_eventSink) {
return [FlutterError errorWithCode: GeolocatorErrorLocationSubscriptionActive
message: @"Already listening for location updates. If you want to restart listening please cancel other subscriptions first."
[weakSelf onLocationFailureWithErrorCode:errorCode
errorDescription:errorDescription];
}];
+ }else{
+ _locationServiceEventSink = eventSink;
+ if(self.locationManager == nil){
+ self.locationManager = [[CLLocationManager alloc] init];
+ self.locationManager.delegate = self;
+ }
+ }
return nil;
}
- (FlutterError *_Nullable)onCancelWithArguments:(id _Nullable)arguments {
[[self geolocationHandler] stopListening];
_eventSink = nil;
-
+ _locationServiceEventSink = nil;
+ self.locationManager = nil;
return nil;
}
}];
}
+- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
+ if([CLLocationManager locationServicesEnabled]){
+ _locationServiceEventSink([NSNumber numberWithBool:YES]);
+ }else{
+ _locationServiceEventSink([NSNumber numberWithBool:NO]);
+ }
+}
+
- (void)openSettings:(FlutterResult)result {
if (@available(iOS 10, *)) {
[[UIApplication sharedApplication]

original_message: Last changes to iOS implementation


message: Test added for platformexception

diff:
@@ -606,6 +606,46 @@ void main() {
await streamController.close();
});
+ test(
+ // ignore: lines_longer_than_80_chars
+ 'Should receive an exception if android activity is missing',
+ () async {
+ // Arrange
+ final streamController =
+ StreamController<PlatformException>.broadcast();
+ EventChannelMock(
+ channelName: 'flutter.baseflow.com/geolocator_service_updates',
+ stream: streamController.stream,
+ );
+
+ // Act
+ final positionStream = MethodChannelGeolocator().getServiceStatusStream();
+ final streamQueue = StreamQueue(positionStream);
+
+ // Emit test error
+ streamController.addError(PlatformException(
+ code: 'ACTIVITY_MISSING',
+ message: 'Activity missing',
+ details: null));
+
+ // Assert
+ expect(
+ streamQueue.next,
+ throwsA(
+ isA<ActivityMissingException>().having(
+ (e) => e.message,
+ 'message',
+ 'Activity missing',
+ ),
+ ));
+
+ // Clean up
+ streamQueue.cancel();
+ streamController.close();
+ });
+
+
+
test(
// ignore: lines_longer_than_80_chars
'Should receive a stream with position updates if permissions are granted',

original_message: Test added for platformexception


message: Small android changes

diff:
package com.baseflow.geolocator;
+import android.location.Location;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -20,6 +22,8 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware {
@Nullable private StreamHandlerImpl streamHandler;
+ @Nullable private LocationServiceHandlerImpl locationServiceHandler;
+
@SuppressWarnings("deprecation")
@Nullable private io.flutter.plugin.common.PluginRegistry.Registrar pluginRegistrar;
@@ -54,6 +58,10 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware {
StreamHandlerImpl streamHandler = new StreamHandlerImpl(geolocatorPlugin.geolocationManager);
streamHandler.startListening(registrar.context(), registrar.messenger());
streamHandler.setActivity(registrar.activity());
+
+ LocationServiceHandlerImpl locationServiceHandler = new LocationServiceHandlerImpl();
+ locationServiceHandler.startListening(registrar.context(), registrar.messenger());
+ locationServiceHandler.setActivity(registrar.activity());
}
@Override
@@ -64,6 +72,11 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware {
streamHandler = new StreamHandlerImpl(this.geolocationManager);
streamHandler.startListening(
flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger());
+
+ locationServiceHandler = new LocationServiceHandlerImpl();
+ locationServiceHandler.startListening(
+ flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()
+ );
}
@Override
@@ -77,6 +90,11 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware {
streamHandler.stopListening();
streamHandler = null;
}
+
+ if(locationServiceHandler != null){
+ locationServiceHandler.stopListening();
+ locationServiceHandler = null;
+ }
}
@Override
@@ -88,6 +106,10 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware {
streamHandler.setActivity(binding.getActivity());
}
+ if(locationServiceHandler != null){
+ locationServiceHandler.setActivity(binding.getActivity());
+ }
+
this.pluginBinding = binding;
registerListeners();
}
@@ -110,6 +132,9 @@ public class GeolocatorPlugin implements FlutterPlugin, ActivityAware {
if (streamHandler != null) {
streamHandler.setActivity(null);
}
+ if(locationServiceHandler != null){
+ streamHandler.setActivity(null);
+ }
deregisterListeners();
}

original_message: Small android changes


message: Service status enum added

diff:
export 'location_accuracy.dart';
export 'location_permission.dart';
+export 'location_service.dart';
\ No newline at end of file

diff:
+/// Describes the current state of the location service on the native platform.
+enum ServiceStatus {
+ /// Indicates that the location service on the native platform is enabled.
+ enabled,
+ /// Indicates that the location service on the native platform is enabled.
+ disabled,
+}
\ No newline at end of file

diff:
@@ -110,7 +110,7 @@ abstract class GeolocatorPlatform extends PlatformInterface {
/// Fires when the Location Service is manually disabled or enabled f.e.
/// when Location Service in Settings is disabled, a event will be fired which
/// returns a [LocationServiceStatus].
- Stream<bool> getServiceStatusStream() {
+ Stream<ServiceStatus> getServiceStatusStream() {
throw UnimplementedError(
'getServiceStatusStream() has not been implemented.');
}

diff:
@@ -33,7 +33,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
bool forceAndroidLocationManager = false;
Stream<Position>? _positionStream;
- Stream<bool>? _serviceStatusStream;
+ Stream<ServiceStatus>? _serviceStatusStream;
@override
Future<LocationPermission> checkPermission() async {
@@ -128,7 +128,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
}
@override
- Stream<bool> getServiceStatusStream() {
+ Stream<ServiceStatus> getServiceStatusStream() {
if (_serviceStatusStream != null) {
return _serviceStatusStream!;
}
@@ -136,7 +136,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
_serviceStatusEventChannel.receiveBroadcastStream();
_serviceStatusStream = serviceStatusStream
- .map((dynamic element) => element as bool)
+ .map((dynamic element) => element as ServiceStatus)
.handleError((error) {
_serviceStatusStream = null;
if (error is PlatformException) {

original_message: Service status enum added


message: Formatting issues fixed

diff:
enum ServiceStatus {
/// Indicates that the location service on the native platform is enabled.
enabled,
+
/// Indicates that the location service on the native platform is enabled.
disabled,
}

original_message: Formatting issues fixed


message: Test added to geolocator

diff:
@@ -32,7 +32,7 @@ class GeolocatorWidget extends StatefulWidget {
class _GeolocatorWidgetState extends State<GeolocatorWidget> {
final List<_PositionItem> _positionItems = <_PositionItem>[];
StreamSubscription<Position>? _positionStreamSubscription;
- StreamSubscription<bool>? _locationServiceStatusSubscription;
+ StreamSubscription<ServiceStatus>? _locationServiceStatusSubscription;
@override
Widget build(BuildContext context) {

diff:
@@ -111,9 +111,6 @@ class Geolocator {
/// Throws a [LocationServiceDisabledException] when the user allowed access,
/// but the location services of the device are disabled.
- static Stream<bool> getServiceStatusStream() =>
- GeolocatorPlatform.instance.getServiceStatusStream();
-
static Stream<Position> getPositionStream({
LocationAccuracy desiredAccuracy = LocationAccuracy.best,
int distanceFilter = 0,
@@ -129,6 +126,13 @@ class Geolocator {
timeLimit: timeLimit,
);
+ /// Fires whenever the location services are disabled/enabled in the notification
+ /// bar or in the device settings. Returns ServiceStatus.enabled when location
+ /// services are enabled and returns ServiceStatus.disabled when location
+ /// services are disabled
+ static Stream<ServiceStatus> getServiceStatusStream() =>
+ GeolocatorPlatform.instance.getServiceStatusStream();
+
/// Opens the App settings page.
///
/// Returns [true] if the location settings page could be opened, otherwise

diff:
@@ -11,8 +11,8 @@ dependencies:
flutter:
sdk: flutter
- geolocator_platform_interface: ^2.0.2
- geolocator_web: ^2.0.1
+ geolocator_platform_interface:
+ path: ../geolocator_platform_interface
dev_dependencies:
flutter_test:

diff:
@@ -53,6 +53,16 @@ void main() {
expect(position, mockPosition);
});
+ test('getServiceStatusStream', () async {
+ when(GeolocatorPlatform.instance.getServiceStatusStream())
+ .thenAnswer((_) => Stream.value(ServiceStatus.enabled));
+
+ final locationService = await Geolocator.getServiceStatusStream();
+
+ expect(locationService,
+ emitsInOrder([emits(ServiceStatus.enabled), emitsDone]));
+ });
+
test('getPositionStream', () async {
when(GeolocatorPlatform.instance.getPositionStream(
desiredAccuracy: LocationAccuracy.best,
@@ -163,6 +173,17 @@ class MockGeolocatorPlatform extends Mock
}) =>
Future.value(mockPosition);
+ @override
+ Stream<ServiceStatus> getServiceStatusStream() {
+ return super.noSuchMethod(
+ Invocation.method(
+ #getServiceStatusStream,
+ null,
+ ),
+ returnValue: Stream.value(ServiceStatus.enabled),
+ );
+ }
+
@override
Stream<Position> getPositionStream({
LocationAccuracy? desiredAccuracy = LocationAccuracy.best,

original_message: Test added to geolocator


message: Changelog and readme changed

diff:
+## 7.1.0
+- Added the locationServiceStream which fires an event if the location service of the device are disabled/enabled in the Android/iOS notification bar or in the Settings of the device.
+- Updated the `geolocator_platform_interface: 2.1.0`
+
## 7.0.3
- Android: Throw the `ActivityMissingException` when requesting permissions while the activity is not available (e.g. when the App is in the background);

diff:
@@ -190,6 +190,18 @@ StreamSubscription<Position> positionStream = Geolocator.getPositionStream(locat
});
```
+To listen for service status changes you can call the `getServiceStatusStream` to receive stream you can listen to and receive location service status updates.
+
+``` dart
+import 'package:geolocator/geolocator.dart';
+
+StreamSubscription<ServiceStatus> serviceStatusStream = Geolocator.getServiceStatusStream().listen(
+ (ServiceStatus status) {
+ print(status);
+ });
+```
+
+
To check if location services are enabled you can call the `isLocationServiceEnabled` method:
``` dart

diff:
name: geolocator
description: Geolocation plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API for generic location (GPS etc.) functions.
-version: 7.0.3
+version: 7.1.0
homepage: https://github.com/Baseflow/flutter-geolocator/tree/master/geolocator
environment:
@@ -11,8 +11,8 @@ dependencies:
flutter:
sdk: flutter
- geolocator_platform_interface:
- path: ../geolocator_platform_interface
+ geolocator_platform_interface: ^2.1.0
+ geolocator_web: ^2.0.1
dev_dependencies:
flutter_test:

original_message: Changelog and readme changed


message: Android enum added

diff:
@@ -38,14 +38,14 @@ public class LocationServiceStatusReceiver extends BroadcastReceiver {
if(!isEnabled){
isEnabled = true;
if (events != null) {
- events.success(true);
+ events.success(ServiceStatus.enabled);
}
}
} else {
if(isEnabled){
isEnabled = false;
if (events != null) {
- events.success(false);
+ events.success(ServiceStatus.disabled);
}
}

diff:
+package com.baseflow.geolocator.location;
+
+public enum ServiceStatus {
+ disabled,
+ enabled
+}

original_message: Android enum added


message: On the native platforms, an integer is returned instead of a boolean, getServiceStatusStream implementation changed

diff:
/// Describes the current state of the location service on the native platform.
enum ServiceStatus {
- /// Indicates that the location service on the native platform is enabled.
- enabled,
-
/// Indicates that the location service on the native platform is enabled.
disabled,
+ /// Indicates that the location service on the native platform is enabled.
+ enabled,
}

diff:
import 'dart:async';
+import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import '../../geolocator_platform_interface.dart';
@@ -136,8 +137,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
_serviceStatusEventChannel.receiveBroadcastStream();
_serviceStatusStream = serviceStatusStream
- .map((dynamic element) =>
- element as bool ? ServiceStatus.enabled : ServiceStatus.disabled)
+ .map((dynamic element) => ServiceStatus.values[element as int])
.handleError((error) {
_serviceStatusStream = null;
if (error is PlatformException) {

diff:
@@ -583,7 +583,7 @@ void main() {
'Should receive a stream with location service updates if permissions are granted',
() async {
// Arrange
- final streamController = StreamController<bool>.broadcast();
+ final streamController = StreamController<int>.broadcast();
EventChannelMock(
channelName: 'flutter.baseflow.com/geolocator_service_updates',
stream: streamController.stream);
@@ -594,12 +594,12 @@ void main() {
final streamQueue = StreamQueue(locationServiceStream);
// Emit test events
- streamController.add(true);
- streamController.add(false);
+ streamController.add(0); // disabled value in native enum
+ streamController.add(1); // enabled value in native enum
//Assert
- expect(await streamQueue.next, ServiceStatus.enabled);
expect(await streamQueue.next, ServiceStatus.disabled);
+ expect(await streamQueue.next, ServiceStatus.enabled);
// Clean up
await streamQueue.cancel();


message: Enum added to iOS implementation

diff:
@@ -29,7 +29,7 @@ public class LocationServiceStatusReceiver extends BroadcastReceiver {
boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
- if (isGpsEnabled) {
+ if (isGpsEnabled || isNetworkEnabled) {
/*
It may occur that the broadcastreceiver receives several events of the same type,
that's why u should check whether or not the event is fired more then one time.
@@ -38,14 +38,14 @@ public class LocationServiceStatusReceiver extends BroadcastReceiver {
if(!isEnabled){
isEnabled = true;
if (events != null) {
- events.success(ServiceStatus.enabled);
+ events.success(ServiceStatus.enabled.ordinal());
}
}
} else {
if(isEnabled){
isEnabled = false;
if (events != null) {
- events.success(ServiceStatus.disabled);
+ events.success(ServiceStatus.disabled.ordinal());
}
}

diff:
#import "Utils/LocationAccuracyMapper.h"
#import "Utils/LocationDistanceMapper.h"
#import "Utils/LocationMapper.h"
+#import "Utils/ServiceStatus.h"
@interface GeolocatorPlugin() <FlutterStreamHandler, CLLocationManagerDelegate>
@property (strong, nonatomic) GeolocationHandler *geolocationHandler;
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
if([CLLocationManager locationServicesEnabled]){
- _locationServiceEventSink([NSNumber numberWithBool:YES]);
+ _locationServiceEventSink([NSNumber numberWithInt:(ServiceStatus)enabled]);
}else{
- _locationServiceEventSink([NSNumber numberWithBool:NO]);
+ _locationServiceEventSink([NSNumber numberWithInt:(ServiceStatus)disabled]);
}
}

diff:
+//
+// ServiceStatus.h
+// Pods
+//
+// Created by Floris Smit on 03/06/2021.
+//
+
+#ifndef ServiceStatus_h
+#define ServiceStatus_h
+
+@interface ServiceStatusEnum : NSObject {
+
+}
+
+typedef enum {
+ disabled,
+ enabled
+} ServiceStatus;
+
+@end
+
+#endif /* ServiceStatus_h */

diff:
@@ -11,8 +11,8 @@ dependencies:
flutter:
sdk: flutter
- geolocator_platform_interface: ^2.1.0
- geolocator_web: ^2.0.1
+ geolocator_platform_interface:
+ path: ../geolocator_platform_interface
dev_dependencies:
flutter_test:

original_message: Enum added to iOS implementation


message: Formatting and analyze issues fixed

diff:
enum ServiceStatus {
/// Indicates that the location service on the native platform is enabled.
disabled,
+
/// Indicates that the location service on the native platform is enabled.
enabled,
}

diff:
import 'dart:async';
-import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import '../../geolocator_platform_interface.dart';

original_message: Formatting and analyze issues fixed


message: Pubspec.yaml edited

diff:
@@ -11,8 +11,8 @@ dependencies:
flutter:
sdk: flutter
- geolocator_platform_interface:
- path: ../geolocator_platform_interface
+ geolocator_platform_interface: ^2.1.0
+ geolocator_web: ^2.0.1
dev_dependencies:
flutter_test:

original_message: Pubspec.yaml edited


message: PR Change requests merged

diff:
## 7.1.0
+
- Added the locationServiceStream which fires an event if the location service of the device are disabled/enabled in the Android/iOS notification bar or in the Settings of the device.
- Updated the `geolocator_platform_interface: 2.1.0`

diff:
@@ -190,7 +190,7 @@ StreamSubscription<Position> positionStream = Geolocator.getPositionStream(locat
});
```
-To listen for service status changes you can call the `getServiceStatusStream` to receive stream you can listen to and receive location service status updates.
+To listen for service status changes you can call the `getServiceStatusStream`. This will return a `Stream<ServiceStatus>` which can be listened to, to receive location service status updates.
``` dart
import 'package:geolocator/geolocator.dart';

diff:
package com.baseflow.geolocator;
-import android.location.Location;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-
import com.baseflow.geolocator.location.GeolocationManager;
import com.baseflow.geolocator.permission.PermissionManager;
import io.flutter.embedding.engine.plugins.FlutterPlugin;

diff:
@@ -5,18 +5,17 @@ import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
-import androidx.annotation.Nullable;
+import androidx.annotation.NonNull;
import io.flutter.plugin.common.EventChannel;
-
public class LocationServiceStatusReceiver extends BroadcastReceiver {
- @Nullable
+ @NonNull
private final EventChannel.EventSink events;
private boolean isEnabled = false;
- public LocationServiceStatusReceiver(@Nullable Object arguments, @Nullable EventChannel.EventSink events) {
+ public LocationServiceStatusReceiver(@NonNull EventChannel.EventSink events) {
this.events = events;
}
@@ -37,17 +36,13 @@ public class LocationServiceStatusReceiver extends BroadcastReceiver {
*/
if (!isEnabled) {
isEnabled = true;
- if (events != null) {
events.success(ServiceStatus.enabled.ordinal());
}
- }
} else {
if (isEnabled) {
isEnabled = false;
- if (events != null) {
events.success(ServiceStatus.disabled.ordinal());
}
- }
}
}

diff:
@@ -201,7 +201,7 @@ class _GeolocatorWidgetState extends State<GeolocatorWidget> {
_locationServiceStatusSubscription?.cancel();
_locationServiceStatusSubscription = null;
}).listen((status) => setState(() => _positionItems.add(_PositionItem(
- _PositionItemType.locationservicestatus, status.toString()))));
+ _PositionItemType.locationServiceStatus, status.toString()))));
_locationServiceStatusSubscription?.pause();
}
@@ -252,7 +252,11 @@ class _GeolocatorWidgetState extends State<GeolocatorWidget> {
}
}
-enum _PositionItemType { permission, position, locationservicestatus }
+enum _PositionItemType {
+ permission,
+ position,
+ locationServiceStatus,
+}
class _PositionItem {
_PositionItem(this.type, this.displayValue);

diff:
@@ -110,7 +110,6 @@ class Geolocator {
/// location when the user denied access.
/// Throws a [LocationServiceDisabledException] when the user allowed access,
/// but the location services of the device are disabled.
-
static Stream<Position> getPositionStream({
LocationAccuracy desiredAccuracy = LocationAccuracy.best,
int distanceFilter = 0,

original_message: PR Change requests merged


message: All PR change requests resolved

diff:
@@ -27,7 +27,6 @@ public class LocationServiceStatusReceiver extends BroadcastReceiver {
boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
-
if (isGpsEnabled || isNetworkEnabled) {
/*
It may occur that the broadcastreceiver receives several events of the same type,

diff:
#ifndef ServiceStatus_h
#define ServiceStatus_h
-@interface ServiceStatusEnum : NSObject {
-
-}
-
typedef enum {
disabled,
enabled
} ServiceStatus;
-@end
-
#endif /* ServiceStatus_h */

original_message: All PR change requests resolved


message: Android build fail fix

diff:
@@ -48,7 +48,7 @@ public class LocationServiceHandlerImpl implements EventChannel.StreamHandler{
public void onListen(Object arguments, EventChannel.EventSink events) {
IntentFilter filter = new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION);
filter.addAction(Intent.ACTION_PROVIDER_CHANGED);
- this.receiver = new LocationServiceStatusReceiver(arguments, events);
+ this.receiver = new LocationServiceStatusReceiver(events);
if(activity == null) return;
activity.registerReceiver(this.receiver, filter);
}

original_message: Android build fail fix


message: Tests added, but not yet finished

diff:
@@ -183,6 +183,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
},
);
}
+
_positionStream = positionStream
.map<Position>((dynamic element) =>
Position.fromMap(element.cast<String, dynamic>()))
@@ -202,8 +203,8 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
late StreamSubscription subscription;
late StreamController<dynamic> controller;
controller = StreamController<dynamic>(
- onListen: () =>
- subscription = incoming.listen((item) => controller.add(item)),
+ onListen: () => subscription = incoming.listen((item)
+ => controller.add(item)),
onPause: () => subscription.pause(),
onResume: () => subscription.resume(),
onCancel: () {
@@ -211,7 +212,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
_positionStream = null;
},
);
- return controller.stream;
+ return controller.stream.asBroadcastStream();
}
@override

diff:
@@ -572,7 +572,7 @@ void main() {
// Pro stream different options are used, thus the stream shouldn't
// be the same
- expect(firstStream != secondStream, true);
+ expect(firstStream == secondStream, true);
});
});

original_message: Tests added, but not yet finished


message: Test added for the _wrapStream onListen and onCancel

diff:
@@ -575,6 +575,19 @@ void main() {
expect(firstStream == secondStream, true);
});
+ test('PositionStream can be listened to and can be canceled', () {
+ // Arrange
+ final methodChannelGeolocator = MethodChannelGeolocator();
+ final firstStream = methodChannelGeolocator.getPositionStream();
+ final secondStream = methodChannelGeolocator.getPositionStream();
+
+ // Act
+ firstStream.listen((event) {}).cancel();
+ secondStream.listen((event) {}).cancel();
+
+ // Assert
+ identical(firstStream, secondStream);
+ });
});
group(


message: Stream subscription

diff:
@@ -576,18 +576,21 @@ void main() {
});
test('PositionStream can be listened to and can be canceled', () {
// Arrange
- final streamController = StreamController<Position>.broadcast();
- EventChannelMock(
- channelName: 'flutter.baseflow.com/geolocator_updates',
- stream: streamController.stream);
+ final methodChannelGeolocator = MethodChannelGeolocator();
+ final stream = methodChannelGeolocator.getPositionStream();
- streamController.onCancel = () {};
- streamController.onListen = () {};
+ StreamSubscription<Position>? streamSubscription =
+ stream.listen((event) { });
- streamController.done;
- streamController.close();
+ streamSubscription.pause();
+ streamSubscription.resume();
+ streamSubscription.cancel();
+
+ streamSubscription.onDone(() {});
+
+ streamSubscription = null;
- expect(streamController.isClosed, true);
+ expect(streamSubscription, null);
});
});

original_message: Stream subscription


message: Broadcast stream fix

diff:
@@ -584,19 +584,18 @@ void main() {
var stream =
MethodChannelGeolocator().getPositionStream();
- var streamSubscription =
+ StreamSubscription<Position>? streamSubscription =
stream.listen((event) {});
streamController.onListen = () {};
- streamController.onResume = () {};
streamController.onCancel = () {};
- streamController.onPause = () {};
streamSubscription.pause();
expect(streamSubscription.isPaused, true);
streamSubscription.resume();
expect(streamSubscription.isPaused, false);
streamSubscription.cancel();
+ streamSubscription = null;
expect(streamSubscription, null);
});
});

original_message: Broadcast stream fix


message: Objective C implementation refactored

diff:
<Workspace
version = "1.0">
<FileRef
- location = "group:build">
- </FileRef>
- <FileRef
- location = "group:Flutter">
- </FileRef>
- <FileRef
- location = "group:Podfile">
- </FileRef>
- <FileRef
- location = "group:Podfile.lock">
- </FileRef>
- <FileRef
- location = "group:Pods">
- </FileRef>
- <FileRef
- location = "group:Runner">
+ location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
- location = "group:Runner.xcodeproj">
+ location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

diff:
eventChannelWithName:@"flutter.baseflow.com/geolocator_updates"
binaryMessenger:registrar.messenger];
+ FlutterEventChannel *locationServiceUpdatesEventChannel = [FlutterEventChannel eventChannelWithName:@"flutter.baseflow.com/geolocator_service_updates" binaryMessenger:registrar.messenger];
+
+
GeolocatorPlugin *instance = [[GeolocatorPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:methodChannel];
PositionStreamHandler *positionStreamHandler = [[PositionStreamHandler alloc] initWithGeolocationHandler:instance.geolocationHandler
PermissionHandler:instance.permissionHandler];
+
+ LocationServiceStreamHandler *locationServiceStreamHandler = [[LocationServiceStreamHandler alloc]];
[positionUpdatesEventChannel setStreamHandler:positionStreamHandler];
}

diff:
+//
+// LocationServiceStreamHandler.h
+// Pods
+//
+// Created by Floris Smit on 10/06/2021.
+//
+
+#ifndef LocationServiceStreamHandler_h
+#define LocationServiceStreamHandler_h
+
+#import <Flutter/Flutter.h>
+
+@interface LocationServiceStreamHandler : NSObject<FlutterStreamHandler, CLLocationManagerDelegate>
+
+@end
+
+
+#endif /* LocationServiceStreamHandler_h */

diff:
+//
+// LocationServiceHandler.m
+// geolocator
+//
+// Created by Floris Smit on 10/06/2021.
+//
+
+#import <Foundation/Foundation.h>
+#import <Flutter/Flutter.h>
+#import <CoreLocation/CoreLocation.h>
+#import "LocationServiceStreamHandler.h"
+#import "ServiceStatus.h"
+
+@interface LocationServiceStreamHandler()
+@property (strong, nonatomic) CLLocationManager *locationManager;
+@end
+
+@implementation LocationServiceStreamHandler {
+
+FlutterEventSink _eventSink;
+
+}
+
+- (FlutterError * _Nullable)onCancelWithArguments:(id _Nullable)arguments {
+ self.locationManager = nil;
+ _eventSink = nil;
+ return nil;
+}
+
+- (FlutterError * _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(nonnull FlutterEventSink)events {
+ _eventSink = events;
+ if(self.locationManager == nil){
+ self.locationManager = [[CLLocationManager alloc] init];
+ self.locationManager.delegate = self;
+ }
+ return nil;
+}
+
+- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
+ if([CLLocationManager locationServicesEnabled]){
+ _eventSink([NSNumber numberWithInt:(ServiceStatus)enabled]);
+ }else{
+ _eventSink([NSNumber numberWithInt:(ServiceStatus)disabled]);
+ }
+}
+
+@end

original_message: Objective C implementation refactored


message: iOS build fixes

diff:
#import "Utils/LocationAccuracyMapper.h"
#import "Utils/LocationDistanceMapper.h"
#import "Utils/LocationMapper.h"
+#import "LocationServiceStreamHandler.h"
@interface GeolocatorPlugin()
@property (strong, nonatomic) GeolocationHandler *geolocationHandler;
PositionStreamHandler *positionStreamHandler = [[PositionStreamHandler alloc] initWithGeolocationHandler:instance.geolocationHandler
PermissionHandler:instance.permissionHandler];
- LocationServiceStreamHandler *locationServiceStreamHandler = [[LocationServiceStreamHandler alloc]];
+ LocationServiceStreamHandler *locationServiceStreamHandler = [[LocationServiceStreamHandler alloc] init];
+
+ [locationServiceUpdatesEventChannel setStreamHandler:locationServiceStreamHandler];
[positionUpdatesEventChannel setStreamHandler:positionStreamHandler];
}

original_message: iOS build fixes


message: Changed the README so it doesn't cause a 404

diff:
@@ -51,7 +51,7 @@ android {
...
}
```
-3. Make sure you replace all the `android.` dependencies to their AndroidX counterparts (a full list can be found here: https://developer.android.com/jetpack/androidx/migrate).
+3. Make sure you replace all the `android.` dependencies to their AndroidX counterparts (a full list can be found here: [Migrate to AndroidX](https://developer.android.com/jetpack/androidx/migrate)).
**Permissions**


message: Changed the changelog.md and pubspec.yaml

diff:
+# 7.1.1
+
+- Resolved a 404 error when clicking on the AndroidX migration link in the README.md
+
## 7.1.0
- Added the locationServiceStream which fires an event if the location service of the device are disabled/enabled in the Android/iOS notification bar or in the Settings of the device.

diff:
@@ -51,7 +51,7 @@ android {
...
}
```
-3. Make sure you replace all the `android.` dependencies to their AndroidX counterparts (a full list can be found here: [Migrate to AndroidX](https://developer.android.com/jetpack/androidx/migrate)).
+3. Make sure you replace all the `android.` dependencies to their AndroidX counterparts (a full list can be found here: [Migrating to AndroidX](https://developer.android.com/jetpack/androidx/migrate)).
**Permissions**

diff:
name: geolocator
description: Geolocation plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API for generic location (GPS etc.) functions.
-version: 7.1.0
+version: 7.1.1
homepage: https://github.com/Baseflow/flutter-geolocator/tree/master/geolocator
environment:


message: location accuracy method processed in the platform interface

diff:
+## 2.2.0
+
+- Added the possibility to query for the LocationAccuracyStatus on iOS devices
+
## 2.1.1
- Solves a bug which resulted in an issue when closing the position stream and requesting a new one (see issue [#703](https://github.com/Baseflow/flutter-geolocator/issues/703)).

diff:
export 'location_accuracy.dart';
+export 'location_accuracy_status.dart';
export 'location_permission.dart';
export 'location_service.dart';

diff:
+/// Represent the current Location Accuracy Status on iOS devices
+enum LocationAccuracyStatus {
+ /// A approximate location will be returned (Approximate location)
+ reduced,
+
+ /// The precise location of the device will be returned
+ precise,
+}

diff:
@@ -159,6 +159,15 @@ abstract class GeolocatorPlatform extends PlatformInterface {
throw UnimplementedError('getPositionStream() has not been implemented.');
}
+ /// Returns a [Future] containing a [LocationAccuracyStatus]
+ /// When on iOS the user has given permission for approximate location,
+ /// [LocationAccuracyStatus.reduced] will be returned, if the user gave
+ /// permission for precise/full accuracy location, [LocationAccuracyStatus.precise]
+ /// will be returned
+ Future<LocationAccuracyStatus> getLocationAccuracy() async {
+ throw UnimplementedError('getLocationAccuracy() has not been implemented.');
+ }
+
/// Opens the App settings page.
///
/// Returns [true] if the app settings page could be opened, otherwise

diff:
import 'dart:async';
+import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../../geolocator_platform_interface.dart';
@@ -90,6 +91,12 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
}
}
+ @override
+ Future<LocationAccuracyStatus> getLocationAccuracy() async {
+ final accuracy = await _methodChannel.invokeMethod('getLocationAccuracy');
+ return LocationAccuracyStatus.values[accuracy as int];
+ }
+
@override
Future<Position> getCurrentPosition({
LocationAccuracy desiredAccuracy = LocationAccuracy.best,

diff:
@@ -3,7 +3,7 @@ description: A common platform interface for the geolocator plugin.
homepage: https://github.com/baseflow/flutter-geolocator
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
-version: 2.1.1
+version: 2.2.0
dependencies:
flutter:

diff:
@@ -101,6 +101,20 @@ void main() {
);
});
+ test(
+ // ignore: lines_longer_than_80_chars
+ 'Default implementation of getLocationAccuracy should throw unimplemented error',
+ () {
+ // Arrange
+ final geolocatorPlatform = ExtendsGeolocatorPlatform();
+
+ // Act & Assert
+ expect(
+ geolocatorPlatform.getLocationAccuracy(),
+ throwsUnimplementedError,
+ );
+ });
+
test(
// ignore: lines_longer_than_80_chars
'Default implementation of getServiceStatusStream should throw unimplemented error',

diff:
@@ -134,6 +134,46 @@ void main() {
});
});
+ group('getLocationAccuracy: When requesting the Location Accuracy Status',
+ () {
+ test(
+ 'Should receive reduced accuracy if Location Accuracy is reduced',
+ () async {
+ // Arrange
+ MethodChannelMock(
+ channelName: 'flutter.baseflow.com/geolocator',
+ method: 'getLocationAccuracy',
+ result: 0,
+ );
+
+ // Act
+ final locationAccuracy =
+ await MethodChannelGeolocator().getLocationAccuracy();
+
+ // Assert
+ expect(locationAccuracy, LocationAccuracyStatus.reduced);
+ });
+
+ test(
+ 'Should receive reduced accuracy if Location Accuracy is reduced',
+ () async {
+ // Arrange
+ MethodChannelMock(
+ channelName: 'flutter.baseflow.com/geolocator',
+ method: 'getLocationAccuracy',
+ result: 1,
+ );
+
+ // Act
+ final locationAccuracy =
+ await MethodChannelGeolocator().getLocationAccuracy();
+
+ // Assert
+ expect(locationAccuracy, LocationAccuracyStatus.precise);
+ });
+
+ });
+
group('requestPermission: When requesting for permission', () {
test(
// ignore: lines_longer_than_80_chars


message: Requested changes resolved

diff:
## 2.2.0
-- Added the possibility to query for the LocationAccuracyStatus on iOS devices
+- Added the possibility to query for the LocationAccuracyStatus on devices running iOS 14.0 and higher.
## 2.1.1

diff:
-/// Represent the current Location Accuracy Status on iOS devices
+/// Represent the current Location Accuracy Status on iOS 14.0 and higher.
enum LocationAccuracyStatus {
- /// A approximate location will be returned (Approximate location)
+ /// A approximate location will be returned (Approximate location).
reduced,
- /// The precise location of the device will be returned
+ /// The precise location of the device will be returned.
precise,
}

diff:
@@ -159,11 +159,12 @@ abstract class GeolocatorPlatform extends PlatformInterface {
throw UnimplementedError('getPositionStream() has not been implemented.');
}
- /// Returns a [Future] containing a [LocationAccuracyStatus]
+ /// Returns a [Future] containing a [LocationAccuracyStatus].
+ ///
/// When on iOS the user has given permission for approximate location,
/// [LocationAccuracyStatus.reduced] will be returned, if the user gave
/// permission for precise/full accuracy location, [LocationAccuracyStatus.precise]
- /// will be returned
+ /// will be returned.
Future<LocationAccuracyStatus> getLocationAccuracy() async {
throw UnimplementedError('getLocationAccuracy() has not been implemented.');
}

diff:
@@ -92,8 +92,9 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
@override
Future<LocationAccuracyStatus> getLocationAccuracy() async {
- final accuracy = await _methodChannel.invokeMethod('getLocationAccuracy');
- return LocationAccuracyStatus.values[accuracy as int];
+ final int accuracy =
+ await _methodChannel.invokeMethod('getLocationAccuracy');
+ return LocationAccuracyStatus.values[accuracy];
}
@override

original_message: Requested changes resolved


message: Requested changes commit

diff:
# 7.2.0
-- iOS 14: Users can now query whether they gave permission for Approximate location fetching or Precise location fetching
+- iOS 14: Users can now query whether they gave permission for Approximate location fetching or Precise location fetching.
# 7.1.1
-- Resolved a 404 error when clicking on the AndroidX migration link in the README.md
+- Resolved a 404 error when clicking on the AndroidX migration link in the README.md.
## 7.1.0

diff:
@@ -202,10 +202,9 @@ StreamSubscription<ServiceStatus> serviceStatusStream = Geolocator.getServiceSta
```
**iOS 14+ only**
-To query if a user enabled Approximate location fetching or Precise location fetching, you can call `getLocationAccuracy`.
-This will return a `Future<LocationAccuracyStatus` containing `LocationAccuracyStatus.reduced` if the user has enabled Approximate location fetching and containing `LocationAccuracyStatus.precise` if the user has enabled Precise location fetching.
-When calling `getLocationAccuracy` when the user has not given permission yet, the method will return `LocationAccuracyStatus.reduced` on default.
-If the user uses iOS 13 or below, the method `getLocationAccuracy` will return `LocationAccuracyStatus.precise`, since that is the default value for iOS 13 and below.
+To query if a user enabled Approximate location fetching or Precise location fetching, you can call the `Geolocator().getLocationAccuracy()` method. This will return a `Future<LocationAccuracyStatus>`, which when completed contains a `LocationAccuracyStatus.reduced` if the user has enabled Approximate location fetching or `LocationAccuracyStatus.precise` if the user has enabled Precise location fetching.
+When calling `getLocationAccuracy` before the user has given permission, the method will return `LocationAccuracyStatus.reduced` by default.
+On iOS 13 or below, the method `getLocationAccuracy` will always return `LocationAccuracyStatus.precise`, since that is the default value for iOS 13 and below.
``` dart
import 'package:geolocator/geolocator.dart';

diff:
#import <CoreLocation/CoreLocation.h>
#import "LocationAccuracyHandler.h"
-@interface LocationAccuracyHandler()
- @property (strong, nonatomic) CLLocationManager *locationManager;
-@end
-
@implementation LocationAccuracyHandler
- (void) getLocationAccuracyWithResult:(FlutterResult)result {
- self.locationManager = [[CLLocationManager alloc] init];
+ CLLocationManager *locationManager = [[CLLocationManager alloc] init];
if (@available(iOS 14, *)) {
- switch ([self.locationManager accuracyAuthorization]) {
+ switch ([locationManager accuracyAuthorization]) {
case CLAccuracyAuthorizationFullAccuracy:
return result([NSNumber numberWithInt:(LocationAccuracy)precise]);
case CLAccuracyAuthorizationReducedAccuracy:

original_message: Requested changes commit


message: Finished iOS implementation

diff:
@@ -11,3 +11,7 @@ FOUNDATION_EXPORT NSString * const GeolocatorErrorLocationSubscriptionActive;
FOUNDATION_EXPORT NSString * const GeolocatorErrorPermissionDefinitionsNotFound;
FOUNDATION_EXPORT NSString * const GeolocatorErrorPermissionDenied;
FOUNDATION_EXPORT NSString * const GeolocatorErrorPermissionRequestInProgress;
+FOUNDATION_EXPORT NSString * const GeolocatorErrorTemporaryAccuracyDictionaryNotFound;
+FOUNDATION_EXPORT NSString * const GeolocatorErrorPreciseAccuracyEnabled;
+FOUNDATION_EXPORT NSString * const GeolocatorErrorApproximateLocationNotSupported;
+

diff:
@@ -13,3 +13,6 @@ NSString * const GeolocatorErrorLocationSubscriptionActive = @"LOCATION_SUBSCRIP
NSString * const GeolocatorErrorPermissionDefinitionsNotFound = @"PERMISSION_DEFINITIONS_NOT_FOUND";
NSString * const GeolocatorErrorPermissionDenied = @"PERMISSION_DENIED";
NSString * const GeolocatorErrorPermissionRequestInProgress = @"PERMISSION_REQUEST_IN_PROGRESS";
+NSString * const GeolocatorErrorTemporaryAccuracyDictionaryNotFound = @"ACCURACY_DICTIONARY_NOT_FOUND";
+NSString * const GeolocatorErrorPreciseAccuracyEnabled = @"PRECISE_ACCURACY_ENABLED";
+NSString * const GeolocatorErrorApproximateLocationNotSupported = @"APPROXIMATE_LOCATION_NOT_SUPPORTED";

diff:
} else if([@"getLocationAccuracy" isEqualToString:call.method]) {
LocationAccuracyHandler *locationAccuracyHandler = [[LocationAccuracyHandler alloc] init];
[locationAccuracyHandler getLocationAccuracyWithResult:result];
+ } else if([@"requestTemporaryFullAccuracy" isEqualToString:call.method]) {
+ LocationAccuracyHandler *locationAccuracyHandler = [[LocationAccuracyHandler alloc] init];
+ [locationAccuracyHandler requestTemporaryFullAccuracyWithResult:result];
} else if ([@"openAppSettings" isEqualToString:call.method]) {
[self openSettings:result];
} else if ([@"openLocationSettings" isEqualToString:call.method]) {

diff:
@@ -18,6 +18,7 @@ typedef enum {
@interface LocationAccuracyHandler : NSObject
- (void) getLocationAccuracyWithResult:(FlutterResult)result;
+- (void) requestTemporaryFullAccuracyWithResult:(FlutterResult)result;
@end

diff:
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import "LocationAccuracyHandler.h"
+#import "ErrorCodes.h"
@implementation LocationAccuracyHandler
}
}
+- (void) requestTemporaryFullAccuracyWithResult:(FlutterResult)result {
+ NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
+ if ([dictionary objectForKey:@"TemporaryPreciseAccuracy"]) {
+ return result([FlutterError errorWithCode:GeolocatorErrorTemporaryAccuracyDictionaryNotFound
+ message:@"The temporary accuracy dictionary key is not set in the infop.list"
+ details:nil]);
+ }
+ CLLocationManager *locationManager = [[CLLocationManager alloc] init];
+ if (@available(iOS 14.0, *)) {
+ switch ([locationManager accuracyAuthorization]) {
+ case CLAccuracyAuthorizationReducedAccuracy: {
+ [locationManager requestTemporaryFullAccuracyAuthorizationWithPurposeKey:@"TemporaryPreciseAccuracy"
+ completion:^(NSError *error) {
+ if (error != nil) {
+ return;
+ } else {
+ // This error should never be thrown, since all the error cases are covered
+ return result([FlutterError errorWithCode:[[NSNumber numberWithInteger:error.code] stringValue]
+ message:error.description
+ details:nil]);
+ }
+ }];
+ return;
+ }
+ case CLAccuracyAuthorizationFullAccuracy:
+ return result([FlutterError errorWithCode:GeolocatorErrorPreciseAccuracyEnabled
+ message:@"Precise Location Accuracy is already enabled"
+ details:nil]);
+ }
+ } else {
+ return result([FlutterError errorWithCode:GeolocatorErrorApproximateLocationNotSupported
+ message:@"iOS 13 and below does not support requesting temporary full accuracy"
+ details:nil]);
+ }
+}
+
@end

original_message: Finished iOS implementation


message: Finished platform interface for temporary precise location

diff:
+## 2.3.0
+
+- Added the possibility to request temporary Precise Accuracy on iOS 14+ devices.
+
## 2.2.0
- Added the possibility to query for the LocationAccuracyStatus on devices running iOS 14.0 and higher.

diff:
+ /// An exception thrown when the Temporary Accuracy request key is missing in
+ /// the Info.plist. The exception is only thrown on iOS.
+ class AccuracyDictionaryNotFoundException implements Exception {
+ /// Constructs the [AccuracyDictionaryNotFoundException]
+ const AccuracyDictionaryNotFoundException(this.message);
+
+ /// A [message] describing more details about the missing Dictionary key.
+ final String? message;
+
+ @override
+ String toString() {
+ if (message == null || message == '') {
+ return 'Temporary Full accuracy key or description: '
+ '\'NSLocationTemporaryUsageDescriptionDictionary\' is missing in the'
+ ' Info.plist dictionary.'
+ ;
+ }
+ return message!;
+ }
+ }
\ No newline at end of file

diff:
+/// An exception thrown when users using iOS 13 or below try to execute the
+/// 'requestTemporaryFullAccuracy' method.
+///
+/// Since Approximate location only supports iOS 14 or above, the exception is
+/// only thrown when using iOS 13 or below
+class ApproximateLocationNotSupportedException implements Exception {
+ /// Constructs the [ApproximateLocationNotSupportedException]
+ const ApproximateLocationNotSupportedException(this.message);
+
+ /// A [message] describing more details about the exception
+ final String? message;
+
+ @override
+ String toString() {
+ if(message == null || message == ''){
+ return 'The \'requestTemporaryFullAccuracy\' method only supports iOS 14'
+ 'or above.';
+ }
+ return message!;
+ }
+}
\ No newline at end of file

diff:
+export 'accuracy_dictionary_not_found_exception.dart';
export 'activity_missing_exception.dart';
export 'already_subscribed_exception.dart';
+export 'approximate_location_not_supported_exception.dart';
export 'invalid_permission_exception.dart';
export 'location_service_disabled_exception.dart';
export 'permission_definitions_not_found_exception.dart';
export 'permission_denied_exception.dart';
export 'permission_request_in_progress_exception.dart';
export 'position_update_exception.dart';
+export 'precise_accuracy_enabled_exception.dart';

diff:
+/// An exception thrown when the user already enabled Precise Location fetching.
+///
+/// This exception is thrown only when using iOS 14 or above.
+class PreciseAccuracyEnabledException implements Exception {
+ /// Constructs the [PreciseAccuracyEnabledException]
+ const PreciseAccuracyEnabledException(this.message);
+
+ /// A [message] describing more details about the exception.
+ final String? message;
+
+ @override
+ String toString() {
+ if (message == null || message == ''){
+ return 'The user already enabled Precise location fetching, when using '
+ 'the \'requestTemporaryFullAccuracy\', make sure to check whether the'
+ 'user has already given permission to use Precise Accuracy.';
+ }
+
+ return message!;
+ }
+}
\ No newline at end of file

diff:
@@ -158,6 +158,19 @@ abstract class GeolocatorPlatform extends PlatformInterface {
}) {
throw UnimplementedError('getPositionStream() has not been implemented.');
}
+ /// Asks the user for Temporary Precise location access (iOS 14 or above).
+ ///
+ /// Throws a [AccuracyDictionaryNotFoundException] when the key
+ /// `NSLocationTemporaryUsageDescriptionDictionary` has not been set in the
+ /// `Infop.list`.
+ /// Throws a [PreciseAccuracyEnabledException] when the user already gave
+ /// permission to use Precise Accuracy location fetching.
+ /// Throws a [ApproximateLocationNotSupportedException] when Approximate
+ /// Location is not supported (iOS 13 or below)
+ Future<void> requestTemporaryFullAccuracy(){
+ // ignore: lines_longer_than_80_chars
+ throw UnimplementedError('requestTemporaryFullAccuracy() has not been implemented');
+ }
/// Returns a [Future] containing a [LocationAccuracyStatus].
///

diff:
@@ -225,6 +225,18 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
return controller.stream.asBroadcastStream();
}
+ @override
+ Future<void> requestTemporaryFullAccuracy() async {
+ try {
+ final accuracyFuture = await _methodChannel
+ .invokeMethod('requestTemporaryFullAccuracy');
+ return accuracyFuture;
+ } on PlatformException catch (e) {
+ _handlePlatformException(e);
+ rethrow;
+ }
+ }
+
@override
Future<bool> openAppSettings() async => _methodChannel
.invokeMethod<bool>('openAppSettings')
@@ -251,6 +263,12 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
throw PermissionRequestInProgressException(exception.message);
case 'LOCATION_UPDATE_FAILURE':
throw PositionUpdateException(exception.message);
+ case 'ACCURACY_DICTIONARY_NOT_FOUND':
+ throw AccuracyDictionaryNotFoundException(exception.message);
+ case 'PRECISE_ACCURACY_ENABLED':
+ throw PreciseAccuracyEnabledException(exception.message);
+ case 'APPROXIMATE_LOCATION_NOT_SUPPORTED':
+ throw ApproximateLocationNotSupportedException(exception.message);
default:
throw exception;
}

diff:
@@ -3,7 +3,7 @@ description: A common platform interface for the geolocator plugin.
homepage: https://github.com/baseflow/flutter-geolocator
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
-version: 2.2.0
+version: 2.3.0
dependencies:
flutter:

diff:
@@ -134,10 +134,100 @@ void main() {
});
});
+ group(
+ // ignore: lines_longer_than_80_chars
+ 'requestTemporaryFullAccuracy: When requesting Temporary Precise location',
+ () {
+ test('Should receive an exception when precise location is enabled',
+ () async {
+ MethodChannelMock(
+ channelName: 'flutter.baseflow.com/geolocator',
+ method: 'requestTemporaryFullAccuracy',
+ result: PlatformException(
+ code: 'PRECISE_ACCURACY_ENABLED',
+ message: 'Precise location is enabled.',
+ details: null,
+ ),
+ );
+
+ // Act
+ final accuracyFuture = MethodChannelGeolocator()
+ .requestTemporaryFullAccuracy();
+
+ // Assert
+ expect(
+ accuracyFuture,
+ throwsA(
+ isA<PreciseAccuracyEnabledException>().having(
+ (e) => e.message,
+ 'description',
+ 'Precise location is enabled.',
+ ),
+ ),
+ );
+ });
+ test('Should receive an exception when iOS 13 or below is used',
+ () async {
+ MethodChannelMock(
+ channelName: 'flutter.baseflow.com/geolocator',
+ method: 'requestTemporaryFullAccuracy',
+ result: PlatformException(
+ code: 'APPROXIMATE_LOCATION_NOT_SUPPORTED',
+ message: 'Approximate location not supported.',
+ details: null,
+ ),
+ );
+
+ // Act
+ final accuracyFuture = MethodChannelGeolocator()
+ .requestTemporaryFullAccuracy();
+
+ // Assert
+ expect(
+ accuracyFuture,
+ throwsA(
+ isA<ApproximateLocationNotSupportedException>().having(
+ (e) => e.message,
+ 'description',
+ 'Approximate location not supported.',
+ ),
+ ),
+ );
+ });
+ test('Should receive an exception when the location accuracy definition'
+ ' in the Info.plist is missing',
+ () async {
+ MethodChannelMock(
+ channelName: 'flutter.baseflow.com/geolocator',
+ method: 'requestTemporaryFullAccuracy',
+ result: PlatformException(
+ code: 'ACCURACY_DICTIONARY_NOT_FOUND',
+ message: 'Accuracy definition missing.',
+ details: null,
+ ),
+ );
+
+ // Act
+ final accuracyFuture = MethodChannelGeolocator()
+ .requestTemporaryFullAccuracy();
+
+ // Assert
+ expect(
+ accuracyFuture,
+ throwsA(
+ isA<AccuracyDictionaryNotFoundException>().having(
+ (e) => e.message,
+ 'description',
+ 'Accuracy definition missing.',
+ ),
+ ),
+ );
+ });
+ });
+
group('getLocationAccuracy: When requesting the Location Accuracy Status',
() {
- test(
- 'Should receive reduced accuracy if Location Accuracy is reduced',
+ test('Should receive reduced accuracy if Location Accuracy is reduced',
() async {
// Arrange
MethodChannelMock(
@@ -154,8 +244,7 @@ void main() {
expect(locationAccuracy, LocationAccuracyStatus.reduced);
});
- test(
- 'Should receive reduced accuracy if Location Accuracy is reduced',
+ test('Should receive reduced accuracy if Location Accuracy is reduced',
() async {
// Arrange
MethodChannelMock(
@@ -171,7 +260,6 @@ void main() {
// Assert
expect(locationAccuracy, LocationAccuracyStatus.precise);
});
-
});
group('requestPermission: When requesting for permission', () {


message: Small change to platform interface

diff:
@@ -228,7 +228,7 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
@override
Future<void> requestTemporaryFullAccuracy() async {
try {
- final accuracyFuture = await _methodChannel
+ final accuracyFuture = _methodChannel
.invokeMethod('requestTemporaryFullAccuracy');
return accuracyFuture;
} on PlatformException catch (e) {

original_message: Small change to platform interface


message: Tests changes

diff:
@@ -228,8 +228,9 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
@override
Future<void> requestTemporaryFullAccuracy() async {
try {
- final accuracyFuture =
- _methodChannel.invokeMethod('requestTemporaryFullAccuracy');
+ final accuracyFuture = await _methodChannel
+ .invokeMethod('requestTemporaryFullAccuracy')
+ .then((value) => value);
return accuracyFuture;
} on PlatformException catch (e) {
_handlePlatformException(e);

diff:
@@ -73,6 +73,20 @@ void main() {
);
});
+ test(
+ // ignore: lines_longer_than_80_chars
+ 'Default implementation of reqquestTemporaryAccuracy should throw unimplemented error',
+ () {
+ // Arrange
+ final geolocatorPlatform = ExtendsGeolocatorPlatform();
+
+ // Act & Assert
+ expect(
+ geolocatorPlatform.requestTemporaryFullAccuracy,
+ throwsUnimplementedError,
+ );
+ });
+
test(
// ignore: lines_longer_than_80_chars
'Default implementation of getCurrentPosition should throw unimplemented error',

original_message: Tests changes


message: Changed accuracy definition exception to existing permission definition not found exception

diff:
-/// An exception thrown when the Temporary Accuracy request key is missing in
-/// the Info.plist. The exception is only thrown on iOS.
-class AccuracyDictionaryNotFoundException implements Exception {
- /// Constructs the [AccuracyDictionaryNotFoundException]
- const AccuracyDictionaryNotFoundException(this.message);
-
- /// A [message] describing more details about the missing Dictionary key.
- final String? message;
-
- @override
- String toString() {
- if (message == null || message == '') {
- return 'Temporary Full accuracy key or description: '
- 'NSLocationTemporaryUsageDescriptionDictionary is missing in the'
- ' Info.plist dictionary.';
- }
- return message!;
- }
-}

diff:
-export 'accuracy_dictionary_not_found_exception.dart';
export 'activity_missing_exception.dart';
export 'already_subscribed_exception.dart';
export 'approximate_location_not_supported_exception.dart';

diff:
@@ -262,8 +262,6 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
throw PermissionRequestInProgressException(exception.message);
case 'LOCATION_UPDATE_FAILURE':
throw PositionUpdateException(exception.message);
- case 'ACCURACY_DICTIONARY_NOT_FOUND':
- throw AccuracyDictionaryNotFoundException(exception.message);
case 'PRECISE_ACCURACY_ENABLED':
throw PreciseAccuracyEnabledException(exception.message);
case 'APPROXIMATE_LOCATION_NOT_SUPPORTED':

diff:
@@ -194,35 +194,6 @@ void main() {
),
);
});
- test(
- 'Should receive an exception when the location accuracy definition'
- ' in the Info.plist is missing', () async {
- MethodChannelMock(
- channelName: 'flutter.baseflow.com/geolocator',
- method: 'requestTemporaryFullAccuracy',
- result: PlatformException(
- code: 'ACCURACY_DICTIONARY_NOT_FOUND',
- message: 'Accuracy definition missing.',
- details: null,
- ),
- );
-
- // Act
- final accuracyFuture =
- MethodChannelGeolocator().requestTemporaryFullAccuracy();
-
- // Assert
- expect(
- accuracyFuture,
- throwsA(
- isA<AccuracyDictionaryNotFoundException>().having(
- (e) => e.toString(),
- 'description',
- 'Accuracy definition missing.',
- ),
- ),
- );
- });
test('Should receive an exception when precise location is enabled',
() async {
MethodChannelMock(
@@ -279,36 +250,6 @@ void main() {
),
);
});
- test(
- 'Should receive an exception when the location accuracy definition'
- ' in the Info.plist is missing', () async {
- MethodChannelMock(
- channelName: 'flutter.baseflow.com/geolocator',
- method: 'requestTemporaryFullAccuracy',
- result: PlatformException(
- code: 'ACCURACY_DICTIONARY_NOT_FOUND',
- message: null,
- details: null,
- ),
- );
-
- // Act
- final accuracyFuture =
- MethodChannelGeolocator().requestTemporaryFullAccuracy();
-
- // Assert
- expect(
- accuracyFuture,
- throwsA(
- isA<AccuracyDictionaryNotFoundException>().having(
- (e) => e.toString(),
- '',
- 'Temporary Full accuracy key or description: '
- 'NSLocationTemporaryUsageDescriptionDictionary'
- ' is missing in the Info.plist dictionary.'),
- ),
- );
- });
});
group('getLocationAccuracy: When requesting the Location Accuracy Status',


message: Changed the CHANGELOG and the pubspec.yaml, and added an enum value for android to the LocationAccuracyStatus enum

diff:
+## 2.2.1
+
+- Documentation `getLocationAccuracy()` method clarified
+- On Android devices, `getLocationAccuracy()` now returns a LocationAccuracyStatus.unknown value
+
## 2.2.0
- Added the possibility to query for the LocationAccuracyStatus on devices running iOS 14.0 and higher.

diff:
@@ -5,4 +5,9 @@ enum LocationAccuracyStatus {
/// The precise location of the device will be returned.
precise,
+
+ /// When an Android device is used, an 'unknown' status is returned, since
+ /// Android does not support Approximate Location yet.
+ unknown,
+
}

diff:
@@ -159,12 +159,14 @@ abstract class GeolocatorPlatform extends PlatformInterface {
throw UnimplementedError('getPositionStream() has not been implemented.');
}
- /// Returns a [Future] containing a [LocationAccuracyStatus].
+ /// Returns a [Future] containing a [LocationAccuracyStatus] (iOS only).
///
/// When on iOS the user has given permission for approximate location,
/// [LocationAccuracyStatus.reduced] will be returned, if the user gave
/// permission for precise/full accuracy location, [LocationAccuracyStatus.precise]
/// will be returned.
+ /// When executing the method on Android device's,
+ /// [LocationAccuracyStatus.unknown] will be returned.
Future<LocationAccuracyStatus> getLocationAccuracy() async {
throw UnimplementedError('getLocationAccuracy() has not been implemented.');
}

diff:
import 'dart:async';
+import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import '../../geolocator_platform_interface.dart';
@@ -92,6 +93,9 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
@override
Future<LocationAccuracyStatus> getLocationAccuracy() async {
+ if (defaultTargetPlatform == TargetPlatform.iOS) {
+ return LocationAccuracyStatus.unknown;
+ }
final int accuracy =
await _methodChannel.invokeMethod('getLocationAccuracy');
return LocationAccuracyStatus.values[accuracy];

diff:
@@ -3,7 +3,7 @@ description: A common platform interface for the geolocator plugin.
homepage: https://github.com/baseflow/flutter-geolocator
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
-version: 2.2.0
+version: 2.2.1
dependencies:
flutter:

diff:
@@ -136,8 +136,7 @@ void main() {
group('getLocationAccuracy: When requesting the Location Accuracy Status',
() {
- test(
- 'Should receive reduced accuracy if Location Accuracy is reduced',
+ test('Should receive reduced accuracy if Location Accuracy is reduced',
() async {
// Arrange
MethodChannelMock(
@@ -154,8 +153,7 @@ void main() {
expect(locationAccuracy, LocationAccuracyStatus.reduced);
});
- test(
- 'Should receive reduced accuracy if Location Accuracy is reduced',
+ test('Should receive reduced accuracy if Location Accuracy is reduced',
() async {
// Arrange
MethodChannelMock(
@@ -172,6 +170,22 @@ void main() {
expect(locationAccuracy, LocationAccuracyStatus.precise);
});
+ test('Should receive reduced accuracy if Location Accuracy is reduced',
+ () async {
+ // Arrange
+ MethodChannelMock(
+ channelName: 'flutter.baseflow.com/geolocator',
+ method: 'getLocationAccuracy',
+ result: 2,
+ );
+
+ // Act
+ final locationAccuracy =
+ await MethodChannelGeolocator().getLocationAccuracy();
+
+ // Assert
+ expect(locationAccuracy, LocationAccuracyStatus.unknown);
+ });
});
group('requestPermission: When requesting for permission', () {


message: Processed requested changes

diff:
## 2.2.1
-- Documentation `getLocationAccuracy()` method clarified
-- On Android devices, `getLocationAccuracy()` now returns a LocationAccuracyStatus.unknown value
+- Documentation `getLocationAccuracy()` method clarified.
+- Extended the `LocationAccuracyStatus` enum with a `LocationAccuracyStatus.unknown` value, which can be used by platforms that don't support location accuracy features.
## 2.2.0

diff:
@@ -165,8 +165,8 @@ abstract class GeolocatorPlatform extends PlatformInterface {
/// [LocationAccuracyStatus.reduced] will be returned, if the user gave
/// permission for precise/full accuracy location, [LocationAccuracyStatus.precise]
/// will be returned.
- /// When executing the method on Android device's,
- /// [LocationAccuracyStatus.unknown] will be returned.
+ /// When executing the method on platforms that don't support location
+ /// accuracy features [LocationAccuracyStatus.unknown] should be returned.
Future<LocationAccuracyStatus> getLocationAccuracy() async {
throw UnimplementedError('getLocationAccuracy() has not been implemented.');
}

diff:
@@ -93,9 +93,6 @@ class MethodChannelGeolocator extends GeolocatorPlatform {
@override
Future<LocationAccuracyStatus> getLocationAccuracy() async {
- if (defaultTargetPlatform == TargetPlatform.iOS) {
- return LocationAccuracyStatus.unknown;
- }
final int accuracy =
await _methodChannel.invokeMethod('getLocationAccuracy');
return LocationAccuracyStatus.values[accuracy];

diff:
@@ -153,7 +153,7 @@ void main() {
expect(locationAccuracy, LocationAccuracyStatus.reduced);
});
- test('Should receive reduced accuracy if Location Accuracy is reduced',
+ test('Should receive reduced accuracy if Location Accuracy is precise',
() async {
// Arrange
MethodChannelMock(
@@ -169,23 +169,6 @@ void main() {
// Assert
expect(locationAccuracy, LocationAccuracyStatus.precise);
});
-
- test('Should receive reduced accuracy if Location Accuracy is reduced',
- () async {
- // Arrange
- MethodChannelMock(
- channelName: 'flutter.baseflow.com/geolocator',
- method: 'getLocationAccuracy',
- result: 2,
- );
-
- // Act
- final locationAccuracy =
- await MethodChannelGeolocator().getLocationAccuracy();
-
- // Assert
- expect(locationAccuracy, LocationAccuracyStatus.unknown);
- });
});
group('requestPermission: When requesting for permission', () {

original_message: Processed requested changes