Merge null-safety plugins (#3324)

This commit is contained in:
Emmanuel Garcia
2020-12-14 13:33:59 -08:00
committed by GitHub
parent 4b0b0a86ce
commit a5c9c5635c
111 changed files with 1153 additions and 669 deletions

View File

@ -1,3 +1,11 @@
## 3.0.0-nullsafety.1
* Bump Dart SDK to support null safety.
## 3.0.0-nullsafety
* Migrate to null safety.
## 2.0.3
* Update Flutter SDK constraint.

View File

@ -0,0 +1,4 @@
include: ../../../analysis_options.yaml
analyzer:
enable-experiment:
- non-nullable

View File

@ -40,7 +40,7 @@ class MyApp extends StatelessWidget {
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@ -51,7 +51,7 @@ class MyHomePage extends StatefulWidget {
class _MyHomePageState extends State<MyHomePage> {
String _connectionStatus = 'Unknown';
final Connectivity _connectivity = Connectivity();
StreamSubscription<ConnectivityResult> _connectivitySubscription;
late StreamSubscription<ConnectivityResult> _connectivitySubscription;
@override
void initState() {
@ -69,7 +69,7 @@ class _MyHomePageState extends State<MyHomePage> {
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initConnectivity() async {
ConnectivityResult result;
ConnectivityResult result = ConnectivityResult.none;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
result = await _connectivity.checkConnectivity();

View File

@ -10,9 +10,10 @@ dependencies:
dev_dependencies:
flutter_driver:
sdk: flutter
test: ^1.10.0-nullsafety.1
integration_test:
path: ../../../integration_test
pedantic: ^1.8.0
pedantic: ^1.10.0-nullsafety.1
flutter:
uses-material-design: true

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(cyanglaz): Remove once https://github.com/flutter/plugins/pull/3158 is landed.
// @dart = 2.9
import 'package:integration_test/integration_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:connectivity/connectivity.dart';

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(cyanglaz): Remove once https://github.com/flutter/plugins/pull/3158 is landed.
// @dart = 2.9
import 'package:integration_test/integration_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:connectivity/connectivity.dart';

View File

@ -22,12 +22,12 @@ class Connectivity {
if (_singleton == null) {
_singleton = Connectivity._();
}
return _singleton;
return _singleton!;
}
Connectivity._();
static Connectivity _singleton;
static Connectivity? _singleton;
static ConnectivityPlatform get _platform => ConnectivityPlatform.instance;

View File

@ -2,7 +2,7 @@ name: connectivity
description: Flutter plugin for discovering the state of the network (WiFi &
mobile/cellular) connectivity on Android and iOS.
homepage: https://github.com/flutter/plugins/tree/master/packages/connectivity/connectivity
version: 2.0.3
version: 3.0.0-nullsafety.1
flutter:
plugin:
@ -21,21 +21,24 @@ dependencies:
flutter:
sdk: flutter
meta: ^1.0.5
connectivity_platform_interface: ^1.0.2
connectivity_macos: ^0.1.0
connectivity_for_web: ^0.3.0
connectivity_platform_interface: ^2.0.0-nullsafety.1
#TODO(cyanglaz): re-endorse the below plugins when they have migrated to nnbd.
# https://github.com/flutter/flutter/issues/68669
connectivity_macos: ^0.2.0-nullsafety
# connectivity_for_web: ^0.3.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_driver:
sdk: flutter
test: ^1.10.0-nullsafety.1
integration_test:
path: ../../integration_test
mockito: ^4.1.1
plugin_platform_interface: ^1.0.0
pedantic: ^1.8.0
plugin_platform_interface: ^1.1.0-nullsafety.1
pedantic: ^1.10.0-nullsafety.1
environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.12.13+hotfix.5"

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
// TODO(cyanglaz): Remove once Mockito is migrated to null safety.
// @dart = 2.9
import 'package:connectivity/connectivity.dart';
import 'package:connectivity_platform_interface/connectivity_platform_interface.dart';
import 'package:flutter_test/flutter_test.dart';

View File

@ -1,3 +1,7 @@
## 0.2.0-nullsafety
* Update Dart SDK constraint.
## 0.1.0+8
* Update Flutter SDK constraint.

View File

@ -3,7 +3,7 @@ description: macOS implementation of the connectivity plugin.
# 0.1.y+z is compatible with 1.0.0, if you land a breaking change bump
# the version to 2.0.0.
# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
version: 0.1.0+8
version: 0.2.0-nullsafety
homepage: https://github.com/flutter/plugins/tree/master/packages/connectivity/connectivity_macos
flutter:
@ -13,7 +13,7 @@ flutter:
pluginClass: ConnectivityPlugin
environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.10.0"
dependencies:

View File

@ -1,3 +1,11 @@
## 2.0.0-nullsafety.1
* Bump Dart SDK to support null safety.
## 2.0.0-nullsafety
* Migrate to null safety.
## 1.0.7
* Update Flutter SDK constraint.

View File

@ -0,0 +1,4 @@
include: ../../../analysis_options.yaml
analyzer:
enable-experiment:
- non-nullable

View File

@ -50,17 +50,17 @@ abstract class ConnectivityPlatform extends PlatformInterface {
}
/// Obtains the wifi name (SSID) of the connected network
Future<String> getWifiName() {
Future<String?> getWifiName() {
throw UnimplementedError('getWifiName() has not been implemented.');
}
/// Obtains the wifi BSSID of the connected network.
Future<String> getWifiBSSID() {
Future<String?> getWifiBSSID() {
throw UnimplementedError('getWifiBSSID() has not been implemented.');
}
/// Obtains the IP address of the connected wifi network
Future<String> getWifiIP() {
Future<String?> getWifiIP() {
throw UnimplementedError('getWifiIP() has not been implemented.');
}

View File

@ -22,29 +22,29 @@ class MethodChannelConnectivity extends ConnectivityPlatform {
EventChannel eventChannel =
EventChannel('plugins.flutter.io/connectivity_status');
Stream<ConnectivityResult> _onConnectivityChanged;
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);
_onConnectivityChanged =
eventChannel.receiveBroadcastStream().map((dynamic result) {
return result != null ? result.toString() : '';
}).map(parseConnectivityResult);
}
return _onConnectivityChanged;
return _onConnectivityChanged!;
}
@override
Future<ConnectivityResult> checkConnectivity() {
return methodChannel
.invokeMethod<String>('check')
.then(parseConnectivityResult);
Future<ConnectivityResult> checkConnectivity() async {
final String checkResult =
await methodChannel.invokeMethod<String>('check') ?? '';
return parseConnectivityResult(checkResult);
}
@override
Future<String> getWifiName() async {
String wifiName = await methodChannel.invokeMethod<String>('wifiName');
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>') {
@ -54,29 +54,31 @@ class MethodChannelConnectivity extends ConnectivityPlatform {
}
@override
Future<String> getWifiBSSID() {
Future<String?> getWifiBSSID() {
return methodChannel.invokeMethod<String>('wifiBSSID');
}
@override
Future<String> getWifiIP() {
Future<String?> getWifiIP() {
return methodChannel.invokeMethod<String>('wifiIPAddress');
}
@override
Future<LocationAuthorizationStatus> requestLocationServiceAuthorization({
bool requestAlwaysLocationUsage = false,
}) {
return methodChannel.invokeMethod<String>(
'requestLocationServiceAuthorization', <bool>[
requestAlwaysLocationUsage
]).then(parseLocationAuthorizationStatus);
}) async {
final String requestLocationServiceResult = await methodChannel
.invokeMethod<String>('requestLocationServiceAuthorization',
<bool>[requestAlwaysLocationUsage]) ??
'';
return parseLocationAuthorizationStatus(requestLocationServiceResult);
}
@override
Future<LocationAuthorizationStatus> getLocationServiceAuthorization() {
return methodChannel
.invokeMethod<String>('getLocationServiceAuthorization')
.then(parseLocationAuthorizationStatus);
Future<LocationAuthorizationStatus> getLocationServiceAuthorization() async {
final String getLocationServiceResult = await methodChannel
.invokeMethod<String>('getLocationServiceAuthorization') ??
'';
return parseLocationAuthorizationStatus(getLocationServiceResult);
}
}

View File

@ -3,19 +3,19 @@ description: A common platform interface for the connectivity plugin.
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.7
version: 2.0.0-nullsafety.1
dependencies:
flutter:
sdk: flutter
meta: ^1.0.5
plugin_platform_interface: ^1.0.1
meta: ^1.3.0-nullsafety.3
plugin_platform_interface: ^1.1.0-nullsafety.1
dev_dependencies:
flutter_test:
sdk: flutter
pedantic: ^1.8.0
pedantic: ^1.10.0-nullsafety.1
environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.12.13+hotfix.5"

View File

@ -12,7 +12,7 @@ void main() {
group('$MethodChannelConnectivity', () {
final List<MethodCall> log = <MethodCall>[];
MethodChannelConnectivity methodChannelConnectivity;
late MethodChannelConnectivity methodChannelConnectivity;
setUp(() async {
methodChannelConnectivity = MethodChannelConnectivity();
@ -42,7 +42,7 @@ void main() {
.setMockMethodCallHandler((MethodCall methodCall) async {
switch (methodCall.method) {
case 'listen':
await ServicesBinding.instance.defaultBinaryMessenger
await ServicesBinding.instance!.defaultBinaryMessenger
.handlePlatformMessage(
methodChannelConnectivity.eventChannel.name,
methodChannelConnectivity.eventChannel.codec
@ -64,7 +64,7 @@ void main() {
});
test('getWifiName', () async {
final String result = await methodChannelConnectivity.getWifiName();
final String? result = await methodChannelConnectivity.getWifiName();
expect(result, '1337wifi');
expect(
log,
@ -78,7 +78,7 @@ void main() {
});
test('getWifiBSSID', () async {
final String result = await methodChannelConnectivity.getWifiBSSID();
final String? result = await methodChannelConnectivity.getWifiBSSID();
expect(result, 'c0:ff:33:c0:d3:55');
expect(
log,
@ -92,7 +92,7 @@ void main() {
});
test('getWifiIP', () async {
final String result = await methodChannelConnectivity.getWifiIP();
final String? result = await methodChannelConnectivity.getWifiIP();
expect(result, '127.0.0.1');
expect(
log,

View File

@ -1,3 +1,11 @@
## 2.0.0-nullsafety.1
* Bump Dart SDK to support null safety.
## 2.0.0-nullsafety
* Migrate to null safety.
## 1.0.1
* Update Flutter SDK constraint.

View File

@ -0,0 +1,4 @@
include: ../../../analysis_options.yaml
analyzer:
enable-experiment:
- non-nullable

View File

@ -2,6 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(cyanglaz): Remove once https://github.com/flutter/plugins/pull/3158 is landed.
// @dart = 2.9
import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
import 'package:device_info/device_info.dart';

View File

@ -36,7 +36,7 @@ class _MyAppState extends State<MyApp> {
}
Future<void> initPlatformState() async {
Map<String, dynamic> deviceData;
Map<String, dynamic> deviceData = <String, dynamic>{};
try {
if (Platform.isAndroid) {

View File

@ -12,11 +12,11 @@ dev_dependencies:
sdk: flutter
integration_test:
path: ../../../integration_test
pedantic: ^1.8.0
pedantic: ^1.10.0-nullsafety.1
flutter:
uses-material-design: true
environment:
sdk: ">=2.1.0<3.0.0"
sdk: ">=2.10.0-56.0.dev <3.0.0"
flutter: ">=1.12.13+hotfix.5 <2.0.0"

View File

@ -2,6 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(cyanglaz): Remove once https://github.com/flutter/flutter/issues/59879 is fixed.
// @dart = 2.9
import 'dart:async';
import 'dart:convert';
import 'dart:io';

View File

@ -15,7 +15,7 @@ class DeviceInfoPlugin {
DeviceInfoPlugin();
/// This information does not change from call to call. Cache it.
AndroidDeviceInfo _cachedAndroidDeviceInfo;
AndroidDeviceInfo? _cachedAndroidDeviceInfo;
/// Information derived from `android.os.Build`.
///
@ -25,7 +25,7 @@ class DeviceInfoPlugin {
await DeviceInfoPlatform.instance.androidInfo();
/// This information does not change from call to call. Cache it.
IosDeviceInfo _cachedIosDeviceInfo;
IosDeviceInfo? _cachedIosDeviceInfo;
/// Information derived from `UIDevice`.
///

View File

@ -2,7 +2,10 @@ name: device_info
description: Flutter plugin providing detailed information about the device
(make, model, etc.), and Android or iOS version the app is running on.
homepage: https://github.com/flutter/plugins/tree/master/packages/device_info
version: 1.0.1
# 0.4.y+z is compatible with 1.0.0, if you land a breaking change bump
# the version to 2.0.0.
# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
version: 2.0.0-nullsafety.1
flutter:
plugin:
@ -16,14 +19,13 @@ flutter:
dependencies:
flutter:
sdk: flutter
device_info_platform_interface: ^1.0.0
device_info_platform_interface: ^2.0.0-nullsafety.1
dev_dependencies:
test: ^1.3.0
test: ^1.10.0-nullsafety.1
flutter_test:
sdk: flutter
pedantic: ^1.8.0
pedantic: ^1.10.0-nullsafety.1
environment:
sdk: ">=2.1.0<3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.12.13+hotfix.5"

View File

@ -1,3 +1,16 @@
## 2.0.0-nullsafety.2
* Make `baseOS`, `previewSdkInt`, and `securityPatch` nullable types.
* Remove default values for non-nullable types.
## 2.0.0-nullsafety.1
* Bump Dart SDK to support null safety.
## 2.0.0-nullsafety
* Migrate to null safety.
## 1.0.2
- Update Flutter SDK constraint.

View File

@ -0,0 +1,4 @@
include: ../../../analysis_options.yaml
analyzer:
enable-experiment:
- non-nullable

View File

@ -8,27 +8,27 @@
class AndroidDeviceInfo {
/// Android device Info class.
AndroidDeviceInfo({
this.version,
this.board,
this.bootloader,
this.brand,
this.device,
this.display,
this.fingerprint,
this.hardware,
this.host,
this.id,
this.manufacturer,
this.model,
this.product,
List<String> supported32BitAbis,
List<String> supported64BitAbis,
List<String> supportedAbis,
this.tags,
this.type,
this.isPhysicalDevice,
this.androidId,
List<String> systemFeatures,
required this.version,
required this.board,
required this.bootloader,
required this.brand,
required this.device,
required this.display,
required this.fingerprint,
required this.hardware,
required this.host,
required this.id,
required this.manufacturer,
required this.model,
required this.product,
required List<String> supported32BitAbis,
required List<String> supported64BitAbis,
required List<String> supportedAbis,
required this.tags,
required this.type,
required this.isPhysicalDevice,
required this.androidId,
required List<String> systemFeatures,
}) : supported32BitAbis = List<String>.unmodifiable(supported32BitAbis),
supported64BitAbis = List<String>.unmodifiable(supported64BitAbis),
supportedAbis = List<String>.unmodifiable(supportedAbis),
@ -113,28 +113,28 @@ class AndroidDeviceInfo {
/// Deserializes from the message received from [_kChannel].
static AndroidDeviceInfo fromMap(Map<String, dynamic> map) {
return AndroidDeviceInfo(
version: AndroidBuildVersion._fromMap(
map['version']?.cast<String, dynamic>() ?? {}),
board: map['board'],
bootloader: map['bootloader'],
brand: map['brand'],
device: map['device'],
display: map['display'],
fingerprint: map['fingerprint'],
hardware: map['hardware'],
host: map['host'],
id: map['id'],
manufacturer: map['manufacturer'],
model: map['model'],
product: map['product'],
supported32BitAbis: _fromList(map['supported32BitAbis'] ?? []),
supported64BitAbis: _fromList(map['supported64BitAbis'] ?? []),
supportedAbis: _fromList(map['supportedAbis'] ?? []),
tags: map['tags'],
type: map['type'],
isPhysicalDevice: map['isPhysicalDevice'],
androidId: map['androidId'],
systemFeatures: _fromList(map['systemFeatures'] ?? []),
version:
AndroidBuildVersion._fromMap(map['version']!.cast<String, dynamic>()),
board: map['board']!,
bootloader: map['bootloader']!,
brand: map['brand']!,
device: map['device']!,
display: map['display']!,
fingerprint: map['fingerprint']!,
hardware: map['hardware']!,
host: map['host']!,
id: map['id']!,
manufacturer: map['manufacturer']!,
model: map['model']!,
product: map['product']!,
supported32BitAbis: _fromList(map['supported32BitAbis']!),
supported64BitAbis: _fromList(map['supported64BitAbis']!),
supportedAbis: _fromList(map['supportedAbis']!),
tags: map['tags']!,
type: map['type']!,
isPhysicalDevice: map['isPhysicalDevice']!,
androidId: map['androidId']!,
systemFeatures: _fromList(map['systemFeatures']!),
);
}
@ -152,16 +152,25 @@ class AndroidDeviceInfo {
class AndroidBuildVersion {
AndroidBuildVersion._({
this.baseOS,
this.codename,
this.incremental,
this.previewSdkInt,
this.release,
this.sdkInt,
this.securityPatch,
required this.codename,
required this.incremental,
required this.release,
required this.sdkInt,
});
/// The base OS build the product is based on.
final String baseOS;
/// This is only available on Android 6.0 or above.
String? baseOS;
/// The developer preview revision of a prerelease SDK.
/// This is only available on Android 6.0 or above.
int? previewSdkInt;
/// The user-visible security patch level.
/// This is only available on Android 6.0 or above.
final String? securityPatch;
/// The current development codename, or the string "REL" if this is a release build.
final String codename;
@ -169,9 +178,6 @@ class AndroidBuildVersion {
/// The internal value used by the underlying source control to represent this build.
final String incremental;
/// The developer preview revision of a prerelease SDK.
final int previewSdkInt;
/// The user-visible version string.
final String release;
@ -180,19 +186,16 @@ class AndroidBuildVersion {
/// Possible values are defined in: https://developer.android.com/reference/android/os/Build.VERSION_CODES.html
final int sdkInt;
/// The user-visible security patch level.
final String securityPatch;
/// Deserializes from the map message received from [_kChannel].
static AndroidBuildVersion _fromMap(Map<String, dynamic> map) {
return AndroidBuildVersion._(
baseOS: map['baseOS'],
codename: map['codename'],
incremental: map['incremental'],
previewSdkInt: map['previewSdkInt'],
release: map['release'],
sdkInt: map['sdkInt'],
securityPatch: map['securityPatch'],
codename: map['codename']!,
incremental: map['incremental']!,
release: map['release']!,
sdkInt: map['sdkInt']!,
);
}
}

View File

@ -8,14 +8,14 @@
class IosDeviceInfo {
/// IOS device info class.
IosDeviceInfo({
this.name,
this.systemName,
this.systemVersion,
this.model,
this.localizedModel,
this.identifierForVendor,
this.isPhysicalDevice,
this.utsname,
required this.name,
required this.systemName,
required this.systemVersion,
required this.model,
required this.localizedModel,
required this.identifierForVendor,
required this.isPhysicalDevice,
required this.utsname,
});
/// Device name.
@ -45,15 +45,14 @@ class IosDeviceInfo {
/// Deserializes from the map message received from [_kChannel].
static IosDeviceInfo fromMap(Map<String, dynamic> map) {
return IosDeviceInfo(
name: map['name'],
systemName: map['systemName'],
systemVersion: map['systemVersion'],
model: map['model'],
localizedModel: map['localizedModel'],
identifierForVendor: map['identifierForVendor'],
name: map['name']!,
systemName: map['systemName']!,
systemVersion: map['systemVersion']!,
model: map['model']!,
localizedModel: map['localizedModel']!,
identifierForVendor: map['identifierForVendor']!,
isPhysicalDevice: map['isPhysicalDevice'] == 'true',
utsname:
IosUtsname._fromMap(map['utsname']?.cast<String, dynamic>() ?? {}),
utsname: IosUtsname._fromMap(map['utsname']!.cast<String, dynamic>()),
);
}
}
@ -62,11 +61,11 @@ class IosDeviceInfo {
/// See http://pubs.opengroup.org/onlinepubs/7908799/xsh/sysutsname.h.html for details.
class IosUtsname {
IosUtsname._({
this.sysname,
this.nodename,
this.release,
this.version,
this.machine,
required this.sysname,
required this.nodename,
required this.release,
required this.version,
required this.machine,
});
/// Operating system name.
@ -87,11 +86,11 @@ class IosUtsname {
/// Deserializes from the map message received from [_kChannel].
static IosUtsname _fromMap(Map<String, dynamic> map) {
return IosUtsname._(
sysname: map['sysname'],
nodename: map['nodename'],
release: map['release'],
version: map['version'],
machine: map['machine'],
sysname: map['sysname']!,
nodename: map['nodename']!,
release: map['release']!,
version: map['version']!,
machine: map['machine']!,
);
}
}

View File

@ -3,20 +3,20 @@ description: A common platform interface for the device_info plugin.
homepage: https://github.com/flutter/plugins/tree/master/packages/device_info
# 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.2
version: 2.0.0-nullsafety.2
dependencies:
flutter:
sdk: flutter
meta: ^1.1.8
plugin_platform_interface: ^1.0.2
meta: ^1.3.0-nullsafety.3
plugin_platform_interface: ^1.1.0-nullsafety.1
dev_dependencies:
flutter_test:
sdk: flutter
mockito: ^4.1.1
pedantic: ^1.8.0
test: ^1.10.0-nullsafety.1
pedantic: ^1.10.0-nullsafety.1
environment:
sdk: ">=2.7.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.9.1+hotfix.4"

View File

@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(cyanglaz): Remove once https://github.com/flutter/flutter/issues/59879 is fixed.
// @dart = 2.9
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:device_info_platform_interface/device_info_platform_interface.dart';
import 'package:device_info_platform_interface/method_channel/method_channel_device_info.dart';
void main() {
@ -23,11 +24,68 @@ void main() {
switch (methodCall.method) {
case 'getAndroidDeviceInfo':
return ({
"brand": "Google",
"version": <String, dynamic>{
"securityPatch": "2018-09-05",
"sdkInt": 28,
"release": "9",
"previewSdkInt": 0,
"incremental": "5124027",
"codename": "REL",
"baseOS": "",
},
"board": "goldfish_x86_64",
"bootloader": "unknown",
"brand": "google",
"device": "generic_x86_64",
"display": "PSR1.180720.075",
"fingerprint":
"google/sdk_gphone_x86_64/generic_x86_64:9/PSR1.180720.075/5124027:user/release-keys",
"hardware": "ranchu",
"host": "abfarm730",
"id": "PSR1.180720.075",
"manufacturer": "Google",
"model": "Android SDK built for x86_64",
"product": "sdk_gphone_x86_64",
"supported32BitAbis": <String>[
"x86",
],
"supported64BitAbis": <String>[
"x86_64",
],
"supportedAbis": <String>[
"x86_64",
"x86",
],
"tags": "release-keys",
"type": "user",
"isPhysicalDevice": false,
"androidId": "f47571f3b4648f45",
"systemFeatures": <String>[
"android.hardware.sensor.proximity",
"android.software.adoptable_storage",
"android.hardware.sensor.accelerometer",
"android.hardware.faketouch",
"android.software.backup",
"android.hardware.touchscreen",
],
});
case 'getIosDeviceInfo':
return ({
"name": "iPhone 10",
"name": "iPhone 13",
"systemName": "iOS",
"systemVersion": "13.0",
"model": "iPhone",
"localizedModel": "iPhone",
"identifierForVendor": "88F59280-55AD-402C-B922-3203B4794C06",
"isPhysicalDevice": false,
"utsname": <String, dynamic>{
"sysname": "Darwin",
"nodename": "host",
"release": "19.6.0",
"version":
"Darwin Kernel Version 19.6.0: Thu Jun 18 20:49:00 PDT 2020; root:xnu-6153.141.1~1/RELEASE_X86_64",
"machine": "x86_64",
}
});
default:
return null;
@ -38,12 +96,66 @@ void main() {
test("androidInfo", () async {
final AndroidDeviceInfo result =
await methodChannelDeviceInfo.androidInfo();
expect(result.brand, "Google");
expect(result.version.securityPatch, "2018-09-05");
expect(result.version.sdkInt, 28);
expect(result.version.release, "9");
expect(result.version.previewSdkInt, 0);
expect(result.version.incremental, "5124027");
expect(result.version.codename, "REL");
expect(result.board, "goldfish_x86_64");
expect(result.bootloader, "unknown");
expect(result.brand, "google");
expect(result.device, "generic_x86_64");
expect(result.display, "PSR1.180720.075");
expect(result.fingerprint,
"google/sdk_gphone_x86_64/generic_x86_64:9/PSR1.180720.075/5124027:user/release-keys");
expect(result.hardware, "ranchu");
expect(result.host, "abfarm730");
expect(result.id, "PSR1.180720.075");
expect(result.manufacturer, "Google");
expect(result.model, "Android SDK built for x86_64");
expect(result.product, "sdk_gphone_x86_64");
expect(result.supported32BitAbis, <String>[
"x86",
]);
expect(result.supported64BitAbis, <String>[
"x86_64",
]);
expect(result.supportedAbis, <String>[
"x86_64",
"x86",
]);
expect(result.tags, "release-keys");
expect(result.type, "user");
expect(result.isPhysicalDevice, false);
expect(result.androidId, "f47571f3b4648f45");
expect(result.systemFeatures, <String>[
"android.hardware.sensor.proximity",
"android.software.adoptable_storage",
"android.hardware.sensor.accelerometer",
"android.hardware.faketouch",
"android.software.backup",
"android.hardware.touchscreen",
]);
});
test("iosInfo", () async {
final IosDeviceInfo result = await methodChannelDeviceInfo.iosInfo();
expect(result.name, "iPhone 10");
expect(result.name, "iPhone 13");
expect(result.systemName, "iOS");
expect(result.systemVersion, "13.0");
expect(result.model, "iPhone");
expect(result.localizedModel, "iPhone");
expect(
result.identifierForVendor, "88F59280-55AD-402C-B922-3203B4794C06");
expect(result.isPhysicalDevice, false);
expect(result.utsname.sysname, "Darwin");
expect(result.utsname.nodename, "host");
expect(result.utsname.release, "19.6.0");
expect(result.utsname.version,
"Darwin Kernel Version 19.6.0: Thu Jun 18 20:49:00 PDT 2020; root:xnu-6153.141.1~1/RELEASE_X86_64");
expect(result.utsname.machine, "x86_64");
});
});
}

View File

@ -1,3 +1,11 @@
## 2.0.0-nullsafety.1
* Fix example app SDK.
## 2.0.0-nullsafety
* Bump Dart SDK.
## 1.0.12
* Update Flutter SDK constraint.

View File

@ -3,7 +3,7 @@ description: Demonstrates how to use the flutter_plugin_android_lifecycle plugin
publish_to: 'none'
environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
dependencies:
flutter:

View File

@ -1,10 +1,10 @@
name: flutter_plugin_android_lifecycle
description: Flutter plugin for accessing an Android Lifecycle within other plugins.
version: 1.0.12
version: 2.0.0-nullsafety.1
homepage: https://github.com/flutter/plugins/tree/master/packages/flutter_plugin_android_lifecycle
environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.12.13"
dependencies:

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
// @dart = 2.9
import 'dart:async';

View File

@ -1,3 +1,7 @@
## 1.0.0-nullsafety
* Migrate to null safety.
## 0.6.3+5
* Update Flutter SDK constraint.

View File

@ -25,14 +25,14 @@ class AndroidAuthMessages {
this.goToSettingsDescription,
});
final String fingerprintHint;
final String fingerprintNotRecognized;
final String fingerprintSuccess;
final String cancelButton;
final String signInTitle;
final String fingerprintRequiredTitle;
final String goToSettingsButton;
final String goToSettingsDescription;
final String? fingerprintHint;
final String? fingerprintNotRecognized;
final String? fingerprintSuccess;
final String? cancelButton;
final String? signInTitle;
final String? fingerprintRequiredTitle;
final String? goToSettingsButton;
final String? goToSettingsDescription;
Map<String, String> get args {
return <String, String>{
@ -62,10 +62,10 @@ class IOSAuthMessages {
this.cancelButton,
});
final String lockOut;
final String goToSettingsButton;
final String goToSettingsDescription;
final String cancelButton;
final String? lockOut;
final String? goToSettingsButton;
final String? goToSettingsDescription;
final String? cancelButton;
Map<String, String> get args {
return <String, String>{

View File

@ -67,7 +67,7 @@ class LocalAuthentication {
/// [PlatformException] with error code [otherOperatingSystem] on the iOS
/// simulator.
Future<bool> authenticateWithBiometrics({
@required String localizedReason,
required String localizedReason,
bool useErrorDialogs = true,
bool stickyAuth = false,
AndroidAuthMessages androidAuthStrings = const AndroidAuthMessages(),
@ -92,8 +92,9 @@ class LocalAuthentication {
'operating systems.',
details: 'Your operating system is ${_platform.operatingSystem}');
}
return await _channel.invokeMethod<bool>(
'authenticateWithBiometrics', args);
final bool? result =
await _channel.invokeMethod<bool>('authenticateWithBiometrics', args);
return result!;
}
/// Returns true if auth was cancelled successfully.
@ -101,18 +102,20 @@ class LocalAuthentication {
/// Returns false if there was some error or no auth in progress.
///
/// Returns [Future] bool true or false:
Future<bool> stopAuthentication() {
Future<bool> stopAuthentication() async {
if (_platform.isAndroid) {
return _channel.invokeMethod<bool>('stopAuthentication');
final bool? result =
await _channel.invokeMethod<bool>('stopAuthentication');
return result!;
}
return Future<bool>.sync(() => true);
return true;
}
/// Returns true if device is capable of checking biometrics
///
/// Returns a [Future] bool true or false:
Future<bool> get canCheckBiometrics async =>
(await _channel.invokeListMethod<String>('getAvailableBiometrics'))
(await _channel.invokeListMethod<String>('getAvailableBiometrics'))!
.isNotEmpty;
/// Returns a list of enrolled biometrics
@ -122,10 +125,10 @@ class LocalAuthentication {
/// - BiometricType.fingerprint
/// - BiometricType.iris (not yet implemented)
Future<List<BiometricType>> getAvailableBiometrics() async {
final List<String> result =
(await _channel.invokeListMethod<String>('getAvailableBiometrics'));
final List<String>? result =
await _channel.invokeListMethod<String>('getAvailableBiometrics');
final List<BiometricType> biometrics = <BiometricType>[];
result.forEach((String value) {
result!.forEach((String value) {
switch (value) {
case 'face':
biometrics.add(BiometricType.face);

View File

@ -2,7 +2,7 @@ name: local_auth
description: Flutter plugin for Android and iOS device authentication sensors
such as Fingerprint Reader and Touch ID.
homepage: https://github.com/flutter/plugins/tree/master/packages/local_auth
version: 0.6.3+5
version: 1.0.0-nullsafety
flutter:
plugin:
@ -16,10 +16,10 @@ flutter:
dependencies:
flutter:
sdk: flutter
meta: ^1.0.5
intl: ">=0.15.1 <0.17.0"
platform: ">=2.0.0 <4.0.0"
flutter_plugin_android_lifecycle: ^1.0.2
meta: ^1.3.0-nullsafety.3
intl: ^0.17.0-nullsafety.2
platform: ^3.0.0-nullsafety.4
flutter_plugin_android_lifecycle: ^2.0.0-nullsafety
dev_dependencies:
integration_test:
@ -28,8 +28,8 @@ dev_dependencies:
sdk: flutter
flutter_test:
sdk: flutter
pedantic: ^1.8.0
pedantic: ^1.10.0-nullsafety.1
environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.12.13+hotfix.5"

View File

@ -19,7 +19,7 @@ void main() {
);
final List<MethodCall> log = <MethodCall>[];
LocalAuthentication localAuthentication;
late LocalAuthentication localAuthentication;
setUp(() {
channel.setMockMethodCallHandler((MethodCall methodCall) {

View File

@ -1,3 +1,7 @@
## 2.0.0-nullsafety
* Migrate to null safety.
## 1.0.5
* Update Flutter SDK constraint.

View File

@ -40,26 +40,26 @@ abstract class PathProviderPlatform extends PlatformInterface {
/// Path to the temporary directory on the device that is not backed up and is
/// suitable for storing caches of downloaded files.
Future<String> getTemporaryPath() {
Future<String?> getTemporaryPath() {
throw UnimplementedError('getTemporaryPath() has not been implemented.');
}
/// Path to a directory where the application may place application support
/// files.
Future<String> getApplicationSupportPath() {
Future<String?> getApplicationSupportPath() {
throw UnimplementedError(
'getApplicationSupportPath() has not been implemented.');
}
/// Path to the directory where application can store files that are persistent,
/// backed up, and not visible to the user, such as sqlite.db.
Future<String> getLibraryPath() {
Future<String?> getLibraryPath() {
throw UnimplementedError('getLibraryPath() has not been implemented.');
}
/// Path to a directory where the application may place data that is
/// user-generated, or that cannot otherwise be recreated by your application.
Future<String> getApplicationDocumentsPath() {
Future<String?> getApplicationDocumentsPath() {
throw UnimplementedError(
'getApplicationDocumentsPath() has not been implemented.');
}
@ -67,7 +67,7 @@ abstract class PathProviderPlatform extends PlatformInterface {
/// Path to a directory where the application may access top level storage.
/// The current operating system should be determined before issuing this
/// function call, as this functionality is only available on Android.
Future<String> getExternalStoragePath() {
Future<String?> getExternalStoragePath() {
throw UnimplementedError(
'getExternalStoragePath() has not been implemented.');
}
@ -76,7 +76,7 @@ abstract class PathProviderPlatform extends PlatformInterface {
/// stored. These paths typically reside on external storage like separate
/// partitions or SD cards. Phones may have multiple storage directories
/// available.
Future<List<String>> getExternalCachePaths() {
Future<List<String>?> getExternalCachePaths() {
throw UnimplementedError(
'getExternalCachePaths() has not been implemented.');
}
@ -84,10 +84,10 @@ abstract class PathProviderPlatform extends PlatformInterface {
/// Paths to directories where application specific data can be stored.
/// These paths typically reside on external storage like separate partitions
/// or SD cards. Phones may have multiple storage directories available.
Future<List<String>> getExternalStoragePaths({
Future<List<String>?> getExternalStoragePaths({
/// Optional parameter. See [StorageDirectory] for more informations on
/// how this type translates to Android storage directories.
StorageDirectory type,
StorageDirectory? type,
}) {
throw UnimplementedError(
'getExternalStoragePaths() has not been implemented.');
@ -95,7 +95,7 @@ abstract class PathProviderPlatform extends PlatformInterface {
/// Path to the directory where downloaded files can be stored.
/// This is typically only relevant on desktop operating systems.
Future<String> getDownloadsPath() {
Future<String?> getDownloadsPath() {
throw UnimplementedError('getDownloadsPath() has not been implemented.');
}
}

View File

@ -30,34 +30,34 @@ class MethodChannelPathProvider extends PathProviderPlatform {
_platform = platform;
}
Future<String> getTemporaryPath() {
Future<String?> getTemporaryPath() {
return methodChannel.invokeMethod<String>('getTemporaryDirectory');
}
Future<String> getApplicationSupportPath() {
Future<String?> getApplicationSupportPath() {
return methodChannel.invokeMethod<String>('getApplicationSupportDirectory');
}
Future<String> getLibraryPath() {
Future<String?> getLibraryPath() {
if (!_platform.isIOS && !_platform.isMacOS) {
throw UnsupportedError('Functionality only available on iOS/macOS');
}
return methodChannel.invokeMethod<String>('getLibraryDirectory');
}
Future<String> getApplicationDocumentsPath() {
Future<String?> getApplicationDocumentsPath() {
return methodChannel
.invokeMethod<String>('getApplicationDocumentsDirectory');
}
Future<String> getExternalStoragePath() {
Future<String?> getExternalStoragePath() {
if (!_platform.isAndroid) {
throw UnsupportedError('Functionality only available on Android');
}
return methodChannel.invokeMethod<String>('getStorageDirectory');
}
Future<List<String>> getExternalCachePaths() {
Future<List<String>?> getExternalCachePaths() {
if (!_platform.isAndroid) {
throw UnsupportedError('Functionality only available on Android');
}
@ -65,8 +65,8 @@ class MethodChannelPathProvider extends PathProviderPlatform {
.invokeListMethod<String>('getExternalCacheDirectories');
}
Future<List<String>> getExternalStoragePaths({
StorageDirectory type,
Future<List<String>?> getExternalStoragePaths({
StorageDirectory? type,
}) async {
if (!_platform.isAndroid) {
throw UnsupportedError('Functionality only available on Android');
@ -77,7 +77,7 @@ class MethodChannelPathProvider extends PathProviderPlatform {
);
}
Future<String> getDownloadsPath() {
Future<String?> getDownloadsPath() {
if (!_platform.isMacOS) {
throw UnsupportedError('Functionality only available on macOS');
}

View File

@ -3,20 +3,20 @@ description: A common platform interface for the path_provider plugin.
homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider_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.5
version: 2.0.0-nullsafety
dependencies:
flutter:
sdk: flutter
meta: ^1.0.5
platform: ">=2.0.0 <4.0.0"
plugin_platform_interface: ^1.0.1
meta: ^1.3.0-nullsafety.3
platform: ^3.0.0-nullsafety.4
plugin_platform_interface: ^1.1.0-nullsafety
dev_dependencies:
flutter_test:
sdk: flutter
pedantic: ^1.8.0
pedantic: ^1.10.0-nullsafety.1
environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.10.0"

View File

@ -19,7 +19,7 @@ void main() {
const String kDownloadsPath = 'downloadsPath';
group('$MethodChannelPathProvider', () {
MethodChannelPathProvider methodChannelPathProvider;
late MethodChannelPathProvider methodChannelPathProvider;
final List<MethodCall> log = <MethodCall>[];
setUp(() async {
@ -59,7 +59,7 @@ void main() {
});
test('getTemporaryPath', () async {
final String path = await methodChannelPathProvider.getTemporaryPath();
final String? path = await methodChannelPathProvider.getTemporaryPath();
expect(
log,
<Matcher>[isMethodCall('getTemporaryDirectory', arguments: null)],
@ -68,7 +68,7 @@ void main() {
});
test('getApplicationSupportPath', () async {
final String path =
final String? path =
await methodChannelPathProvider.getApplicationSupportPath();
expect(
log,
@ -92,7 +92,7 @@ void main() {
methodChannelPathProvider
.setMockPathProviderPlatform(FakePlatform(operatingSystem: 'ios'));
final String path = await methodChannelPathProvider.getLibraryPath();
final String? path = await methodChannelPathProvider.getLibraryPath();
expect(
log,
<Matcher>[isMethodCall('getLibraryDirectory', arguments: null)],
@ -104,7 +104,7 @@ void main() {
methodChannelPathProvider
.setMockPathProviderPlatform(FakePlatform(operatingSystem: 'macos'));
final String path = await methodChannelPathProvider.getLibraryPath();
final String? path = await methodChannelPathProvider.getLibraryPath();
expect(
log,
<Matcher>[isMethodCall('getLibraryDirectory', arguments: null)],
@ -113,7 +113,7 @@ void main() {
});
test('getApplicationDocumentsPath', () async {
final String path =
final String? path =
await methodChannelPathProvider.getApplicationDocumentsPath();
expect(
log,
@ -125,13 +125,13 @@ void main() {
});
test('getExternalCachePaths android succeeds', () async {
final List<String> result =
final List<String>? result =
await methodChannelPathProvider.getExternalCachePaths();
expect(
log,
<Matcher>[isMethodCall('getExternalCacheDirectories', arguments: null)],
);
expect(result.length, 1);
expect(result!.length, 1);
expect(result.first, kExternalCachePaths);
});
@ -147,10 +147,12 @@ void main() {
}
});
for (StorageDirectory type
in StorageDirectory.values + <StorageDirectory>[null]) {
for (StorageDirectory? type in <StorageDirectory?>[
null,
...StorageDirectory.values
]) {
test('getExternalStoragePaths (type: $type) android succeeds', () async {
final List<String> result =
final List<String>? result =
await methodChannelPathProvider.getExternalStoragePaths(type: type);
expect(
log,
@ -162,7 +164,7 @@ void main() {
],
);
expect(result.length, 1);
expect(result!.length, 1);
expect(result.first, kExternalStoragePaths);
});
@ -182,7 +184,7 @@ void main() {
test('getDownloadsPath macos succeeds', () async {
methodChannelPathProvider
.setMockPathProviderPlatform(FakePlatform(operatingSystem: 'macos'));
final String result = await methodChannelPathProvider.getDownloadsPath();
final String? result = await methodChannelPathProvider.getDownloadsPath();
expect(
log,
<Matcher>[isMethodCall('getDownloadsDirectory', arguments: null)],

View File

@ -1,3 +1,11 @@
## 1.1.0-nullsafety.1
* Bump Dart SDK to support null safety.
## 1.1.0-nullsafety
* Migrate to null safety.
## 1.0.3
* Fix homepage in `pubspec.yaml`.

View File

@ -0,0 +1,4 @@
include: ../../analysis_options.yaml
analyzer:
enable-experiment:
- non-nullable

View File

@ -41,7 +41,7 @@ import 'package:meta/meta.dart';
/// [MockPlatformInterfaceMixin] for a sample of using Mockito to mock a platform interface.
abstract class PlatformInterface {
/// Pass a private, class-specific `const Object()` as the `token`.
PlatformInterface({@required Object token}) : _instanceToken = token;
PlatformInterface({required Object token}) : _instanceToken = token;
final Object _instanceToken;

View File

@ -12,17 +12,17 @@ description: Reusable base class for Flutter plugin platform interfaces.
# be done when absolutely necessary and after the ecosystem has already migrated to 1.X.Y version
# that is forward compatible with 2.0.0 (ideally the ecosystem have migrated to depend on:
# `plugin_platform_interface: >=1.X.Y <3.0.0`).
version: 1.0.3
version: 1.1.0-nullsafety.1
repository: https://github.com/flutter/plugins/tree/master/packages/plugin_platform_interface
environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
dependencies:
meta: ^1.0.0
meta: ^1.3.0-nullsafety.3
dev_dependencies:
mockito: ^4.1.1
test: ^1.9.4
pedantic: ^1.8.0
test: ^1.10.0-nullsafety.1
pedantic: ^1.10.0-nullsafety.1

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(egarciad): Remove once Mockito is migrated to null safety.
// @dart = 2.9
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
// @dart = 2.9
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

View File

@ -1,3 +1,11 @@
## 6.0.0-nullsafety.1
* Bump Dart SDK to support null safety.
## 6.0.0-nullsafety
* Migrate to null safety.
## 5.7.13
* Update Flutter SDK constraint.

View File

@ -0,0 +1,4 @@
include: ../../../analysis_options.yaml
analyzer:
enable-experiment:
- non-nullable

View File

@ -2,6 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(egarciad): Remove once integration_test is migrated to null safety.
// @dart = 2.9
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart' show kIsWeb;

View File

@ -27,7 +27,7 @@ class MyApp extends StatelessWidget {
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
@ -35,7 +35,7 @@ class MyHomePage extends StatefulWidget {
}
class _MyHomePageState extends State<MyHomePage> {
Future<void> _launched;
Future<void>? _launched;
String _phone = '';
Future<void> _launchInBrowser(String url) async {

View File

@ -12,9 +12,9 @@ dev_dependencies:
path: ../../../integration_test
flutter_driver:
sdk: flutter
pedantic: ^1.8.0
pedantic: ^1.10.0-nullsafety.1
mockito: ^4.1.1
plugin_platform_interface: ^1.0.0
plugin_platform_interface: ^1.1.0-nullsafety.1
flutter:
uses-material-design: true

View File

@ -1,3 +1,10 @@
// Copyright 2017 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.
// TODO(egarciad): Remove once mockito is migrated to null safety.
// @dart = 2.9
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:mockito/mockito.dart';

View File

@ -2,6 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(egarciad): Remove once flutter_driver is migrated to null safety.
// @dart = 2.9
import 'dart:async';
import 'dart:convert';
import 'dart:io';

View File

@ -40,7 +40,7 @@ class Link extends StatelessWidget implements LinkInfo {
final LinkWidgetBuilder builder;
/// The destination that this link leads to.
final Uri uri;
final Uri? uri;
/// The target indicating where to open the link.
final LinkTarget target;
@ -51,12 +51,11 @@ class Link extends StatelessWidget implements LinkInfo {
/// Creates a widget that renders a real link on the web, and uses WebViews in
/// native platforms to open links.
Link({
Key key,
@required this.uri,
LinkTarget target,
@required this.builder,
}) : target = target ?? LinkTarget.defaultTarget,
super(key: key);
Key? key,
required this.uri,
this.target = LinkTarget.defaultTarget,
required this.builder,
}) : super(key: key);
LinkDelegate get _effectiveDelegate {
return UrlLauncherPlatform.instance.linkDelegate ??
@ -90,16 +89,17 @@ class DefaultLinkDelegate extends StatelessWidget {
bool get _useWebView {
if (link.target == LinkTarget.self) return true;
if (link.target == LinkTarget.blank) return false;
return null;
return false;
}
Future<void> _followLink(BuildContext context) async {
if (!link.uri.hasScheme) {
if (!link.uri!.hasScheme) {
// A uri that doesn't have a scheme is an internal route name. In this
// case, we push it via Flutter's navigation system instead of letting the
// browser handle it.
final String routeName = link.uri.toString();
return pushRouteNameToFramework(context, routeName);
await pushRouteNameToFramework(context, routeName);
return;
}
// At this point, we know that the link is external. So we use the `launch`
@ -119,7 +119,6 @@ class DefaultLinkDelegate extends StatelessWidget {
context: ErrorDescription('during launching a link'),
));
}
return Future<void>.value(null);
}
@override

View File

@ -62,16 +62,15 @@ import 'package:url_launcher_platform_interface/url_launcher_platform_interface.
/// is set to true and the universal link failed to launch.
Future<bool> launch(
String urlString, {
bool forceSafariVC,
bool forceWebView,
bool enableJavaScript,
bool enableDomStorage,
bool universalLinksOnly,
Map<String, String> headers,
Brightness statusBarBrightness,
String webOnlyWindowName,
bool forceSafariVC = true,
bool forceWebView = false,
bool enableJavaScript = false,
bool enableDomStorage = false,
bool universalLinksOnly = false,
Map<String, String> headers = const <String, String>{},
Brightness? statusBarBrightness,
String? webOnlyWindowName,
}) async {
assert(urlString != null);
final Uri url = Uri.parse(urlString.trimLeft());
final bool isWebURL = url.scheme == 'http' || url.scheme == 'https';
if ((forceSafariVC == true || forceWebView == true) && !isWebURL) {
@ -84,29 +83,32 @@ Future<bool> launch(
/// [true] so that ui is automatically computed if [statusBarBrightness] is set.
bool previousAutomaticSystemUiAdjustment = true;
if (statusBarBrightness != null &&
defaultTargetPlatform == TargetPlatform.iOS) {
defaultTargetPlatform == TargetPlatform.iOS &&
WidgetsBinding.instance != null) {
previousAutomaticSystemUiAdjustment =
WidgetsBinding.instance.renderView.automaticSystemUiAdjustment;
WidgetsBinding.instance.renderView.automaticSystemUiAdjustment = false;
WidgetsBinding.instance!.renderView.automaticSystemUiAdjustment;
WidgetsBinding.instance!.renderView.automaticSystemUiAdjustment = false;
SystemChrome.setSystemUIOverlayStyle(statusBarBrightness == Brightness.light
? SystemUiOverlayStyle.dark
: SystemUiOverlayStyle.light);
}
final bool result = await UrlLauncherPlatform.instance.launch(
urlString,
useSafariVC: forceSafariVC ?? isWebURL,
useWebView: forceWebView ?? false,
enableJavaScript: enableJavaScript ?? false,
enableDomStorage: enableDomStorage ?? false,
universalLinksOnly: universalLinksOnly ?? false,
headers: headers ?? <String, String>{},
useSafariVC: forceSafariVC,
useWebView: forceWebView,
enableJavaScript: enableJavaScript,
enableDomStorage: enableDomStorage,
universalLinksOnly: universalLinksOnly,
headers: headers,
webOnlyWindowName: webOnlyWindowName,
);
assert(previousAutomaticSystemUiAdjustment != null);
if (statusBarBrightness != null) {
WidgetsBinding.instance.renderView.automaticSystemUiAdjustment =
if (statusBarBrightness != null && WidgetsBinding.instance != null) {
WidgetsBinding.instance!.renderView.automaticSystemUiAdjustment =
previousAutomaticSystemUiAdjustment;
}
return result;
}
@ -118,9 +120,6 @@ Future<bool> launch(
/// For more information see the [Managing package visibility](https://developer.android.com/training/basics/intents/package-visibility)
/// article in the Android docs.
Future<bool> canLaunch(String urlString) async {
if (urlString == null) {
return false;
}
return await UrlLauncherPlatform.instance.canLaunch(urlString);
}

View File

@ -2,7 +2,7 @@ name: url_launcher
description: Flutter plugin for launching a URL on Android and iOS. Supports
web, phone, SMS, and email schemes.
homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher
version: 5.7.13
version: 6.0.0-nullsafety.1
flutter:
plugin:
@ -12,8 +12,9 @@ flutter:
pluginClass: UrlLauncherPlugin
ios:
pluginClass: FLTURLLauncherPlugin
web:
default_package: url_launcher_web
# TODO(mvanbeusekom): Temporary disabled until web is migrated to nnbd (advised by @blasten).
#web:
# default_package: url_launcher_web
linux:
default_package: url_laucher_linux
macos:
@ -24,25 +25,26 @@ flutter:
dependencies:
flutter:
sdk: flutter
url_launcher_platform_interface: ^1.0.9
url_launcher_platform_interface: ^2.0.0-nullsafety
# The design on https://flutter.dev/go/federated-plugins was to leave
# this constraint as "any". We cannot do it right now as it fails pub publish
# validation, so we set a ^ constraint.
# TODO(amirh): Revisit this (either update this part in the design or the pub tool).
# https://github.com/flutter/flutter/issues/46264
url_launcher_web: ^0.1.5
url_launcher_linux: ^0.0.1
url_launcher_macos: ^0.0.1
url_launcher_windows: ^0.0.1
url_launcher_linux: ^0.1.0-nullsafety
url_launcher_macos: ^0.1.0-nullsafety
url_launcher_windows: ^0.1.0-nullsafety
# TODO(mvanbeusekom): Temporary disabled until web is migrated to nnbd (advised by @blasten).
#url_launcher_web: ^0.1.3
dev_dependencies:
flutter_test:
sdk: flutter
test: ^1.3.0
test: ^1.10.0-nullsafety.1
mockito: ^4.1.1
plugin_platform_interface: ^1.0.0
pedantic: ^1.8.0
plugin_platform_interface: ^1.1.0-nullsafety.1
pedantic: ^1.10.0-nullsafety.1
environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.12.13+hotfix.5"

View File

@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
// TODO(egarciad): Remove once Mockito has been migrated to null safety.
// @dart = 2.9
import 'dart:ui';
import 'package:flutter/material.dart';

View File

@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
// TODO(mvanbeusekom): Remove once Mockito is migrated to null safety.
// @dart = 2.9
import 'dart:async';
import 'dart:ui';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:flutter/foundation.dart';
@ -41,10 +43,6 @@ void main() {
});
});
group('launch', () {
test('requires a non-null urlString', () {
expect(() => launch(null), throwsAssertionError);
});
test('default behavior', () async {
await launch('http://flutter.dev/');
expect(

View File

@ -1,3 +1,7 @@
## 0.1.0-nullsafety.1
* Migrate to null safety.
## 0.0.2+1
* Update Flutter SDK constraint.

View File

@ -1,6 +1,6 @@
name: url_launcher_linux
description: Linux implementation of the url_launcher plugin.
version: 0.0.2+1
version: 0.1.0-nullsafety.1
homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher_linux
flutter:
@ -10,7 +10,7 @@ flutter:
pluginClass: UrlLauncherPlugin
environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.12.8"
dependencies:

View File

@ -1,3 +1,11 @@
# 0.1.0-nullsafety.1
* Bump SDK to support null safety.
# 0.1.0-nullsafety
* Migrate to null safety.
## 0.0.2+1
* Update Flutter SDK constraint.

View File

@ -3,7 +3,7 @@ description: macOS implementation of the url_launcher plugin.
# 0.0.y+z is compatible with 1.0.0, if you land a breaking change bump
# the version to 2.0.0.
# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
version: 0.0.2+1
version: 0.1.0-nullsafety.1
homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher_macos
flutter:
@ -14,7 +14,7 @@ flutter:
fileName: url_launcher_macos.dart
environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.12.8"
dependencies:

View File

@ -1,3 +1,11 @@
## 2.0.0-nullsafety.1
* Bump Dart SDK to support null safety.
## 2.0.0-nullsafety
* Migrate to null safety.
## 1.0.10
* Update Flutter SDK constraint.

View File

@ -0,0 +1,4 @@
include: ../../../analysis_options.yaml
analyzer:
enable-experiment:
- non-nullable

View File

@ -16,7 +16,7 @@ typedef FollowLink = Future<void> Function();
/// the widget tree under it.
typedef LinkWidgetBuilder = Widget Function(
BuildContext context,
FollowLink followLink,
FollowLink? followLink,
);
/// Signature for a delegate function to build the [Link] widget.
@ -31,7 +31,7 @@ final MethodCodec _codec = const JSONMethodCodec();
class LinkTarget {
/// Const private constructor with a [debugLabel] to allow the creation of
/// multiple distinct const instances.
const LinkTarget._({this.debugLabel});
const LinkTarget._({required this.debugLabel});
/// Used to distinguish multiple const instances of [LinkTarget].
final String debugLabel;
@ -64,7 +64,7 @@ abstract class LinkInfo {
LinkWidgetBuilder get builder;
/// The destination that this link leads to.
Uri get uri;
Uri? get uri;
/// The target indicating where to open the link.
LinkTarget get target;
@ -80,10 +80,14 @@ Future<ByteData> pushRouteNameToFramework(
String routeName, {
@visibleForTesting bool debugForceRouter = false,
}) {
final PlatformMessageCallback? onPlatformMessage = window.onPlatformMessage;
if (onPlatformMessage == null) {
return Future<ByteData>.value(null);
}
final Completer<ByteData> completer = Completer<ByteData>();
if (debugForceRouter || _hasRouter(context)) {
SystemNavigator.routeInformationUpdated(location: routeName);
window.onPlatformMessage(
onPlatformMessage(
'flutter/navigation',
_codec.encodeMethodCall(
MethodCall('pushRouteInformation', <dynamic, dynamic>{
@ -94,7 +98,7 @@ Future<ByteData> pushRouteNameToFramework(
completer.complete,
);
} else {
window.onPlatformMessage(
onPlatformMessage(
'flutter/navigation',
_codec.encodeMethodCall(MethodCall('pushRoute', routeName)),
completer.complete,

View File

@ -5,7 +5,6 @@
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:meta/meta.dart' show required;
import 'link.dart';
import 'url_launcher_platform_interface.dart';
@ -15,14 +14,14 @@ const MethodChannel _channel = MethodChannel('plugins.flutter.io/url_launcher');
/// An implementation of [UrlLauncherPlatform] that uses method channels.
class MethodChannelUrlLauncher extends UrlLauncherPlatform {
@override
final LinkDelegate linkDelegate = null;
final LinkDelegate? linkDelegate = null;
@override
Future<bool> canLaunch(String url) {
return _channel.invokeMethod<bool>(
'canLaunch',
<String, Object>{'url': url},
);
).then((value) => value ?? false);
}
@override
@ -33,13 +32,13 @@ class MethodChannelUrlLauncher extends UrlLauncherPlatform {
@override
Future<bool> launch(
String url, {
@required bool useSafariVC,
@required bool useWebView,
@required bool enableJavaScript,
@required bool enableDomStorage,
@required bool universalLinksOnly,
@required Map<String, String> headers,
String webOnlyWindowName,
required bool useSafariVC,
required bool useWebView,
required bool enableJavaScript,
required bool enableDomStorage,
required bool universalLinksOnly,
required Map<String, String> headers,
String? webOnlyWindowName,
}) {
return _channel.invokeMethod<bool>(
'launch',
@ -52,6 +51,6 @@ class MethodChannelUrlLauncher extends UrlLauncherPlatform {
'universalLinksOnly': universalLinksOnly,
'headers': headers,
},
);
).then((value) => value ?? false);
}
}

View File

@ -4,7 +4,6 @@
import 'dart:async';
import 'package:meta/meta.dart' show required;
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'package:url_launcher_platform_interface/link.dart';
@ -40,7 +39,7 @@ abstract class UrlLauncherPlatform extends PlatformInterface {
}
/// The delegate used by the Link widget to build itself.
LinkDelegate get linkDelegate;
LinkDelegate? get linkDelegate;
/// Returns `true` if this platform is able to launch [url].
Future<bool> canLaunch(String url) {
@ -53,13 +52,13 @@ abstract class UrlLauncherPlatform extends PlatformInterface {
/// in `package:url_launcher/url_launcher.dart`.
Future<bool> launch(
String url, {
@required bool useSafariVC,
@required bool useWebView,
@required bool enableJavaScript,
@required bool enableDomStorage,
@required bool universalLinksOnly,
@required Map<String, String> headers,
String webOnlyWindowName,
required bool useSafariVC,
required bool useWebView,
required bool enableJavaScript,
required bool enableDomStorage,
required bool universalLinksOnly,
required Map<String, String> headers,
String? webOnlyWindowName,
}) {
throw UnimplementedError('launch() has not been implemented.');
}

View File

@ -3,20 +3,19 @@ description: A common platform interface for the url_launcher plugin.
homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher_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.10
version: 2.0.0-nullsafety.1
dependencies:
flutter:
sdk: flutter
meta: ^1.0.5
plugin_platform_interface: ^1.0.1
plugin_platform_interface: ^1.1.0-nullsafety.1
dev_dependencies:
flutter_test:
sdk: flutter
mockito: ^4.1.1
pedantic: ^1.8.0
pedantic: ^1.10.0-nullsafety.1
environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.22.0"

View File

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(egarciad): Remove once Mockito has been migrated to null safety.
// @dart = 2.9
import 'dart:ui';
import 'package:mockito/mockito.dart';

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(mvanbeusekom): Remove once Mockito is migrated to null safety.
// @dart = 2.9
import 'package:mockito/mockito.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
@ -42,6 +44,10 @@ void main() {
final List<MethodCall> log = <MethodCall>[];
channel.setMockMethodCallHandler((MethodCall methodCall) async {
log.add(methodCall);
// Return null explicitly instead of relying on the implicit null
// returned by the method channel if no return statement is specified.
return null;
});
final MethodChannelUrlLauncher launcher = MethodChannelUrlLauncher();
@ -62,6 +68,12 @@ void main() {
);
});
test('canLaunch should return false if platform returns null', () async {
final canLaunch = await launcher.canLaunch('http://example.com/');
expect(canLaunch, false);
});
test('launch', () async {
await launcher.launch(
'http://example.com/',
@ -270,6 +282,20 @@ void main() {
);
});
test('launch should return false if platform returns null', () async {
final launched = await launcher.launch(
'http://example.com/',
useSafariVC: true,
useWebView: false,
enableJavaScript: false,
enableDomStorage: false,
universalLinksOnly: false,
headers: const <String, String>{},
);
expect(launched, false);
});
test('closeWebView default behavior', () async {
await launcher.closeWebView();
expect(

View File

@ -15,6 +15,12 @@ flutter:
dependencies:
url_launcher_platform_interface: ^1.0.9
# TODO(mvanbeusekom): Update to use pub.dev once null safety version is published.
# url_launcher_platform_interface:
# git:
# url: https://github.com/flutter/plugins.git
# ref: nnbd
# path: packages/url_launcher/url_launcher_platform_interface
flutter:
sdk: flutter
flutter_web_plugins:
@ -25,6 +31,9 @@ dev_dependencies:
flutter_test:
sdk: flutter
url_launcher: ^5.2.5
# TODO(mvanbeusekom): Update to use pub.dev once null safety version is published.
# url_launcher:
# path: ../url_launcher
pedantic: ^1.8.0
mockito: ^4.1.1
integration_test:

View File

@ -2,7 +2,7 @@ name: regular_integration_tests
publish_to: none
environment:
sdk: ">=2.2.2 <3.0.0"
sdk: ">=2.10.0-56.0.dev <3.0.0"
dependencies:
flutter:

View File

@ -1,3 +1,11 @@
## 0.1.0-nullsafety.1
* Bump Dart SDK to support null safety.
## 0.1.0-nullsafety
* Migrate to null-safety.
## 0.0.2+1
* Update Flutter SDK constraint.

View File

@ -3,7 +3,7 @@ description: Windows implementation of the url_launcher plugin.
# 0.0.y+z is compatible with 1.0.0, if you land a breaking change bump
# the version to 2.0.0.
# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
version: 0.0.2+1
version: 0.1.0-nullsafety.1
homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher_windows
flutter:
@ -13,7 +13,7 @@ flutter:
pluginClass: UrlLauncherPlugin
environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.12.8"
dependencies:

View File

@ -1,3 +1,19 @@
## 2.0.0-nullsafety.3
* Dart null safety requires `2.12`.
## 2.0.0-nullsafety.2
* Bump SDK version.
## 2.0.0-nullsafety.1
* Merge master.
## 2.0.0-nullsafety
* Migration to null safety.
## 1.0.2
* Update Flutter SDK constraint.

View File

@ -0,0 +1,4 @@
include: ../../../analysis_options.yaml
analyzer:
enable-experiment:
- non-nullable

View File

@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v0.1.7), do not edit directly.
// Autogenerated from Pigeon (v0.1.12), do not edit directly.
// See also: https://pub.dev/packages/pigeon
package io.flutter.plugins.videoplayer;
@ -597,7 +597,7 @@ public class Messages {
private static HashMap wrapError(Exception exception) {
HashMap<String, Object> errorMap = new HashMap<>();
errorMap.put("message", exception.toString());
errorMap.put("code", null);
errorMap.put("code", exception.getClass().getSimpleName());
errorMap.put("details", null);
return errorMap;
}

View File

@ -11,7 +11,7 @@ const Duration _playDuration = Duration(seconds: 1);
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
VideoPlayerController _controller;
late VideoPlayerController _controller;
tearDown(() async => _controller.dispose());
group('asset videos', () {
@ -22,7 +22,7 @@ void main() {
testWidgets('can be initialized', (WidgetTester tester) async {
await _controller.initialize();
expect(_controller.value.initialized, true);
expect(_controller.value.isInitialized, true);
expect(_controller.value.position, const Duration(seconds: 0));
expect(_controller.value.isPlaying, false);
expect(_controller.value.duration,

View File

@ -108,7 +108,7 @@ class _ButterFlyAssetVideoInList extends StatelessWidget {
/// A filler card to show the video in a list of scrolling contents.
class _ExampleCard extends StatelessWidget {
const _ExampleCard({Key key, this.title}) : super(key: key);
const _ExampleCard({Key? key, required this.title}) : super(key: key);
final String title;
@ -150,7 +150,7 @@ class _ButterFlyAssetVideo extends StatefulWidget {
}
class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> {
VideoPlayerController _controller;
late VideoPlayerController _controller;
@override
void initState() {
@ -206,7 +206,7 @@ class _BumbleBeeRemoteVideo extends StatefulWidget {
}
class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> {
VideoPlayerController _controller;
late VideoPlayerController _controller;
Future<ClosedCaptionFile> _loadCaptions() async {
final String fileContents = await DefaultAssetBundle.of(context)
@ -265,7 +265,8 @@ class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> {
}
class _ControlsOverlay extends StatelessWidget {
const _ControlsOverlay({Key key, this.controller}) : super(key: key);
const _ControlsOverlay({Key? key, required this.controller})
: super(key: key);
static const _examplePlaybackRates = [
0.25,
@ -345,7 +346,7 @@ class _PlayerVideoAndPopPage extends StatefulWidget {
}
class _PlayerVideoAndPopPageState extends State<_PlayerVideoAndPopPage> {
VideoPlayerController _videoPlayerController;
late VideoPlayerController _videoPlayerController;
bool startedPlaying = false;
@override

View File

@ -16,7 +16,8 @@ dev_dependencies:
sdk: flutter
integration_test:
path: ../../../integration_test
pedantic: ^1.8.0
test: any
pedantic: ^1.10.0-nullsafety.1
flutter:
uses-material-design: true

View File

@ -2,6 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(egarciad): Remove once Flutter driver is migrated to null safety.
// @dart = 2.9
import 'dart:async';
import 'dart:convert';
import 'dart:io';

View File

@ -0,0 +1,14 @@
// Copyright 2019, the Chromium project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(egarciad): Remove once Flutter driver is migrated to null safety.
// @dart = 2.9
import 'package:flutter_driver/driver_extension.dart';
import 'package:video_player_example/main.dart' as app;
void main() {
enableFlutterDriverExtension();
app.main();
}

View File

@ -0,0 +1,30 @@
// Copyright 2019, the Chromium project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(egarciad): Remove once Flutter driver is migrated to null safety.
// @dart = 2.9
import 'dart:async';
import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart';
Future<void> main() async {
final FlutterDriver driver = await FlutterDriver.connect();
tearDownAll(() async {
await driver.close();
});
//TODO(cyanglaz): Use TabBar tabs to navigate between pages after https://github.com/flutter/flutter/issues/16991 is fixed.
//TODO(cyanglaz): Un-skip the test after https://github.com/flutter/flutter/issues/43012 is fixed
test('Push a page contains video and pop back, do not crash.', () async {
final SerializableFinder pushTab = find.byValueKey('push_tab');
await driver.waitFor(pushTab);
await driver.tap(pushTab);
await driver.waitForAbsent(pushTab);
await driver.waitFor(find.byValueKey('home_page'));
await driver.waitUntilNoTransientCallbacks();
final Health health = await driver.checkHealth();
expect(health.status, HealthStatus.ok);
}, skip: 'Cirrus CI currently hangs while playing videos');
}

View File

@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v0.1.7), do not edit directly.
// Autogenerated from Pigeon (v0.1.12), do not edit directly.
// See also: https://pub.dev/packages/pigeon
#import <Foundation/Foundation.h>
@protocol FlutterBinaryMessenger;

View File

@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v0.1.7), do not edit directly.
// Autogenerated from Pigeon (v0.1.12), do not edit directly.
// See also: https://pub.dev/packages/pigeon
#import "messages.h"
#import <Flutter/Flutter.h>
@ -7,6 +7,7 @@
#error File requires ARC to be enabled.
#endif
#ifndef __clang_analyzer__
static NSDictionary *wrapResult(NSDictionary *result, FlutterError *error) {
NSDictionary *errorDict = (NSDictionary *)[NSNull null];
if (error) {
@ -59,8 +60,8 @@ static NSDictionary *wrapResult(NSDictionary *result, FlutterError *error) {
return result;
}
- (NSDictionary *)toMap {
return [NSDictionary
dictionaryWithObjectsAndKeys:(self.textureId != nil ? self.textureId : [NSNull null]),
return
[NSDictionary dictionaryWithObjectsAndKeys:(self.textureId ? self.textureId : [NSNull null]),
@"textureId", nil];
}
@end
@ -112,10 +113,9 @@ static NSDictionary *wrapResult(NSDictionary *result, FlutterError *error) {
}
- (NSDictionary *)toMap {
return [NSDictionary
dictionaryWithObjectsAndKeys:(self.textureId != nil ? self.textureId : [NSNull null]),
@"textureId",
(self.isLooping != nil ? self.isLooping : [NSNull null]),
@"isLooping", nil];
dictionaryWithObjectsAndKeys:(self.textureId ? self.textureId : [NSNull null]), @"textureId",
(self.isLooping ? self.isLooping : [NSNull null]), @"isLooping",
nil];
}
@end
@ -134,9 +134,8 @@ static NSDictionary *wrapResult(NSDictionary *result, FlutterError *error) {
}
- (NSDictionary *)toMap {
return [NSDictionary
dictionaryWithObjectsAndKeys:(self.textureId != nil ? self.textureId : [NSNull null]),
@"textureId", (self.volume != nil ? self.volume : [NSNull null]),
@"volume", nil];
dictionaryWithObjectsAndKeys:(self.textureId ? self.textureId : [NSNull null]), @"textureId",
(self.volume ? self.volume : [NSNull null]), @"volume", nil];
}
@end
@ -155,9 +154,8 @@ static NSDictionary *wrapResult(NSDictionary *result, FlutterError *error) {
}
- (NSDictionary *)toMap {
return [NSDictionary
dictionaryWithObjectsAndKeys:(self.textureId != nil ? self.textureId : [NSNull null]),
@"textureId", (self.speed != nil ? self.speed : [NSNull null]),
@"speed", nil];
dictionaryWithObjectsAndKeys:(self.textureId ? self.textureId : [NSNull null]), @"textureId",
(self.speed ? self.speed : [NSNull null]), @"speed", nil];
}
@end
@ -176,10 +174,9 @@ static NSDictionary *wrapResult(NSDictionary *result, FlutterError *error) {
}
- (NSDictionary *)toMap {
return [NSDictionary
dictionaryWithObjectsAndKeys:(self.textureId != nil ? self.textureId : [NSNull null]),
@"textureId",
(self.position != nil ? self.position : [NSNull null]),
@"position", nil];
dictionaryWithObjectsAndKeys:(self.textureId ? self.textureId : [NSNull null]), @"textureId",
(self.position ? self.position : [NSNull null]), @"position",
nil];
}
@end
@ -194,7 +191,7 @@ static NSDictionary *wrapResult(NSDictionary *result, FlutterError *error) {
}
- (NSDictionary *)toMap {
return [NSDictionary
dictionaryWithObjectsAndKeys:(self.mixWithOthers != nil ? self.mixWithOthers : [NSNull null]),
dictionaryWithObjectsAndKeys:(self.mixWithOthers ? self.mixWithOthers : [NSNull null]),
@"mixWithOthers", nil];
}
@end
@ -365,3 +362,4 @@ void FLTVideoPlayerApiSetup(id<FlutterBinaryMessenger> binaryMessenger, id<FLTVi
}
}
}
#endif

View File

@ -31,7 +31,11 @@ class Caption {
///
/// This is not recommended for direct use unless you are writing a parser for
/// a new closed captioning file type.
const Caption({this.number, this.start, this.end, this.text});
const Caption(
{required this.number,
required this.start,
required this.end,
required this.text});
/// The number that this caption was assigned.
final int number;
@ -46,6 +50,11 @@ class Caption {
/// and [end].
final String text;
/// A no caption object. This is a caption with [start] and [end] durations of zero,
/// and an empty [text] string.
static const Caption none =
Caption(number: 0, start: Duration.zero, end: Duration.zero, text: '');
@override
String toString() {
return '$runtimeType('

View File

@ -41,8 +41,7 @@ List<Caption> _parseCaptionsFromSubRipString(String file) {
end: startAndEnd.end,
text: text,
);
if (newCaption.start != null && newCaption.end != null) {
if (newCaption.start != newCaption.end) {
captions.add(newCaption);
}
}
@ -64,7 +63,7 @@ class _StartAndEnd {
RegExp(_subRipTimeStamp + _subRipArrow + _subRipTimeStamp);
if (!format.hasMatch(line)) {
return _StartAndEnd(null, null);
return _StartAndEnd(Duration.zero, Duration.zero);
}
final List<String> times = line.split(_subRipArrow);
@ -84,7 +83,7 @@ class _StartAndEnd {
// Duration(hours: 0, minutes: 1, seconds: 59, milliseconds: 084)
Duration _parseSubRipTimestamp(String timestampString) {
if (!RegExp(_subRipTimeStamp).hasMatch(timestampString)) {
return null;
return Duration.zero;
}
final List<String> commaSections = timestampString.split(',');

View File

@ -28,11 +28,12 @@ class VideoPlayerValue {
/// Constructs a video with the given values. Only [duration] is required. The
/// rest will initialize with default values when unset.
VideoPlayerValue({
@required this.duration,
this.size,
this.position = const Duration(),
this.caption = const Caption(),
required this.duration,
this.size = Size.zero,
this.position = Duration.zero,
this.caption = Caption.none,
this.buffered = const <DurationRange>[],
this.isInitialized = false,
this.isPlaying = false,
this.isLooping = false,
this.isBuffering = false,
@ -41,17 +42,20 @@ class VideoPlayerValue {
this.errorDescription,
});
/// Returns an instance with a `null` [Duration].
VideoPlayerValue.uninitialized() : this(duration: null);
/// Returns an instance for a video that hasn't been loaded.
VideoPlayerValue.uninitialized()
: this(duration: Duration.zero, isInitialized: false);
/// Returns an instance with a `null` [Duration] and the given
/// [errorDescription].
/// Returns an instance with the given [errorDescription].
VideoPlayerValue.erroneous(String errorDescription)
: this(duration: null, errorDescription: errorDescription);
: this(
duration: Duration.zero,
isInitialized: false,
errorDescription: errorDescription);
/// The total duration of the video.
///
/// Is null when [initialized] is false.
/// The duration is [Duration.zero] if the video hasn't been initialized.
final Duration duration;
/// The current playback position.
@ -60,7 +64,7 @@ class VideoPlayerValue {
/// The [Caption] that should be displayed based on the current [position].
///
/// This field will never be null. If there is no caption for the current
/// [position], this will be an empty [Caption] object.
/// [position], this will be a [Caption.none] object.
final Caption caption;
/// The currently buffered ranges.
@ -84,7 +88,7 @@ class VideoPlayerValue {
/// A description of the error if present.
///
/// If [hasError] is false this is [null].
final String errorDescription;
final String? errorDescription;
/// The [size] of the currently loaded video.
///
@ -92,7 +96,7 @@ class VideoPlayerValue {
final Size size;
/// Indicates whether or not the video has been loaded and is ready to play.
bool get initialized => duration != null;
final bool isInitialized;
/// Indicates whether or not the video is in an error state. If this is true
/// [errorDescription] should have information about the problem.
@ -101,7 +105,7 @@ class VideoPlayerValue {
/// Returns [size.width] / [size.height] when size is non-null, or `1.0.` when
/// size is null or the aspect ratio would be less than or equal to 0.0.
double get aspectRatio {
if (size == null || size.width == 0 || size.height == 0) {
if (!isInitialized || size.width == 0 || size.height == 0) {
return 1.0;
}
final double aspectRatio = size.width / size.height;
@ -114,17 +118,18 @@ class VideoPlayerValue {
/// Returns a new instance that has the same values as this current instance,
/// except for any overrides passed in as arguments to [copyWidth].
VideoPlayerValue copyWith({
Duration duration,
Size size,
Duration position,
Caption caption,
List<DurationRange> buffered,
bool isPlaying,
bool isLooping,
bool isBuffering,
double volume,
double playbackSpeed,
String errorDescription,
Duration? duration,
Size? size,
Duration? position,
Caption? caption,
List<DurationRange>? buffered,
bool? isInitialized,
bool? isPlaying,
bool? isLooping,
bool? isBuffering,
double? volume,
double? playbackSpeed,
String? errorDescription,
}) {
return VideoPlayerValue(
duration: duration ?? this.duration,
@ -132,6 +137,7 @@ class VideoPlayerValue {
position: position ?? this.position,
caption: caption ?? this.caption,
buffered: buffered ?? this.buffered,
isInitialized: isInitialized ?? this.isInitialized,
isPlaying: isPlaying ?? this.isPlaying,
isLooping: isLooping ?? this.isLooping,
isBuffering: isBuffering ?? this.isBuffering,
@ -149,6 +155,7 @@ class VideoPlayerValue {
'position: $position, '
'caption: $caption, '
'buffered: [${buffered.join(', ')}], '
'isInitialized: $isInitialized, '
'isPlaying: $isPlaying, '
'isLooping: $isLooping, '
'isBuffering: $isBuffering, '
@ -178,7 +185,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
{this.package, this.closedCaptionFile, this.videoPlayerOptions})
: dataSourceType = DataSourceType.asset,
formatHint = null,
super(VideoPlayerValue(duration: null));
super(VideoPlayerValue(duration: Duration.zero));
/// Constructs a [VideoPlayerController] playing a video from obtained from
/// the network.
@ -191,7 +198,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
{this.formatHint, this.closedCaptionFile, this.videoPlayerOptions})
: dataSourceType = DataSourceType.network,
package = null,
super(VideoPlayerValue(duration: null));
super(VideoPlayerValue(duration: Duration.zero));
/// Constructs a [VideoPlayerController] playing a video from a file.
///
@ -203,9 +210,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
dataSourceType = DataSourceType.file,
package = null,
formatHint = null,
super(VideoPlayerValue(duration: null));
int _textureId;
super(VideoPlayerValue(duration: Duration.zero));
/// The URI to the video file. This will be in different formats depending on
/// the [DataSourceType] of the original video.
@ -213,31 +218,36 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
/// **Android only**. Will override the platform's generic file format
/// detection with whatever is set here.
final VideoFormat formatHint;
final VideoFormat? formatHint;
/// Describes the type of data source this [VideoPlayerController]
/// is constructed with.
final DataSourceType dataSourceType;
/// Provide additional configuration options (optional). Like setting the audio mode to mix
final VideoPlayerOptions videoPlayerOptions;
final VideoPlayerOptions? videoPlayerOptions;
/// Only set for [asset] videos. The package that the asset was loaded from.
final String package;
final String? package;
/// Optional field to specify a file containing the closed
/// captioning.
///
/// This future will be awaited and the file will be loaded when
/// [initialize()] is called.
final Future<ClosedCaptionFile> closedCaptionFile;
final Future<ClosedCaptionFile>? closedCaptionFile;
ClosedCaptionFile _closedCaptionFile;
Timer _timer;
ClosedCaptionFile? _closedCaptionFile;
Timer? _timer;
bool _isDisposed = false;
Completer<void> _creatingCompleter;
StreamSubscription<dynamic> _eventSubscription;
_VideoAppLifeCycleObserver _lifeCycleObserver;
Completer<void>? _creatingCompleter;
StreamSubscription<dynamic>? _eventSubscription;
late _VideoAppLifeCycleObserver _lifeCycleObserver;
/// The id of a texture that hasn't been initialized.
@visibleForTesting
static const int kUninitializedTextureId = -1;
int _textureId = kUninitializedTextureId;
/// This is just exposed for testing. It shouldn't be used by anyone depending
/// on the plugin.
@ -250,7 +260,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
_lifeCycleObserver.initialize();
_creatingCompleter = Completer<void>();
DataSource dataSourceDescription;
late DataSource dataSourceDescription;
switch (dataSourceType) {
case DataSourceType.asset:
dataSourceDescription = DataSource(
@ -276,11 +286,12 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
if (videoPlayerOptions?.mixWithOthers != null) {
await _videoPlayerPlatform
.setMixWithOthers(videoPlayerOptions.mixWithOthers);
.setMixWithOthers(videoPlayerOptions!.mixWithOthers);
}
_textureId = await _videoPlayerPlatform.create(dataSourceDescription);
_creatingCompleter.complete(null);
_textureId = (await _videoPlayerPlatform.create(dataSourceDescription)) ??
kUninitializedTextureId;
_creatingCompleter!.complete(null);
final Completer<void> initializingCompleter = Completer<void>();
void eventListener(VideoEvent event) {
@ -293,6 +304,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
value = value.copyWith(
duration: event.duration,
size: event.size,
isInitialized: event.duration != null,
);
initializingCompleter.complete(null);
_applyLooping();
@ -325,8 +337,8 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
}
void errorListener(Object obj) {
final PlatformException e = obj;
value = VideoPlayerValue.erroneous(e.message);
final PlatformException e = obj as PlatformException;
value = VideoPlayerValue.erroneous(e.message!);
_timer?.cancel();
if (!initializingCompleter.isCompleted) {
initializingCompleter.completeError(obj);
@ -342,7 +354,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
@override
Future<void> dispose() async {
if (_creatingCompleter != null) {
await _creatingCompleter.future;
await _creatingCompleter!.future;
if (!_isDisposed) {
_isDisposed = true;
_timer?.cancel();
@ -379,14 +391,14 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
}
Future<void> _applyLooping() async {
if (!value.initialized || _isDisposed) {
if (!value.isInitialized || _isDisposed) {
return;
}
await _videoPlayerPlatform.setLooping(_textureId, value.isLooping);
}
Future<void> _applyPlayPause() async {
if (!value.initialized || _isDisposed) {
if (!value.isInitialized || _isDisposed) {
return;
}
if (value.isPlaying) {
@ -400,8 +412,8 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
if (_isDisposed) {
return;
}
final Duration newPosition = await position;
if (_isDisposed) {
final Duration? newPosition = await position;
if (newPosition == null) {
return;
}
_updatePosition(newPosition);
@ -419,14 +431,14 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
}
Future<void> _applyVolume() async {
if (!value.initialized || _isDisposed) {
if (!value.isInitialized || _isDisposed) {
return;
}
await _videoPlayerPlatform.setVolume(_textureId, value.volume);
}
Future<void> _applyPlaybackSpeed() async {
if (!value.initialized || _isDisposed) {
if (!value.isInitialized || _isDisposed) {
return;
}
@ -442,7 +454,7 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
}
/// The position in the current video.
Future<Duration> get position async {
Future<Duration?> get position async {
if (_isDisposed) {
return null;
}
@ -519,17 +531,17 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
/// [Caption].
Caption _getCaptionAt(Duration position) {
if (_closedCaptionFile == null) {
return Caption();
return Caption.none;
}
// TODO: This would be more efficient as a binary search.
for (final caption in _closedCaptionFile.captions) {
for (final caption in _closedCaptionFile!.captions) {
if (caption.start <= position && caption.end >= position) {
return caption;
}
}
return Caption();
return Caption.none;
}
void _updatePosition(Duration position) {
@ -545,7 +557,7 @@ class _VideoAppLifeCycleObserver extends Object with WidgetsBindingObserver {
final VideoPlayerController _controller;
void initialize() {
WidgetsBinding.instance.addObserver(this);
WidgetsBinding.instance!.addObserver(this);
}
@override
@ -565,7 +577,7 @@ class _VideoAppLifeCycleObserver extends Object with WidgetsBindingObserver {
}
void dispose() {
WidgetsBinding.instance.removeObserver(this);
WidgetsBinding.instance!.removeObserver(this);
}
}
@ -594,8 +606,9 @@ class _VideoPlayerState extends State<VideoPlayer> {
};
}
VoidCallback _listener;
int _textureId;
late VoidCallback _listener;
late int _textureId;
@override
void initState() {
@ -622,7 +635,7 @@ class _VideoPlayerState extends State<VideoPlayer> {
@override
Widget build(BuildContext context) {
return _textureId == null
return _textureId == VideoPlayerController.kUninitializedTextureId
? Container()
: _videoPlayerPlatform.buildView(_textureId);
}
@ -646,7 +659,7 @@ class VideoProgressColors {
/// [backgroundColor] defaults to gray at 50% opacity. This is the background
/// color behind both [playedColor] and [bufferedColor] to denote the total
/// size of the video compared to either of those values.
VideoProgressColors({
const VideoProgressColors({
this.playedColor = const Color.fromRGBO(255, 0, 0, 0.7),
this.bufferedColor = const Color.fromRGBO(50, 50, 200, 0.2),
this.backgroundColor = const Color.fromRGBO(200, 200, 200, 0.5),
@ -670,8 +683,8 @@ class VideoProgressColors {
class _VideoScrubber extends StatefulWidget {
_VideoScrubber({
@required this.child,
@required this.controller,
required this.child,
required this.controller,
});
final Widget child;
@ -689,7 +702,7 @@ class _VideoScrubberState extends State<_VideoScrubber> {
@override
Widget build(BuildContext context) {
void seekToRelativePosition(Offset globalPosition) {
final RenderBox box = context.findRenderObject();
final RenderBox box = context.findRenderObject() as RenderBox;
final Offset tapPos = box.globalToLocal(globalPosition);
final double relative = tapPos.dx / box.size.width;
final Duration position = controller.value.duration * relative;
@ -700,7 +713,7 @@ class _VideoScrubberState extends State<_VideoScrubber> {
behavior: HitTestBehavior.opaque,
child: widget.child,
onHorizontalDragStart: (DragStartDetails details) {
if (!controller.value.initialized) {
if (!controller.value.isInitialized) {
return;
}
_controllerWasPlaying = controller.value.isPlaying;
@ -709,7 +722,7 @@ class _VideoScrubberState extends State<_VideoScrubber> {
}
},
onHorizontalDragUpdate: (DragUpdateDetails details) {
if (!controller.value.initialized) {
if (!controller.value.isInitialized) {
return;
}
seekToRelativePosition(details.globalPosition);
@ -720,7 +733,7 @@ class _VideoScrubberState extends State<_VideoScrubber> {
}
},
onTapDown: (TapDownDetails details) {
if (!controller.value.initialized) {
if (!controller.value.isInitialized) {
return;
}
seekToRelativePosition(details.globalPosition);
@ -745,10 +758,10 @@ class VideoProgressIndicator extends StatefulWidget {
/// to `top: 5.0`.
VideoProgressIndicator(
this.controller, {
VideoProgressColors colors,
this.allowScrubbing,
this.colors = const VideoProgressColors(),
required this.allowScrubbing,
this.padding = const EdgeInsets.only(top: 5.0),
}) : colors = colors ?? VideoProgressColors();
});
/// The [VideoPlayerController] that actually associates a video with this
/// widget.
@ -785,7 +798,7 @@ class _VideoProgressIndicatorState extends State<VideoProgressIndicator> {
};
}
VoidCallback listener;
late VoidCallback listener;
VideoPlayerController get controller => widget.controller;
@ -806,7 +819,7 @@ class _VideoProgressIndicatorState extends State<VideoProgressIndicator> {
@override
Widget build(BuildContext context) {
Widget progressIndicator;
if (controller.value.initialized) {
if (controller.value.isInitialized) {
final int duration = controller.value.duration.inMilliseconds;
final int position = controller.value.position.inMilliseconds;
@ -878,17 +891,17 @@ class ClosedCaption extends StatelessWidget {
/// [VideoPlayerValue.caption].
///
/// If [text] is null, nothing will be displayed.
const ClosedCaption({Key key, this.text, this.textStyle}) : super(key: key);
const ClosedCaption({Key? key, this.text, this.textStyle}) : super(key: key);
/// The text that will be shown in the closed caption, or null if no caption
/// should be shown.
final String text;
final String? text;
/// Specifies how the text in the closed caption should look.
///
/// If null, defaults to [DefaultTextStyle.of(context).style] with size 36
/// font colored white.
final TextStyle textStyle;
final TextStyle? textStyle;
@override
Widget build(BuildContext context) {
@ -913,7 +926,7 @@ class ClosedCaption extends StatelessWidget {
),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 2.0),
child: Text(text, style: effectiveTextStyle),
child: Text(text!, style: effectiveTextStyle),
),
),
),

View File

@ -1,3 +1,5 @@
// @dart = 2.9
import 'package:pigeon/pigeon_lib.dart';
class TextureMessage {

View File

@ -1,7 +1,10 @@
name: video_player
description: Flutter plugin for displaying inline video with other Flutter
widgets on Android, iOS, and web.
version: 1.0.2
# 0.10.y+z is compatible with 1.0.0, if you land a breaking change bump
# the version to 2.0.0.
# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
version: 2.0.0-nullsafety.3
homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player
flutter:
@ -16,15 +19,15 @@ flutter:
default_package: video_player_web
dependencies:
meta: ^1.0.5
video_player_platform_interface: ^2.2.0
meta: ^1.3.0-nullsafety.3
video_player_platform_interface: ^3.0.0-nullsafety.3
# The design on https://flutter.dev/go/federated-plugins was to leave
# this constraint as "any". We cannot do it right now as it fails pub publish
# validation, so we set a ^ constraint.
# TODO(amirh): Revisit this (either update this part in the design or the pub tool).
# https://github.com/flutter/flutter/issues/46264
video_player_web: ">=0.1.4 <2.0.0"
video_player_web: ^2.0.0-nullsafety.1
flutter:
sdk: flutter
@ -32,9 +35,9 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
pedantic: ^1.8.0
pedantic: ^1.10.0-nullsafety.1
pigeon: 0.1.7
environment:
sdk: ">=2.8.0 <3.0.0"
sdk: ">=2.12.0-0 <3.0.0"
flutter: ">=1.12.13+hotfix.5"

View File

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:video_player/video_player.dart';

View File

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'dart:io';
@ -18,7 +16,7 @@ import 'package:video_player_platform_interface/video_player_platform_interface.
class FakeController extends ValueNotifier<VideoPlayerValue>
implements VideoPlayerController {
FakeController() : super(VideoPlayerValue(duration: null));
FakeController() : super(VideoPlayerValue(duration: Duration.zero));
@override
Future<void> dispose() async {
@ -26,7 +24,7 @@ class FakeController extends ValueNotifier<VideoPlayerValue>
}
@override
int textureId;
int textureId = VideoPlayerController.kUninitializedTextureId;
@override
String get dataSource => '';
@ -35,7 +33,7 @@ class FakeController extends ValueNotifier<VideoPlayerValue>
DataSourceType get dataSourceType => DataSourceType.file;
@override
String get package => null;
String get package => '';
@override
Future<Duration> get position async => value.position;
@ -62,13 +60,13 @@ class FakeController extends ValueNotifier<VideoPlayerValue>
Future<void> setLooping(bool looping) async {}
@override
VideoFormat get formatHint => null;
VideoFormat? get formatHint => null;
@override
Future<ClosedCaptionFile> get closedCaptionFile => _loadClosedCaption();
@override
VideoPlayerOptions get videoPlayerOptions => null;
VideoPlayerOptions? get videoPlayerOptions => null;
}
Future<ClosedCaptionFile> _loadClosedCaption() async =>
@ -80,11 +78,13 @@ class _FakeClosedCaptionFile extends ClosedCaptionFile {
return <Caption>[
Caption(
text: 'one',
number: 0,
start: Duration(milliseconds: 100),
end: Duration(milliseconds: 200),
),
Caption(
text: 'two',
number: 1,
start: Duration(milliseconds: 300),
end: Duration(milliseconds: 400),
),
@ -101,6 +101,7 @@ void main() {
controller.textureId = 123;
controller.value = controller.value.copyWith(
duration: const Duration(milliseconds: 100),
isInitialized: true,
);
await tester.pump();
@ -133,8 +134,8 @@ void main() {
await tester.pumpWidget(MaterialApp(home: ClosedCaption(text: text)));
final Text textWidget = tester.widget<Text>(find.text(text));
expect(textWidget.style.fontSize, 36.0);
expect(textWidget.style.color, Colors.white);
expect(textWidget.style!.fontSize, 36.0);
expect(textWidget.style!.color, Colors.white);
});
testWidgets('uses given text and style', (WidgetTester tester) async {
@ -149,7 +150,7 @@ void main() {
expect(find.text(text), findsOneWidget);
final Text textWidget = tester.widget<Text>(find.text(text));
expect(textWidget.style.fontSize, textStyle.fontSize);
expect(textWidget.style!.fontSize, textStyle.fontSize);
});
testWidgets('handles null text', (WidgetTester tester) async {
@ -173,7 +174,7 @@ void main() {
});
group('VideoPlayerController', () {
FakeVideoPlayerPlatform fakeVideoPlayerPlatform;
late FakeVideoPlayerPlatform fakeVideoPlayerPlatform;
setUp(() {
fakeVideoPlayerPlatform = FakeVideoPlayerPlatform();
@ -221,7 +222,7 @@ void main() {
'http://testing.com/invalid_url',
);
try {
dynamic error;
late dynamic error;
fakeVideoPlayerPlatform.forceInitError = true;
await controller.initialize().catchError((dynamic e) => error = e);
final PlatformException platformEx = error;
@ -245,13 +246,14 @@ void main() {
final VideoPlayerController controller = VideoPlayerController.network(
'https://127.0.0.1',
);
expect(controller.textureId, isNull);
expect(
controller.textureId, VideoPlayerController.kUninitializedTextureId);
expect(await controller.position, const Duration(seconds: 0));
await controller.initialize();
await controller.dispose();
expect(controller.textureId, isNotNull);
expect(controller.textureId, 0);
expect(await controller.position, isNull);
});
@ -390,19 +392,19 @@ void main() {
await controller.initialize();
expect(controller.value.position, const Duration());
expect(controller.value.caption.text, isNull);
expect(controller.value.caption.text, '');
await controller.seekTo(const Duration(milliseconds: 100));
expect(controller.value.caption.text, 'one');
await controller.seekTo(const Duration(milliseconds: 250));
expect(controller.value.caption.text, isNull);
expect(controller.value.caption.text, '');
await controller.seekTo(const Duration(milliseconds: 300));
expect(controller.value.caption.text, 'two');
await controller.seekTo(const Duration(milliseconds: 500));
expect(controller.value.caption.text, isNull);
expect(controller.value.caption.text, '');
await controller.seekTo(const Duration(milliseconds: 300));
expect(controller.value.caption.text, 'two');
@ -419,8 +421,7 @@ void main() {
await controller.play();
expect(controller.value.isPlaying, isTrue);
final FakeVideoEventStream fakeVideoEventStream =
fakeVideoPlayerPlatform.streams[controller.textureId];
assert(fakeVideoEventStream != null);
fakeVideoPlayerPlatform.streams[controller.textureId]!;
fakeVideoEventStream.eventsChannel
.sendEvent(<String, dynamic>{'event': 'completed'});
@ -438,8 +439,7 @@ void main() {
expect(controller.value.isBuffering, false);
expect(controller.value.buffered, isEmpty);
final FakeVideoEventStream fakeVideoEventStream =
fakeVideoPlayerPlatform.streams[controller.textureId];
assert(fakeVideoEventStream != null);
fakeVideoPlayerPlatform.streams[controller.textureId]!;
fakeVideoEventStream.eventsChannel
.sendEvent(<String, dynamic>{'event': 'bufferingStart'});
@ -496,9 +496,9 @@ void main() {
test('uninitialized()', () {
final VideoPlayerValue uninitialized = VideoPlayerValue.uninitialized();
expect(uninitialized.duration, isNull);
expect(uninitialized.position, equals(const Duration(seconds: 0)));
expect(uninitialized.caption, equals(const Caption()));
expect(uninitialized.duration, equals(Duration.zero));
expect(uninitialized.position, equals(Duration.zero));
expect(uninitialized.caption, equals(Caption.none));
expect(uninitialized.buffered, isEmpty);
expect(uninitialized.isPlaying, isFalse);
expect(uninitialized.isLooping, isFalse);
@ -506,9 +506,8 @@ void main() {
expect(uninitialized.volume, 1.0);
expect(uninitialized.playbackSpeed, 1.0);
expect(uninitialized.errorDescription, isNull);
expect(uninitialized.size, isNull);
expect(uninitialized.size, isNull);
expect(uninitialized.initialized, isFalse);
expect(uninitialized.size, equals(Size.zero));
expect(uninitialized.isInitialized, isFalse);
expect(uninitialized.hasError, isFalse);
expect(uninitialized.aspectRatio, 1.0);
});
@ -517,9 +516,9 @@ void main() {
const String errorMessage = 'foo';
final VideoPlayerValue error = VideoPlayerValue.erroneous(errorMessage);
expect(error.duration, isNull);
expect(error.position, equals(const Duration(seconds: 0)));
expect(error.caption, equals(const Caption()));
expect(error.duration, equals(Duration.zero));
expect(error.position, equals(Duration.zero));
expect(error.caption, equals(Caption.none));
expect(error.buffered, isEmpty);
expect(error.isPlaying, isFalse);
expect(error.isLooping, isFalse);
@ -527,9 +526,8 @@ void main() {
expect(error.volume, 1.0);
expect(error.playbackSpeed, 1.0);
expect(error.errorDescription, errorMessage);
expect(error.size, isNull);
expect(error.size, isNull);
expect(error.initialized, isFalse);
expect(error.size, equals(Size.zero));
expect(error.isInitialized, isFalse);
expect(error.hasError, isTrue);
expect(error.aspectRatio, 1.0);
});
@ -538,10 +536,12 @@ void main() {
const Duration duration = Duration(seconds: 5);
const Size size = Size(400, 300);
const Duration position = Duration(seconds: 1);
const Caption caption = Caption(text: 'foo');
const Caption caption = Caption(
text: 'foo', number: 0, start: Duration.zero, end: Duration.zero);
final List<DurationRange> buffered = <DurationRange>[
DurationRange(const Duration(seconds: 0), const Duration(seconds: 4))
];
const bool isInitialized = true;
const bool isPlaying = true;
const bool isLooping = true;
const bool isBuffering = true;
@ -554,6 +554,7 @@ void main() {
position: position,
caption: caption,
buffered: buffered,
isInitialized: isInitialized,
isPlaying: isPlaying,
isLooping: isLooping,
isBuffering: isBuffering,
@ -568,6 +569,7 @@ void main() {
'position: 0:00:01.000000, '
'caption: Caption(number: null, start: null, end: null, text: foo), '
'buffered: [DurationRange(start: 0:00:00.000000, end: 0:00:04.000000)], '
'isInitialized: true, '
'isPlaying: true, '
'isLooping: true, '
'isBuffering: true, '
@ -586,15 +588,16 @@ void main() {
group('aspectRatio', () {
test('640x480 -> 4:3', () {
final value = VideoPlayerValue(
isInitialized: true,
size: Size(640, 480),
duration: Duration(seconds: 1),
);
expect(value.aspectRatio, 4 / 3);
});
test('null size -> 1.0', () {
test('no size -> 1.0', () {
final value = VideoPlayerValue(
size: null,
isInitialized: true,
duration: Duration(seconds: 1),
);
expect(value.aspectRatio, 1.0);
@ -602,6 +605,7 @@ void main() {
test('height = 0 -> 1.0', () {
final value = VideoPlayerValue(
isInitialized: true,
size: Size(640, 0),
duration: Duration(seconds: 1),
);
@ -610,6 +614,7 @@ void main() {
test('width = 0 -> 1.0', () {
final value = VideoPlayerValue(
isInitialized: true,
size: Size(0, 480),
duration: Duration(seconds: 1),
);
@ -618,6 +623,7 @@ void main() {
test('negative aspect ratio -> 1.0', () {
final value = VideoPlayerValue(
isInitialized: true,
size: Size(640, -480),
duration: Duration(seconds: 1),
);
@ -646,7 +652,7 @@ void main() {
File(''),
videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true));
await controller.initialize();
expect(controller.videoPlayerOptions.mixWithOthers, true);
expect(controller.videoPlayerOptions!.mixWithOthers, true);
});
}
@ -706,7 +712,7 @@ class FakeVideoPlayerPlatform extends TestHostVideoPlayerApi {
@override
void seekTo(PositionMessage arg) {
calls.add('seekTo');
_positions[arg.textureId] = Duration(milliseconds: arg.position);
_positions[arg.textureId!] = Duration(milliseconds: arg.position!);
}
@override
@ -742,7 +748,7 @@ class FakeVideoEventStream {
int height;
Duration duration;
bool initWithError;
FakeEventsChannel eventsChannel;
late FakeEventsChannel eventsChannel;
void onListen() {
if (!initWithError) {
@ -764,7 +770,7 @@ class FakeEventsChannel {
eventsMethodChannel.setMockMethodCallHandler(onMethodCall);
}
MethodChannel eventsMethodChannel;
late MethodChannel eventsMethodChannel;
VoidCallback onListen;
Future<dynamic> onMethodCall(MethodCall call) {
@ -780,7 +786,7 @@ class FakeEventsChannel {
_sendMessage(const StandardMethodCodec().encodeSuccessEnvelope(event));
}
void sendError(String code, [String message, dynamic details]) {
void sendError(String code, [String? message, dynamic details]) {
_sendMessage(const StandardMethodCodec().encodeErrorEnvelope(
code: code,
message: message,
@ -794,6 +800,6 @@ class FakeEventsChannel {
// available on all the versions of Flutter that we test.
// ignore: deprecated_member_use
defaultBinaryMessenger.handlePlatformMessage(
eventsMethodChannel.name, data, (ByteData data) {});
eventsMethodChannel.name, data, (ByteData? data) {});
}
}

View File

@ -1,3 +1,19 @@
## 3.0.0-nullsafety.3
* `messages.dart` sets Dart `2.12`.
## 3.0.0-nullsafety.2
* Bump Dart SDK to support null safety.
## 3.0.0-nullsafety.1
* Make DataSource's `uri` parameter nullable.
## 3.0.0-nullsafety
* Migrate to null safety.
## 2.2.1
* Update Flutter SDK constraint.

View File

@ -0,0 +1,4 @@
include: ../../../analysis_options.yaml
analyzer:
enable-experiment:
- non-nullable

View File

@ -1,13 +1,13 @@
// Autogenerated from Pigeon (v0.1.7), do not edit directly.
// Autogenerated from Pigeon (v0.1.12), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import
// @dart = 2.8
// @dart = 2.12
import 'dart:async';
import 'package:flutter/services.dart';
import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List;
class TextureMessage {
int textureId;
int? textureId;
// ignore: unused_element
Map<dynamic, dynamic> _toMap() {
final Map<dynamic, dynamic> pigeonMap = <dynamic, dynamic>{};
@ -17,9 +17,6 @@ class TextureMessage {
// ignore: unused_element
static TextureMessage _fromMap(Map<dynamic, dynamic> pigeonMap) {
if (pigeonMap == null) {
return null;
}
final TextureMessage result = TextureMessage();
result.textureId = pigeonMap['textureId'];
return result;
@ -27,10 +24,10 @@ class TextureMessage {
}
class CreateMessage {
String asset;
String uri;
String packageName;
String formatHint;
String? asset;
String? uri;
String? packageName;
String? formatHint;
// ignore: unused_element
Map<dynamic, dynamic> _toMap() {
final Map<dynamic, dynamic> pigeonMap = <dynamic, dynamic>{};
@ -43,9 +40,6 @@ class CreateMessage {
// ignore: unused_element
static CreateMessage _fromMap(Map<dynamic, dynamic> pigeonMap) {
if (pigeonMap == null) {
return null;
}
final CreateMessage result = CreateMessage();
result.asset = pigeonMap['asset'];
result.uri = pigeonMap['uri'];
@ -56,8 +50,8 @@ class CreateMessage {
}
class LoopingMessage {
int textureId;
bool isLooping;
int? textureId;
bool? isLooping;
// ignore: unused_element
Map<dynamic, dynamic> _toMap() {
final Map<dynamic, dynamic> pigeonMap = <dynamic, dynamic>{};
@ -68,9 +62,6 @@ class LoopingMessage {
// ignore: unused_element
static LoopingMessage _fromMap(Map<dynamic, dynamic> pigeonMap) {
if (pigeonMap == null) {
return null;
}
final LoopingMessage result = LoopingMessage();
result.textureId = pigeonMap['textureId'];
result.isLooping = pigeonMap['isLooping'];
@ -79,8 +70,8 @@ class LoopingMessage {
}
class VolumeMessage {
int textureId;
double volume;
int? textureId;
double? volume;
// ignore: unused_element
Map<dynamic, dynamic> _toMap() {
final Map<dynamic, dynamic> pigeonMap = <dynamic, dynamic>{};
@ -91,9 +82,6 @@ class VolumeMessage {
// ignore: unused_element
static VolumeMessage _fromMap(Map<dynamic, dynamic> pigeonMap) {
if (pigeonMap == null) {
return null;
}
final VolumeMessage result = VolumeMessage();
result.textureId = pigeonMap['textureId'];
result.volume = pigeonMap['volume'];
@ -102,8 +90,8 @@ class VolumeMessage {
}
class PlaybackSpeedMessage {
int textureId;
double speed;
int? textureId;
double? speed;
// ignore: unused_element
Map<dynamic, dynamic> _toMap() {
final Map<dynamic, dynamic> pigeonMap = <dynamic, dynamic>{};
@ -114,9 +102,6 @@ class PlaybackSpeedMessage {
// ignore: unused_element
static PlaybackSpeedMessage _fromMap(Map<dynamic, dynamic> pigeonMap) {
if (pigeonMap == null) {
return null;
}
final PlaybackSpeedMessage result = PlaybackSpeedMessage();
result.textureId = pigeonMap['textureId'];
result.speed = pigeonMap['speed'];
@ -125,8 +110,8 @@ class PlaybackSpeedMessage {
}
class PositionMessage {
int textureId;
int position;
int? textureId;
int? position;
// ignore: unused_element
Map<dynamic, dynamic> _toMap() {
final Map<dynamic, dynamic> pigeonMap = <dynamic, dynamic>{};
@ -137,9 +122,6 @@ class PositionMessage {
// ignore: unused_element
static PositionMessage _fromMap(Map<dynamic, dynamic> pigeonMap) {
if (pigeonMap == null) {
return null;
}
final PositionMessage result = PositionMessage();
result.textureId = pigeonMap['textureId'];
result.position = pigeonMap['position'];
@ -148,7 +130,7 @@ class PositionMessage {
}
class MixWithOthersMessage {
bool mixWithOthers;
bool? mixWithOthers;
// ignore: unused_element
Map<dynamic, dynamic> _toMap() {
final Map<dynamic, dynamic> pigeonMap = <dynamic, dynamic>{};
@ -158,9 +140,6 @@ class MixWithOthersMessage {
// ignore: unused_element
static MixWithOthersMessage _fromMap(Map<dynamic, dynamic> pigeonMap) {
if (pigeonMap == null) {
return null;
}
final MixWithOthersMessage result = MixWithOthersMessage();
result.mixWithOthers = pigeonMap['mixWithOthers'];
return result;
@ -172,7 +151,7 @@ class VideoPlayerApi {
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.initialize', StandardMessageCodec());
final Map<dynamic, dynamic> replyMap = await channel.send(null);
final Map<dynamic, dynamic>? replyMap = await channel.send(null);
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
@ -194,7 +173,7 @@ class VideoPlayerApi {
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.create', StandardMessageCodec());
final Map<dynamic, dynamic> replyMap = await channel.send(requestMap);
final Map<dynamic, dynamic>? replyMap = await channel.send(requestMap);
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
@ -216,7 +195,7 @@ class VideoPlayerApi {
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.dispose', StandardMessageCodec());
final Map<dynamic, dynamic> replyMap = await channel.send(requestMap);
final Map<dynamic, dynamic>? replyMap = await channel.send(requestMap);
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
@ -238,7 +217,7 @@ class VideoPlayerApi {
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.setLooping', StandardMessageCodec());
final Map<dynamic, dynamic> replyMap = await channel.send(requestMap);
final Map<dynamic, dynamic>? replyMap = await channel.send(requestMap);
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
@ -260,7 +239,7 @@ class VideoPlayerApi {
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.setVolume', StandardMessageCodec());
final Map<dynamic, dynamic> replyMap = await channel.send(requestMap);
final Map<dynamic, dynamic>? replyMap = await channel.send(requestMap);
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
@ -283,7 +262,7 @@ class VideoPlayerApi {
'dev.flutter.pigeon.VideoPlayerApi.setPlaybackSpeed',
StandardMessageCodec());
final Map<dynamic, dynamic> replyMap = await channel.send(requestMap);
final Map<dynamic, dynamic>? replyMap = await channel.send(requestMap);
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
@ -305,7 +284,7 @@ class VideoPlayerApi {
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.play', StandardMessageCodec());
final Map<dynamic, dynamic> replyMap = await channel.send(requestMap);
final Map<dynamic, dynamic>? replyMap = await channel.send(requestMap);
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
@ -327,7 +306,7 @@ class VideoPlayerApi {
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.position', StandardMessageCodec());
final Map<dynamic, dynamic> replyMap = await channel.send(requestMap);
final Map<dynamic, dynamic>? replyMap = await channel.send(requestMap);
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
@ -349,7 +328,7 @@ class VideoPlayerApi {
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.seekTo', StandardMessageCodec());
final Map<dynamic, dynamic> replyMap = await channel.send(requestMap);
final Map<dynamic, dynamic>? replyMap = await channel.send(requestMap);
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
@ -371,7 +350,7 @@ class VideoPlayerApi {
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.pause', StandardMessageCodec());
final Map<dynamic, dynamic> replyMap = await channel.send(requestMap);
final Map<dynamic, dynamic>? replyMap = await channel.send(requestMap);
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
@ -394,7 +373,7 @@ class VideoPlayerApi {
'dev.flutter.pigeon.VideoPlayerApi.setMixWithOthers',
StandardMessageCodec());
final Map<dynamic, dynamic> replyMap = await channel.send(requestMap);
final Map<dynamic, dynamic>? replyMap = await channel.send(requestMap);
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
@ -424,19 +403,26 @@ abstract class TestHostVideoPlayerApi {
void seekTo(PositionMessage arg);
void pause(TextureMessage arg);
void setMixWithOthers(MixWithOthersMessage arg);
static void setup(TestHostVideoPlayerApi api) {
static void setup(TestHostVideoPlayerApi? api) {
{
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.initialize',
StandardMessageCodec());
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((dynamic message) async {
api.initialize();
return <dynamic, dynamic>{};
});
}
}
{
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.create', StandardMessageCodec());
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((dynamic message) async {
final Map<dynamic, dynamic> mapMessage =
message as Map<dynamic, dynamic>;
@ -445,9 +431,13 @@ abstract class TestHostVideoPlayerApi {
return <dynamic, dynamic>{'result': output._toMap()};
});
}
}
{
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.dispose', StandardMessageCodec());
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((dynamic message) async {
final Map<dynamic, dynamic> mapMessage =
message as Map<dynamic, dynamic>;
@ -456,10 +446,14 @@ abstract class TestHostVideoPlayerApi {
return <dynamic, dynamic>{};
});
}
}
{
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.setLooping',
StandardMessageCodec());
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((dynamic message) async {
final Map<dynamic, dynamic> mapMessage =
message as Map<dynamic, dynamic>;
@ -468,10 +462,14 @@ abstract class TestHostVideoPlayerApi {
return <dynamic, dynamic>{};
});
}
}
{
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.setVolume',
StandardMessageCodec());
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((dynamic message) async {
final Map<dynamic, dynamic> mapMessage =
message as Map<dynamic, dynamic>;
@ -480,10 +478,14 @@ abstract class TestHostVideoPlayerApi {
return <dynamic, dynamic>{};
});
}
}
{
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.setPlaybackSpeed',
StandardMessageCodec());
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((dynamic message) async {
final Map<dynamic, dynamic> mapMessage =
message as Map<dynamic, dynamic>;
@ -493,9 +495,13 @@ abstract class TestHostVideoPlayerApi {
return <dynamic, dynamic>{};
});
}
}
{
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.play', StandardMessageCodec());
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((dynamic message) async {
final Map<dynamic, dynamic> mapMessage =
message as Map<dynamic, dynamic>;
@ -504,9 +510,13 @@ abstract class TestHostVideoPlayerApi {
return <dynamic, dynamic>{};
});
}
}
{
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.position', StandardMessageCodec());
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((dynamic message) async {
final Map<dynamic, dynamic> mapMessage =
message as Map<dynamic, dynamic>;
@ -515,9 +525,13 @@ abstract class TestHostVideoPlayerApi {
return <dynamic, dynamic>{'result': output._toMap()};
});
}
}
{
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.seekTo', StandardMessageCodec());
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((dynamic message) async {
final Map<dynamic, dynamic> mapMessage =
message as Map<dynamic, dynamic>;
@ -526,9 +540,13 @@ abstract class TestHostVideoPlayerApi {
return <dynamic, dynamic>{};
});
}
}
{
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.pause', StandardMessageCodec());
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((dynamic message) async {
final Map<dynamic, dynamic> mapMessage =
message as Map<dynamic, dynamic>;
@ -537,10 +555,14 @@ abstract class TestHostVideoPlayerApi {
return <dynamic, dynamic>{};
});
}
}
{
const BasicMessageChannel<dynamic> channel = BasicMessageChannel<dynamic>(
'dev.flutter.pigeon.VideoPlayerApi.setMixWithOthers',
StandardMessageCodec());
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((dynamic message) async {
final Map<dynamic, dynamic> mapMessage =
message as Map<dynamic, dynamic>;
@ -551,4 +573,5 @@ abstract class TestHostVideoPlayerApi {
});
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More