From f3a8e52d1decb07bdd3d17f6e8ffea44f0b8f7f7 Mon Sep 17 00:00:00 2001 From: Jeroen Weener Date: Thu, 9 Mar 2023 17:33:58 +0100 Subject: [PATCH 1/2] Revert "Merge pull request #35 from Baseflow/revert-34-enhancement/platform-interface" This reverts commit 101bf12cadd4d2d63bb7f64809a6f3998deff6fc, reversing changes made to d828355dce0279749bf2295c4fa369bdcf0be035. --- CONTRIBUTING.md | 4 +- google_api_availability/example/pubspec.yaml | 7 +- .../CHANGELOG.md | 3 + .../LICENSE | 21 +++ .../README.md | 42 ++++++ .../analysis_options.yaml | 10 ++ ...e_api_availability_platform_interface.dart | 4 + ...e_api_availability_platform_interface.dart | 95 ++++++++++++ .../google_play_services_availability.dart | 78 ++++++++++ .../pubspec.yaml | 22 +++ ..._availability_platform_interface_test.dart | 140 ++++++++++++++++++ ...oogle_play_services_availability_test.dart | 29 ++++ 12 files changed, 450 insertions(+), 5 deletions(-) create mode 100644 google_api_availability_platform_interface/CHANGELOG.md create mode 100644 google_api_availability_platform_interface/LICENSE create mode 100644 google_api_availability_platform_interface/README.md create mode 100644 google_api_availability_platform_interface/analysis_options.yaml create mode 100644 google_api_availability_platform_interface/lib/google_api_availability_platform_interface.dart create mode 100644 google_api_availability_platform_interface/lib/src/google_api_availability_platform_interface.dart create mode 100644 google_api_availability_platform_interface/lib/src/models/google_play_services_availability.dart create mode 100644 google_api_availability_platform_interface/pubspec.yaml create mode 100644 google_api_availability_platform_interface/test/google_api_availability_platform_interface_test.dart create mode 100644 google_api_availability_platform_interface/test/google_play_services_availability_test.dart diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6ca1db7..36ca0a0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,8 +36,8 @@ We really appreciate contributions via GitHub pull requests. To contribute take * `git checkout upstream/develop -b ` * Apply your changes * Verify your changes and fix potential warnings/ errors: - * Check formatting: `flutter format .` - * Run static analyses: `flutter analyzes` + * Check formatting: `dart format .` + * Run static analyses: `flutter analyze` * Run unit-tests: `flutter test` * Commit your changes: `git commit -am ""` * Push changes to your fork: `git push origin ` diff --git a/google_api_availability/example/pubspec.yaml b/google_api_availability/example/pubspec.yaml index 4435167..7a444bf 100644 --- a/google_api_availability/example/pubspec.yaml +++ b/google_api_availability/example/pubspec.yaml @@ -1,6 +1,7 @@ name: google_api_availability_example description: Demonstrates how to use the google_api_availability plugin. version: 1.0.0+1 +publish_to: none environment: sdk: ">=2.15.0 <3.0.0" @@ -9,11 +10,11 @@ dependencies: flutter: sdk: flutter cupertino_icons: ^0.1.2 - -dev_dependencies: google_api_availability: path: ../ + +dev_dependencies: flutter_lints: 1.0.4 flutter: - uses-material-design: true \ No newline at end of file + uses-material-design: true diff --git a/google_api_availability_platform_interface/CHANGELOG.md b/google_api_availability_platform_interface/CHANGELOG.md new file mode 100644 index 0000000..18399a9 --- /dev/null +++ b/google_api_availability_platform_interface/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +* Extracts the common platform interface from the google_api_availability package. diff --git a/google_api_availability_platform_interface/LICENSE b/google_api_availability_platform_interface/LICENSE new file mode 100644 index 0000000..b0b0b52 --- /dev/null +++ b/google_api_availability_platform_interface/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Baseflow + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/google_api_availability_platform_interface/README.md b/google_api_availability_platform_interface/README.md new file mode 100644 index 0000000..744dfdb --- /dev/null +++ b/google_api_availability_platform_interface/README.md @@ -0,0 +1,42 @@ +# google_api_availability_platform_interface + +[![style: flutter_lints](https://img.shields.io/badge/style-flutter_lints-40c4ff.svg)](https://pub.dev/packages/flutter_lints) + +A common platform interface for the [`google_api_availability`][1] plugin. + +This interface allows platform-specific implementations of the `google_api_availability` +plugin, as well as the plugin itself, to ensure they are supporting the +same interface. Have a look at the [Federated plugins](https://flutter.dev/docs/development/packages-and-plugins/developing-packages#federated-plugins) +section of the official [Developing packages & plugins](https://flutter.dev/docs/development/packages-and-plugins/developing-packages) +documentation for more information regarding the federated architecture concept. + +## Usage + +To implement a new platform-specific implementation of `google_api_availability`, extend +[`GoogleApiAvailabilityPlatform`][2] with an implementation that performs the +platform-specific behavior, and when you register your plugin, set the default +`GoogleApiAvailabilityPlatform` by calling +`GoogleApiAvailabilityPlatform.instance = MyGoogleApiAvailabilityPlatform()`. + +## Note on breaking changes + +Strongly prefer non-breaking changes (such as adding a method to the interface) +over breaking changes for this package. + +See https://flutter.dev/go/platform-interface-breaking-changes for a discussion +on why a less-clean interface is preferable to a breaking change. + +## Issues + +Please file any issues, bugs or feature requests as an issue on our [GitHub](https://github.com/Baseflow/flutter-google-api-availability/issues) page. Commercial support is available, you can contact us at . + +## Want to contribute + +If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Baseflow/flutter-google-api-availability/pulls). + +## Author + +This Google API Availability plugin for Flutter is developed by [Baseflow](https://baseflow.com). + +[1]: ../google_api_availability +[2]: lib/google_api_availability_platform_interface.dart diff --git a/google_api_availability_platform_interface/analysis_options.yaml b/google_api_availability_platform_interface/analysis_options.yaml new file mode 100644 index 0000000..fbe6296 --- /dev/null +++ b/google_api_availability_platform_interface/analysis_options.yaml @@ -0,0 +1,10 @@ +include: package:flutter_lints/flutter.yaml + +analyzer: + exclude: + # Ignore generated files + - '**/*.g.dart' + - 'lib/src/generated/*.dart' +linter: + rules: + - public_member_api_docs diff --git a/google_api_availability_platform_interface/lib/google_api_availability_platform_interface.dart b/google_api_availability_platform_interface/lib/google_api_availability_platform_interface.dart new file mode 100644 index 0000000..381c2d9 --- /dev/null +++ b/google_api_availability_platform_interface/lib/google_api_availability_platform_interface.dart @@ -0,0 +1,4 @@ +library google_api_availability_platform_interface; + +export 'src/google_api_availability_platform_interface.dart'; +export 'src/models/google_play_services_availability.dart'; diff --git a/google_api_availability_platform_interface/lib/src/google_api_availability_platform_interface.dart b/google_api_availability_platform_interface/lib/src/google_api_availability_platform_interface.dart new file mode 100644 index 0000000..030151e --- /dev/null +++ b/google_api_availability_platform_interface/lib/src/google_api_availability_platform_interface.dart @@ -0,0 +1,95 @@ +import 'package:google_api_availability_platform_interface/google_api_availability_platform_interface.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +/// The interface that implementations of `google_api_availability` must implement. +/// +/// Platform implementations should extend this class rather than implement it +/// as `google_api_availability` does not consider newly added methods to be +/// breaking changes. Extending this class (using `extends`) ensures that the +/// subclass will get the default implementation, while platform implementations +/// that `implements` this interface will be broken by newly added +/// [GoogleApiAvailabilityPlatform] methods. +abstract class GoogleApiAvailabilityPlatform extends PlatformInterface { + /// Constructs a [GoogleApiAvailabilityPlatform]. + GoogleApiAvailabilityPlatform() : super(token: _token); + + static final Object _token = Object(); + + static GoogleApiAvailabilityPlatform? _instance; + + /// The default instance of [GoogleApiAvailabilityPlatform] to use. + static GoogleApiAvailabilityPlatform? get instance => _instance; + + /// Platform-specific plugins should set this with their own platform-specific + /// class that extends [GoogleApiAvailabilityPlatform] when they register + /// themselves. + static set instance(GoogleApiAvailabilityPlatform? instance) { + if (instance == null) { + throw AssertionError( + 'Platform interfaces can only be set to a non-null instance'); + } + + PlatformInterface.verify(instance, _token); + _instance = instance; + } + + /// Returns the connection status of Google Play Service. + /// + /// Optionally, you can also show an error dialog if the connection status is + /// not [GooglePlayServicesAvailability.success]. + Future checkGooglePlayServicesAvailability([ + bool showDialogIfNecessary = false, + ]) { + throw UnimplementedError( + 'checkGooglePlayServicesAvailability() has not been implemented.', + ); + } + + /// Attempts to make Google Play Services available on this device. + /// + /// Shows a dialog if the error is resolvable by user. + /// If the `Future` completes without throwing an exception, Play Services + /// is available on this device. + Future makeGooglePlayServicesAvailable() { + throw UnimplementedError( + 'makeGooglePlayServicesAvailable() has not been implemented.', + ); + } + + /// Returns a human-readable string of the error code. + Future getErrorString() { + throw UnimplementedError( + 'getErrorString() has not been implemented.', + ); + } + + /// Determines whether an error can be resolved via user action. + Future isUserResolvable() { + throw UnimplementedError( + 'isUserResolvable() has not been implemented.', + ); + } + + /// Displays a notification for an error code, if it is resolvable by the user. + /// + /// This method is similar to [showErrorDialogFragment], but is provided for + /// background tasks that cannot or should not display dialogs. + Future showErrorNotification() { + throw UnimplementedError( + 'showErrorNotification() has not been implemented.', + ); + } + + /// Display an error dialog according to the [ErrorCode] if the connection + /// status is not [GooglePlayServicesAvailability.success]. + /// + /// Returns true if the connection status did not equal + /// [GooglePlayServicesAvailability.success] or any other + /// non-[ConnectionResult] value. + /// Returns false otherwise. + Future showErrorDialogFragment() { + throw UnimplementedError( + 'showErrorDialogFragment() has not been implemented.', + ); + } +} diff --git a/google_api_availability_platform_interface/lib/src/models/google_play_services_availability.dart b/google_api_availability_platform_interface/lib/src/models/google_play_services_availability.dart new file mode 100644 index 0000000..2d058c0 --- /dev/null +++ b/google_api_availability_platform_interface/lib/src/models/google_play_services_availability.dart @@ -0,0 +1,78 @@ +import 'package:meta/meta.dart'; + +/// Indicates possible states of the Google Api Services availability. +class GooglePlayServicesAvailability { + const GooglePlayServicesAvailability._(this.value); + + /// Returns the value of the status as a string of the given status integer + factory GooglePlayServicesAvailability.byValue(int value) => values[value]; + + /// Creates an instance of the [GooglePlayServicesAvailability] class. This + /// constructor is exposed for testing purposes only and should not be used + /// by clients of the plugin as it may break or change at any time. + @visibleForTesting + const GooglePlayServicesAvailability.private(this.value); + + /// Represents the integer value of the Google Api Services availability + /// state. + final int value; + + /// Google Play services are installed on the device and ready to be used. + static const GooglePlayServicesAvailability success = + GooglePlayServicesAvailability._(0); + + /// Google Play services is missing on this device. + static const GooglePlayServicesAvailability serviceMissing = + GooglePlayServicesAvailability._(1); + + /// Google Play service is currently being updated on this device. + static const GooglePlayServicesAvailability serviceUpdating = + GooglePlayServicesAvailability._(2); + + /// The installed version of Google Play services is out of date. + static const GooglePlayServicesAvailability serviceVersionUpdateRequired = + GooglePlayServicesAvailability._(3); + + /// The installed version of Google Play services has been disabled on this device. + static const GooglePlayServicesAvailability serviceDisabled = + GooglePlayServicesAvailability._(4); + + /// The version of the Google Play services installed on this device is not authentic. + static const GooglePlayServicesAvailability serviceInvalid = + GooglePlayServicesAvailability._(5); + + /// Google Play services are not available on this platform. + static const GooglePlayServicesAvailability notAvailableOnPlatform = + GooglePlayServicesAvailability._(6); + + /// Unable to determine if Google Play services are installed. + static const GooglePlayServicesAvailability unknown = + GooglePlayServicesAvailability._(7); + + /// Returns a list with all possible Google Api Availability states. + static const List values = + [ + success, + serviceMissing, + serviceUpdating, + serviceVersionUpdateRequired, + serviceDisabled, + serviceInvalid, + notAvailableOnPlatform, + unknown, + ]; + + static const List _names = [ + 'success', + 'serviceMissing', + 'serviceUpdating', + 'serviceVersionUpdateRequired', + 'serviceDisabled', + 'serviceInvalid', + 'notAvailableOnPlatform', + 'unknown', + ]; + + @override + String toString() => 'GooglePlayServicesAvailability.${_names[value]}'; +} diff --git a/google_api_availability_platform_interface/pubspec.yaml b/google_api_availability_platform_interface/pubspec.yaml new file mode 100644 index 0000000..dd770af --- /dev/null +++ b/google_api_availability_platform_interface/pubspec.yaml @@ -0,0 +1,22 @@ +name: google_api_availability_platform_interface +description: A common platform interface for the google_api_availability plugin. +repository: https://github.com/baseflow/flutter-google-api-availability/tree/main/google_api_availability_platform_interface +# 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: 1.0.0 + +dependencies: + flutter: + sdk: flutter + plugin_platform_interface: ^2.1.4 + meta: ^1.8.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.1 + mockito: ^5.3.2 + +environment: + sdk: ">=2.15.0 <3.0.0" + flutter: ">=2.8.0" diff --git a/google_api_availability_platform_interface/test/google_api_availability_platform_interface_test.dart b/google_api_availability_platform_interface/test/google_api_availability_platform_interface_test.dart new file mode 100644 index 0000000..e62cb3e --- /dev/null +++ b/google_api_availability_platform_interface/test/google_api_availability_platform_interface_test.dart @@ -0,0 +1,140 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:google_api_availability_platform_interface/google_api_availability_platform_interface.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; +import 'package:mockito/mockito.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('$GoogleApiAvailabilityPlatform', () { + test('The default instance is null', () { + expect(GoogleApiAvailabilityPlatform.instance, isNull); + }); + + test('Cannot be implemented with `implements`', () { + expect(() { + GoogleApiAvailabilityPlatform.instance = + ImplementsGoogleApiAvailabilityPlatform(); + // In versions of `package:plugin_platform_interface` prior to fixing + // https://github.com/flutter/flutter/issues/109339, an attempt to + // implement a platform interface using `implements` would sometimes + // throw a `NoSuchMethodError` and other times throw an + // `AssertionError`. After the issue is fixed, an `AssertionError` will + // always be thrown. For the purpose of this test, we don't really care + // what exception is thrown, so just allow any exception. + }, throwsA(anything)); + }); + + test('Can be extended', () { + GoogleApiAvailabilityPlatform.instance = + ExtendsGoogleApiAvailabilityPlatform(); + }); + + test('Can be mocked with `implements`', () { + final mock = MockGoogleApiAvailabilityPlatform(); + GoogleApiAvailabilityPlatform.instance = mock; + }); + + test( + 'Default implementation of checkGooglePlayServicesAvailability should throw unimplemented error', + () { + // Arrange + final googleApiAvailabilityPlatform = + ExtendsGoogleApiAvailabilityPlatform(); + + // Act & Assert + expect( + () => + googleApiAvailabilityPlatform.checkGooglePlayServicesAvailability(), + throwsUnimplementedError, + ); + }); + + test( + 'Default implementation of makeGooglePlayServicesAvailable should throw unimplemented error', + () { + // Arrange + final googleApiAvailabilityPlatform = + ExtendsGoogleApiAvailabilityPlatform(); + + // Act & Assert + expect( + () => googleApiAvailabilityPlatform.makeGooglePlayServicesAvailable(), + throwsUnimplementedError, + ); + }); + + test( + 'Default implementation of getErrorString should throw unimplemented error', + () { + // Arrange + final googleApiAvailabilityPlatform = + ExtendsGoogleApiAvailabilityPlatform(); + + // Act & Assert + expect( + () => googleApiAvailabilityPlatform.getErrorString(), + throwsUnimplementedError, + ); + }); + + test( + 'Default implementation of isUserResolvable should throw unimplemented error', + () { + // Arrange + final googleApiAvailabilityPlatform = + ExtendsGoogleApiAvailabilityPlatform(); + + // Act & Assert + expect( + () => googleApiAvailabilityPlatform.isUserResolvable(), + throwsUnimplementedError, + ); + }); + + test( + 'Default implementation of showErrorNotification should throw unimplemented error', + () { + // Arrange + final googleApiAvailabilityPlatform = + ExtendsGoogleApiAvailabilityPlatform(); + + // Act & Assert + expect( + () => googleApiAvailabilityPlatform.showErrorNotification(), + throwsUnimplementedError, + ); + }); + + test( + 'Default implementation of showErrorDialogFragment should throw unimplemented error', + () { + // Arrange + final googleApiAvailabilityPlatform = + ExtendsGoogleApiAvailabilityPlatform(); + + // Act & Assert + expect( + () => googleApiAvailabilityPlatform.showErrorDialogFragment(), + throwsUnimplementedError, + ); + }); + }); +} + +class ImplementsGoogleApiAvailabilityPlatform + implements GoogleApiAvailabilityPlatform { + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +class MockGoogleApiAvailabilityPlatform extends Mock + with MockPlatformInterfaceMixin + implements GoogleApiAvailabilityPlatform {} + +class ExtendsGoogleApiAvailabilityPlatform + extends GoogleApiAvailabilityPlatform {} diff --git a/google_api_availability_platform_interface/test/google_play_services_availability_test.dart b/google_api_availability_platform_interface/test/google_play_services_availability_test.dart new file mode 100644 index 0000000..daf0f99 --- /dev/null +++ b/google_api_availability_platform_interface/test/google_play_services_availability_test.dart @@ -0,0 +1,29 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:google_api_availability_platform_interface/google_api_availability_platform_interface.dart'; + +void main() { + group('$GooglePlayServicesAvailability', () { + test('has the right amount of availability states', () { + const values = GooglePlayServicesAvailability.values; + + expect(values.length, 8); + }); + + test('check if corresponding status gets received when calling constructor', + () { + const values = GooglePlayServicesAvailability.values; + + for (var i = 0; i < values.length; i++) { + expect(values[i], GooglePlayServicesAvailability.byValue(i)); + } + }); + + test('check if toString method returns the corresponding name', () { + var playServicesAvailability = + const GooglePlayServicesAvailability.private(0); + + expect(playServicesAvailability.toString(), + 'GooglePlayServicesAvailability.success'); + }); + }); +} From 959400c5b506617457aa82c6ab368ca16155b358 Mon Sep 17 00:00:00 2001 From: Jeroen Weener Date: 2023年3月14日 12:15:08 +0100 Subject: [PATCH 2/2] Adds method to remove platform instance --- google_api_availability_platform_interface/CHANGELOG.md | 4 ++++ .../src/google_api_availability_platform_interface.dart | 8 ++++++++ google_api_availability_platform_interface/pubspec.yaml | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/google_api_availability_platform_interface/CHANGELOG.md b/google_api_availability_platform_interface/CHANGELOG.md index 18399a9..e598763 100644 --- a/google_api_availability_platform_interface/CHANGELOG.md +++ b/google_api_availability_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.1 + +* Adds `removeInstance` to `GoogleApiAvailabilityPlatform` for testing purposes. + ## 1.0.0 * Extracts the common platform interface from the google_api_availability package. diff --git a/google_api_availability_platform_interface/lib/src/google_api_availability_platform_interface.dart b/google_api_availability_platform_interface/lib/src/google_api_availability_platform_interface.dart index 030151e..a53ddc5 100644 --- a/google_api_availability_platform_interface/lib/src/google_api_availability_platform_interface.dart +++ b/google_api_availability_platform_interface/lib/src/google_api_availability_platform_interface.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:google_api_availability_platform_interface/google_api_availability_platform_interface.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; @@ -33,6 +34,13 @@ abstract class GoogleApiAvailabilityPlatform extends PlatformInterface { _instance = instance; } + /// Removes the registered instance of the [GoogleApiAvailabilityPlatform] class. + /// + /// This method is exposed for testing purposes only and should not be used by + /// clients of the plugin. + @visibleForTesting + static removeInstance() => _instance = null; + /// Returns the connection status of Google Play Service. /// /// Optionally, you can also show an error dialog if the connection status is diff --git a/google_api_availability_platform_interface/pubspec.yaml b/google_api_availability_platform_interface/pubspec.yaml index dd770af..b2f2e3a 100644 --- a/google_api_availability_platform_interface/pubspec.yaml +++ b/google_api_availability_platform_interface/pubspec.yaml @@ -3,7 +3,7 @@ description: A common platform interface for the google_api_availability plugin. repository: https://github.com/baseflow/flutter-google-api-availability/tree/main/google_api_availability_platform_interface # 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: 1.0.0 +version: 1.0.1 dependencies: flutter:

AltStyle によって変換されたページ (->オリジナル) /