[connectivity_platform_interface] Move here as much code as possible from the core package (#2526)
* Bring ConnectivityResult and LocationAuthorizationStatus enums from
core package.
* Use the above Enums as return values for ConnectivityPlatformInterface
methods.
* Modify the MethodChannel implementation so it returns the right types.
* Bring utility methods, asserts and other logic that is only needed on
the MethodChannel implementation from the core package, so it's simpler.
* Bring MethodChannel unit tests from core package.
Co-authored-by: David Iglesias <ditman@gmail.com>
diff --git a/packages/connectivity/connectivity_platform_interface/CHANGELOG.md b/packages/connectivity/connectivity_platform_interface/CHANGELOG.md
index 8e4cc49..eb60d86 100644
--- a/packages/connectivity/connectivity_platform_interface/CHANGELOG.md
+++ b/packages/connectivity/connectivity_platform_interface/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 1.0.2
+
+* Bring ConnectivityResult and LocationAuthorizationStatus enums from the core package.
+* Use the above Enums as return values for ConnectivityPlatformInterface methods.
+* Modify the MethodChannel implementation so it returns the right types.
+* Bring all utility methods, asserts and other logic that is only needed on the MethodChannel implementation from the core package.
+* Bring MethodChannel unit tests from core package.
+
## 1.0.1
* Fix README.md link.
diff --git a/packages/connectivity/connectivity_platform_interface/lib/connectivity_platform_interface.dart b/packages/connectivity/connectivity_platform_interface/lib/connectivity_platform_interface.dart
index 30884bb..cfd9cf6 100644
--- a/packages/connectivity/connectivity_platform_interface/lib/connectivity_platform_interface.dart
+++ b/packages/connectivity/connectivity_platform_interface/lib/connectivity_platform_interface.dart
@@ -6,7 +6,10 @@
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
-import 'method_channel_connectivity.dart';
+import 'src/enums.dart';
+import 'src/method_channel_connectivity.dart';
+
+export 'src/enums.dart';
/// The interface that implementations of connectivity must implement.
///
@@ -36,10 +39,16 @@
}
/// Checks the connection status of the device.
- Future<String> checkConnectivity() {
+ Future<ConnectivityResult> checkConnectivity() {
throw UnimplementedError('checkConnectivity() has not been implemented.');
}
+ /// Returns a Stream of ConnectivityResults changes.
+ Stream<ConnectivityResult> get onConnectivityChanged {
+ throw UnimplementedError(
+ 'get onConnectivityChanged has not been implemented.');
+ }
+
/// Obtains the wifi name (SSID) of the connected network
Future<String> getWifiName() {
throw UnimplementedError('getWifiName() has not been implemented.');
@@ -56,14 +65,14 @@
}
/// Request to authorize the location service (Only on iOS).
- Future<String> requestLocationServiceAuthorization(
+ Future<LocationAuthorizationStatus> requestLocationServiceAuthorization(
{bool requestAlwaysLocationUsage = false}) {
throw UnimplementedError(
'requestLocationServiceAuthorization() has not been implemented.');
}
/// Get the current location service authorization (Only on iOS).
- Future<String> getLocationServiceAuthorization() {
+ Future<LocationAuthorizationStatus> getLocationServiceAuthorization() {
throw UnimplementedError(
'getLocationServiceAuthorization() has not been implemented.');
}
diff --git a/packages/connectivity/connectivity_platform_interface/lib/method_channel_connectivity.dart b/packages/connectivity/connectivity_platform_interface/lib/method_channel_connectivity.dart
deleted file mode 100644
index 0d35b02..0000000
--- a/packages/connectivity/connectivity_platform_interface/lib/method_channel_connectivity.dart
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2020 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 'dart:async';
-
-import 'package:flutter/services.dart';
-import 'package:meta/meta.dart';
-
-import 'connectivity_platform_interface.dart';
-
-/// The method channel used to interact with the native platform.
-@visibleForTesting
-const MethodChannel method_channel =
- MethodChannel('plugins.flutter.io/connectivity');
-
-/// An implementation of [ConnectivityPlatform] that uses method channels.
-class MethodChannelConnectivity extends ConnectivityPlatform {
- @override
- Future<String> checkConnectivity() async {
- final String result = await method_channel.invokeMethod<String>('check');
- return result;
- }
-
- @override
- Future<String> getWifiName() async {
- return method_channel.invokeMethod<String>('wifiName');
- }
-
- @override
- Future<String> getWifiBSSID() async {
- return await method_channel.invokeMethod<String>('wifiBSSID');
- }
-
- @override
- Future<String> getWifiIP() async {
- return await method_channel.invokeMethod<String>('wifiIPAddress');
- }
-
- @override
- Future<String> requestLocationServiceAuthorization(
- {bool requestAlwaysLocationUsage = false}) async {
- final String result = await method_channel.invokeMethod<String>(
- 'requestLocationServiceAuthorization',
- <bool>[requestAlwaysLocationUsage]);
- return result;
- }
-
- @override
- Future<String> getLocationServiceAuthorization() async {
- final String result = await method_channel
- .invokeMethod<String>('getLocationServiceAuthorization');
- return result;
- }
-}
diff --git a/packages/connectivity/connectivity_platform_interface/lib/src/enums.dart b/packages/connectivity/connectivity_platform_interface/lib/src/enums.dart
new file mode 100644
index 0000000..9d8cef9
--- /dev/null
+++ b/packages/connectivity/connectivity_platform_interface/lib/src/enums.dart
@@ -0,0 +1,32 @@
+/// Connection status check result.
+enum ConnectivityResult {
+ /// WiFi: Device connected via Wi-Fi
+ wifi,
+
+ /// Mobile: Device connected to cellular network
+ mobile,
+
+ /// None: Device not connected to any network
+ none
+}
+
+/// The status of the location service authorization.
+enum LocationAuthorizationStatus {
+ /// The authorization of the location service is not determined.
+ notDetermined,
+
+ /// This app is not authorized to use location.
+ restricted,
+
+ /// User explicitly denied the location service.
+ denied,
+
+ /// User authorized the app to access the location at any time.
+ authorizedAlways,
+
+ /// User authorized the app to access the location when the app is visible to them.
+ authorizedWhenInUse,
+
+ /// Status unknown.
+ unknown
+}
diff --git a/packages/connectivity/connectivity_platform_interface/lib/src/method_channel_connectivity.dart b/packages/connectivity/connectivity_platform_interface/lib/src/method_channel_connectivity.dart
new file mode 100644
index 0000000..7a64115
--- /dev/null
+++ b/packages/connectivity/connectivity_platform_interface/lib/src/method_channel_connectivity.dart
@@ -0,0 +1,88 @@
+// Copyright 2020 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 'dart:async';
+import 'dart:io' show Platform;
+
+import 'package:connectivity_platform_interface/connectivity_platform_interface.dart';
+import 'package:flutter/services.dart';
+import 'package:meta/meta.dart';
+
+import 'utils.dart';
+
+/// An implementation of [ConnectivityPlatform] that uses method channels.
+class MethodChannelConnectivity extends ConnectivityPlatform {
+ /// The method channel used to interact with the native platform.
+ @visibleForTesting
+ MethodChannel methodChannel =
+ MethodChannel('plugins.flutter.io/connectivity');
+
+ /// The event channel used to receive ConnectivityResult changes from the native platform.
+ @visibleForTesting
+ EventChannel eventChannel =
+ EventChannel('plugins.flutter.io/connectivity_status');
+
+ Stream<ConnectivityResult> _onConnectivityChanged;
+
+ /// Fires whenever the connectivity state changes.
+ Stream<ConnectivityResult> get onConnectivityChanged {
+ if (_onConnectivityChanged == null) {
+ _onConnectivityChanged = eventChannel
+ .receiveBroadcastStream()
+ .map((dynamic result) => result.toString())
+ .map(parseConnectivityResult);
+ }
+ return _onConnectivityChanged;
+ }
+
+ @override
+ Future<ConnectivityResult> checkConnectivity() {
+ return methodChannel
+ .invokeMethod<String>('check')
+ .then(parseConnectivityResult);
+ }
+
+ @override
+ Future<String> getWifiName() async {
+ String wifiName = await methodChannel.invokeMethod<String>('wifiName');
+ // as Android might return <unknown ssid>, uniforming result
+ // our iOS implementation will return null
+ if (wifiName == '<unknown ssid>') {
+ wifiName = null;
+ }
+ return wifiName;
+ }
+
+ @override
+ Future<String> getWifiBSSID() {
+ return methodChannel.invokeMethod<String>('wifiBSSID');
+ }
+
+ @override
+ Future<String> getWifiIP() {
+ return methodChannel.invokeMethod<String>('wifiIPAddress');
+ }
+
+ @override
+ Future<LocationAuthorizationStatus> requestLocationServiceAuthorization({
+ bool requestAlwaysLocationUsage = false,
+ }) {
+ // `assert(Platform.isIOS)` will prevent us from doing dart side unit testing.
+ // TODO: These should noop for non-Android, instead of throwing, so people don't need to rely on dart:io for this.
+ assert(!Platform.isAndroid);
+ return methodChannel.invokeMethod<String>(
+ 'requestLocationServiceAuthorization', <bool>[
+ requestAlwaysLocationUsage
+ ]).then(parseLocationAuthorizationStatus);
+ }
+
+ @override
+ Future<LocationAuthorizationStatus> getLocationServiceAuthorization() {
+ // `assert(Platform.isIOS)` will prevent us from doing dart side unit testing.
+ assert(!Platform.isAndroid);
+ return methodChannel
+ .invokeMethod<String>('getLocationServiceAuthorization')
+ .then(parseLocationAuthorizationStatus);
+ }
+}
diff --git a/packages/connectivity/connectivity_platform_interface/lib/src/utils.dart b/packages/connectivity/connectivity_platform_interface/lib/src/utils.dart
new file mode 100644
index 0000000..2ae22e1
--- /dev/null
+++ b/packages/connectivity/connectivity_platform_interface/lib/src/utils.dart
@@ -0,0 +1,32 @@
+import 'package:connectivity_platform_interface/connectivity_platform_interface.dart';
+
+/// Convert a String to a ConnectivityResult value.
+ConnectivityResult parseConnectivityResult(String state) {
+ switch (state) {
+ case 'wifi':
+ return ConnectivityResult.wifi;
+ case 'mobile':
+ return ConnectivityResult.mobile;
+ case 'none':
+ default:
+ return ConnectivityResult.none;
+ }
+}
+
+/// Convert a String to a LocationAuthorizationStatus value.
+LocationAuthorizationStatus parseLocationAuthorizationStatus(String result) {
+ switch (result) {
+ case 'notDetermined':
+ return LocationAuthorizationStatus.notDetermined;
+ case 'restricted':
+ return LocationAuthorizationStatus.restricted;
+ case 'denied':
+ return LocationAuthorizationStatus.denied;
+ case 'authorizedAlways':
+ return LocationAuthorizationStatus.authorizedAlways;
+ case 'authorizedWhenInUse':
+ return LocationAuthorizationStatus.authorizedWhenInUse;
+ default:
+ return LocationAuthorizationStatus.unknown;
+ }
+}
diff --git a/packages/connectivity/connectivity_platform_interface/pubspec.yaml b/packages/connectivity/connectivity_platform_interface/pubspec.yaml
index cccf14e..14fa04e 100644
--- a/packages/connectivity/connectivity_platform_interface/pubspec.yaml
+++ b/packages/connectivity/connectivity_platform_interface/pubspec.yaml
@@ -3,7 +3,7 @@
homepage: https://github.com/flutter/plugins/tree/master/packages/connectivity/connectivity_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.1
+version: 1.0.2
dependencies:
flutter:
@@ -14,7 +14,6 @@
dev_dependencies:
flutter_test:
sdk: flutter
- mockito: ^4.1.1
environment:
sdk: ">=2.0.0-dev.28.0 <3.0.0"
diff --git a/packages/connectivity/connectivity_platform_interface/test/method_channel_connectivity_test.dart b/packages/connectivity/connectivity_platform_interface/test/method_channel_connectivity_test.dart
index d8d9d5b..3d9c405 100644
--- a/packages/connectivity/connectivity_platform_interface/test/method_channel_connectivity_test.dart
+++ b/packages/connectivity/connectivity_platform_interface/test/method_channel_connectivity_test.dart
@@ -2,129 +2,152 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'package:mockito/mockito.dart';
+import 'package:connectivity_platform_interface/connectivity_platform_interface.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
-import 'package:plugin_platform_interface/plugin_platform_interface.dart';
-
-import 'package:connectivity_platform_interface/method_channel_connectivity.dart';
-import 'package:connectivity_platform_interface/connectivity_platform_interface.dart';
+import 'package:connectivity_platform_interface/src/method_channel_connectivity.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
- group('$ConnectivityPlatform', () {
- test('$MethodChannelConnectivity() is the default instance', () {
- expect(ConnectivityPlatform.instance,
- isInstanceOf<MethodChannelConnectivity>());
- });
-
- test('Cannot be implemented with `implements`', () {
- expect(() {
- ConnectivityPlatform.instance = ImplementsConnectivityPlatform();
- }, throwsA(isInstanceOf<AssertionError>()));
- });
-
- test('Can be mocked with `implements`', () {
- final ConnectivityPlatformMock mock = ConnectivityPlatformMock();
- ConnectivityPlatform.instance = mock;
- });
-
- test('Can be extended', () {
- ConnectivityPlatform.instance = ExtendsConnectivityPlatform();
- });
- });
-
group('$MethodChannelConnectivity', () {
- const MethodChannel channel =
- MethodChannel('plugins.flutter.io/connectivity');
final List<MethodCall> log = <MethodCall>[];
- channel.setMockMethodCallHandler((MethodCall methodCall) async {
- log.add(methodCall);
- });
+ MethodChannelConnectivity methodChannelConnectivity;
- final MethodChannelConnectivity connectivity = MethodChannelConnectivity();
+ setUp(() async {
+ methodChannelConnectivity = MethodChannelConnectivity();
- tearDown(() {
+ methodChannelConnectivity.methodChannel
+ .setMockMethodCallHandler((MethodCall methodCall) async {
+ log.add(methodCall);
+ switch (methodCall.method) {
+ case 'check':
+ return 'wifi';
+ case 'wifiName':
+ return '1337wifi';
+ case 'wifiBSSID':
+ return 'c0:ff:33:c0:d3:55';
+ case 'wifiIPAddress':
+ return '127.0.0.1';
+ case 'requestLocationServiceAuthorization':
+ return 'authorizedAlways';
+ case 'getLocationServiceAuthorization':
+ return 'authorizedAlways';
+ default:
+ return null;
+ }
+ });
log.clear();
+ MethodChannel(methodChannelConnectivity.eventChannel.name)
+ .setMockMethodCallHandler((MethodCall methodCall) async {
+ switch (methodCall.method) {
+ case 'listen':
+ await ServicesBinding.instance.defaultBinaryMessenger
+ .handlePlatformMessage(
+ methodChannelConnectivity.eventChannel.name,
+ methodChannelConnectivity.eventChannel.codec
+ .encodeSuccessEnvelope('wifi'),
+ (_) {},
+ );
+ break;
+ case 'cancel':
+ default:
+ return null;
+ }
+ });
});
- test('checkConnectivity', () async {
- await connectivity.checkConnectivity();
- expect(
- log,
- <Matcher>[isMethodCall('check', arguments: null)],
- );
+ test('onConnectivityChanged', () async {
+ final ConnectivityResult result =
+ await methodChannelConnectivity.onConnectivityChanged.first;
+ expect(result, ConnectivityResult.wifi);
});
test('getWifiName', () async {
- await connectivity.getWifiName();
- expect(
- log,
- <Matcher>[isMethodCall('wifiName', arguments: null)],
- );
- });
-
- test('getWifiBSSID', () async {
- await connectivity.getWifiBSSID();
- expect(
- log,
- <Matcher>[isMethodCall('wifiBSSID', arguments: null)],
- );
- });
-
- test('getWifiIP', () async {
- await connectivity.getWifiIP();
- expect(
- log,
- <Matcher>[isMethodCall('wifiIPAddress', arguments: null)],
- );
- });
-
- test(
- 'requestLocationServiceAuthorization requestLocationServiceAuthorization set to false (default)',
- () async {
- await connectivity.requestLocationServiceAuthorization();
+ final String result = await methodChannelConnectivity.getWifiName();
+ expect(result, '1337wifi');
expect(
log,
<Matcher>[
- isMethodCall('requestLocationServiceAuthorization',
- arguments: <bool>[false])
+ isMethodCall(
+ 'wifiName',
+ arguments: null,
+ ),
],
);
});
- test(
- 'requestLocationServiceAuthorization requestLocationServiceAuthorization set to true',
- () async {
- await connectivity.requestLocationServiceAuthorization(
- requestAlwaysLocationUsage: true);
+ test('getWifiBSSID', () async {
+ final String result = await methodChannelConnectivity.getWifiBSSID();
+ expect(result, 'c0:ff:33:c0:d3:55');
expect(
log,
<Matcher>[
- isMethodCall('requestLocationServiceAuthorization',
- arguments: <bool>[true])
+ isMethodCall(
+ 'wifiBSSID',
+ arguments: null,
+ ),
+ ],
+ );
+ });
+
+ test('getWifiIP', () async {
+ final String result = await methodChannelConnectivity.getWifiIP();
+ expect(result, '127.0.0.1');
+ expect(
+ log,
+ <Matcher>[
+ isMethodCall(
+ 'wifiIPAddress',
+ arguments: null,
+ ),
+ ],
+ );
+ });
+
+ test('requestLocationServiceAuthorization', () async {
+ final LocationAuthorizationStatus result =
+ await methodChannelConnectivity.requestLocationServiceAuthorization();
+ expect(result, LocationAuthorizationStatus.authorizedAlways);
+ expect(
+ log,
+ <Matcher>[
+ isMethodCall(
+ 'requestLocationServiceAuthorization',
+ arguments: <bool>[false],
+ ),
],
);
});
test('getLocationServiceAuthorization', () async {
- await connectivity.getLocationServiceAuthorization();
+ final LocationAuthorizationStatus result =
+ await methodChannelConnectivity.getLocationServiceAuthorization();
+ expect(result, LocationAuthorizationStatus.authorizedAlways);
expect(
log,
<Matcher>[
- isMethodCall('getLocationServiceAuthorization', arguments: null)
+ isMethodCall(
+ 'getLocationServiceAuthorization',
+ arguments: null,
+ ),
+ ],
+ );
+ });
+
+ test('checkConnectivity', () async {
+ final ConnectivityResult result =
+ await methodChannelConnectivity.checkConnectivity();
+ expect(result, ConnectivityResult.wifi);
+ expect(
+ log,
+ <Matcher>[
+ isMethodCall(
+ 'check',
+ arguments: null,
+ ),
],
);
});
});
}
-
-class ConnectivityPlatformMock extends Mock
- with MockPlatformInterfaceMixin
- implements ConnectivityPlatform {}
-
-class ImplementsConnectivityPlatform extends Mock
- implements ConnectivityPlatform {}
-
-class ExtendsConnectivityPlatform extends ConnectivityPlatform {}