diff --git a/bin/internal/engine.version b/bin/internal/engine.version index f0e474e2271..4ac12041b8c 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -e8d046e9e208bbc026f0f0e81cac87bfd791b7a0 +cf774d580c40767548cbf68a1f07f2b7657ff93b diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart index 2ad227f50a7..265df15d8c8 100644 --- a/packages/flutter/lib/src/material/app_bar.dart +++ b/packages/flutter/lib/src/material/app_bar.dart @@ -4,7 +4,6 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_services/platform/system_chrome.dart' as mojom; import 'constants.dart'; import 'icon_theme.dart'; @@ -342,8 +341,8 @@ class AppBar extends StatelessWidget { Brightness brightness = this.brightness ?? themeData.primaryColorBrightness; SystemChrome.setSystemUIOverlayStyle(brightness == Brightness.dark - ? mojom.SystemUiOverlayStyle.light - : mojom.SystemUiOverlayStyle.dark); + ? SystemUiOverlayStyle.light + : SystemUiOverlayStyle.dark); final double toolbarOpacity = _toolbarOpacity(size.height, statusBarHeight); if (toolbarOpacity != 1.0) { diff --git a/packages/flutter/lib/src/services/haptic_feedback.dart b/packages/flutter/lib/src/services/haptic_feedback.dart index 5afa0fa354d..cd6c711a683 100644 --- a/packages/flutter/lib/src/services/haptic_feedback.dart +++ b/packages/flutter/lib/src/services/haptic_feedback.dart @@ -4,15 +4,7 @@ import 'dart:async'; -import 'package:flutter_services/platform/haptic_feedback.dart' as mojom; - -import 'shell.dart'; - -mojom.HapticFeedbackProxy _initHapticFeedbackProxy() { - return shell.connectToApplicationService('mojo:flutter_platform', mojom.HapticFeedback.connectToService); -} - -final mojom.HapticFeedbackProxy _hapticFeedbackProxy = _initHapticFeedbackProxy(); +import 'platform_messages.dart'; /// Allows access to the haptic feedback interface on the device. This API is /// intentionally terse since it calls default platform behavior. It is not @@ -29,18 +21,10 @@ class HapticFeedback { /// AudioServicesPlaySystemSound) /// * _Android_: Uses the platform haptic feedback API that simulates a short /// a short tap on a virtual keyboard. - /// - /// Return Value: - /// - /// boolean indicating if the intent to provide haptic feedback to the user - /// was successfully conveyed to the embedder. There may not be any actual - /// feedback if the device does not have a vibrator or one is disabled in - /// system settings. - static Future vibrate() { - Completer completer = new Completer(); - _hapticFeedbackProxy.vibrate((bool result) { - completer.complete(result); + static Future vibrate() async { + await PlatformMessages.sendJSON('flutter/platform', { + 'method': 'HapticFeedback.vibrate', + 'args': [], }); - return completer.future; } } diff --git a/packages/flutter/lib/src/services/path_provider.dart b/packages/flutter/lib/src/services/path_provider.dart index 3c5f23dcea3..3bc0a2e1808 100644 --- a/packages/flutter/lib/src/services/path_provider.dart +++ b/packages/flutter/lib/src/services/path_provider.dart @@ -5,15 +5,7 @@ import 'dart:async'; import 'dart:io'; -import 'package:flutter_services/platform/path_provider.dart' as mojom; - -import 'shell.dart'; - -mojom.PathProviderProxy _initPathProviderProxy() { - return shell.connectToApplicationService('mojo:flutter_platform', mojom.PathProvider.connectToService); -} - -final mojom.PathProviderProxy _pathProviderProxy = _initPathProviderProxy(); +import 'platform_messages.dart'; /// Returns commonly used locations on the filesystem. class PathProvider { @@ -29,12 +21,15 @@ class PathProvider { /// /// * _iOS_: `NSTemporaryDirectory()` /// * _Android_: `getCacheDir()` on the context. - static Future getTemporaryDirectory() { - Completer completer = new Completer(); - _pathProviderProxy.temporaryDirectory((String path) { - completer.complete(new Directory(path)); - }); - return completer.future; + static Future getTemporaryDirectory() async { + Map result = + await PlatformMessages.sendJSON('flutter/platform', { + 'method': 'PathProvider.getTemporaryDirectory', + 'args': [], + }); + if (result == null) + return null; + return new Directory(result['path']); } /// Path to a directory where the application may place files that are private @@ -45,11 +40,14 @@ class PathProvider { /// /// * _iOS_: `NSDocumentsDirectory` /// * _Android_: The AppData directory. - static Future getApplicationDocumentsDirectory() { - Completer completer = new Completer(); - _pathProviderProxy.applicationDocumentsDirectory((String path) { - completer.complete(new Directory(path)); + static Future getApplicationDocumentsDirectory() async { + Map result = + await PlatformMessages.sendJSON('flutter/platform', { + 'method': 'PathProvider.getApplicationDocumentsDirectory', + 'args': [], }); - return completer.future; + if (result == null) + return null; + return new Directory(result['path']); } } diff --git a/packages/flutter/lib/src/services/platform_messages.dart b/packages/flutter/lib/src/services/platform_messages.dart index 8cb42f86ece..aaa5e63817a 100644 --- a/packages/flutter/lib/src/services/platform_messages.dart +++ b/packages/flutter/lib/src/services/platform_messages.dart @@ -17,7 +17,7 @@ dynamic _decodeJSON(String message) { void _sendString(String name, String message, void callback(String reply)) { Uint8List encoded = UTF8.encoder.convert(message); - ui.window.sendPlatformMesssage(name, encoded.buffer.asByteData(), (ByteData reply) { + ui.window.sendPlatformMessage(name, encoded.buffer.asByteData(), (ByteData reply) { callback(_decodeUTF8(reply)); }); } diff --git a/packages/flutter/lib/src/services/system_chrome.dart b/packages/flutter/lib/src/services/system_chrome.dart index 9da8aefecc7..717900138a4 100644 --- a/packages/flutter/lib/src/services/system_chrome.dart +++ b/packages/flutter/lib/src/services/system_chrome.dart @@ -4,20 +4,83 @@ import 'dart:async'; -import 'package:flutter_services/platform/system_chrome.dart' as mojom; -import 'package:flutter_services/platform/system_chrome.dart' - show DeviceOrientation, SystemUiOverlay, SystemUiOverlayStyle; +import 'platform_messages.dart'; -import 'shell.dart'; +/// Specifies a particular device orientation. +/// +/// Discussion: +/// +/// To determine which values correspond to which orientations, first position +/// the device in its default orientation (this is the orientation that the +/// system first uses for its boot logo, or the orientation in which the +/// hardware logos or markings are upright, or the orientation in which the +/// cameras are at the top). If this is a portrait orientation, then this is +/// [portraitUp]. Otherwise, it's [landscapeLeft]. As you rotate the device by 90 +/// degrees in a counter-clockwise direction around the axis that traverses the +/// screen, you step through each value in this enum in the order given. (For a +/// device with a landscape default orientation, the orientation obtained by +/// rotating the device 90 degrees clockwise from its default orientation is +/// [portraitUp].) +enum DeviceOrientation { + /// If the device shows its boot logo in portrait, then the boot logo is shown + /// in [portraitUp]. Otherwise, the device shows its boot logo in landscape + /// and this orientation is obtained by rotating the device 90 degrees + /// clockwise from its boot orientation. + portraitUp, -export 'package:flutter_services/platform/system_chrome.dart' - show DeviceOrientation, SystemUiOverlay, SystemUiOverlayStyle; + /// The orientation that is 90 degrees clockwise from [portraitUp]. + landscapeLeft, -mojom.SystemChromeProxy _initSystemChromeProxy() { - return shell.connectToApplicationService('mojo:flutter_platform', mojom.SystemChrome.connectToService); + /// The orientation that is 180 degrees from [portraitUp]. + portraitDown, + + /// The orientation that is 90 degrees counterclockwise from [portraitUp]. + landscapeRight, } -final mojom.SystemChromeProxy _systemChromeProxy = _initSystemChromeProxy(); +/// Specifies a description of the application that is pertinent to the +/// embedder's application switcher (a.k.a. "recent tasks") user interface. +class ApplicationSwitcherDescription { + /// Creates an ApplicationSwitcherDescription. + const ApplicationSwitcherDescription({ this.label, this.primaryColor }); + + /// A label and description of the current state of the application. + final String label; + + /// The application's primary color. + final int primaryColor; +} + +/// Specifies a system overlay at a particular location. Certain platforms +/// may not use all overlays specified here. +enum SystemUiOverlay { + /// The status bar provided by the embedder on the top of the application + /// surface (optional) + top, + + /// The status bar provided by the embedder on the bottom of the application + /// surface (optional) + bottom, +} + +/// Specifies a preference for the style of the system overlays. Certain +/// platforms may not respect this preference. +enum SystemUiOverlayStyle { + /// System overlays should be drawn with a light color. Intended for + /// applications with a dark background. + light, + + /// System overlays should be drawn with a dark color. Intended for + /// applications with a light background. + dark, +} + +List _stringify(List list) { + List result = []; + for (dynamic item in list) + result.add(item.toString()); + return result; +} /// Controls specific aspects of the embedder interface. class SystemChrome { @@ -28,19 +91,13 @@ class SystemChrome { /// /// Arguments: /// - /// * [deviceOrientationMask]: A mask of [DeviceOrientation] enum values. - /// The value 0 is synonymous with having all options enabled. - /// - /// Return Value: - /// - /// boolean indicating if the orientation mask is valid and the changes - /// could be conveyed successfully to the embedder. - static Future setPreferredOrientations(int deviceOrientationMask) { - Completer completer = new Completer(); - _systemChromeProxy.setPreferredOrientations(deviceOrientationMask, (bool success) { - completer.complete(success); + /// * [orientation]: A list of [DeviceOrientation] enum values. The empty + /// list is synonymous with having all options enabled. + static Future setPreferredOrientations(List orientations) async { + await PlatformMessages.sendJSON('flutter/platform', { + 'method': 'SystemChrome.setPreferredOrientations', + 'args': >[ _stringify(orientations) ], }); - return completer.future; } /// Specifies the description of the current state of the application as it @@ -50,21 +107,18 @@ class SystemChrome { /// /// * [description]: The application description. /// - /// Return Value: - /// - /// boolean indicating if the description was conveyed successfully to the - /// embedder. - /// /// Platform Specific Notes: /// /// If application-specified metadata is unsupported on the platform, /// specifying it is a no-op and always return true. - static Future setApplicationSwitcherDescription(mojom.ApplicationSwitcherDescription description) { - Completer completer = new Completer(); - _systemChromeProxy.setApplicationSwitcherDescription(description, (bool success) { - completer.complete(success); + static Future setApplicationSwitcherDescription(ApplicationSwitcherDescription description) async { + await PlatformMessages.sendJSON('flutter/platform', { + 'method': 'SystemChrome.setApplicationSwitcherDescription', + 'args': >[{ + 'label': description.label, + 'primaryColor': description.primaryColor, + }], }); - return completer.future; } /// Specifies the set of overlays visible on the embedder when the @@ -76,21 +130,15 @@ class SystemChrome { /// * [overlaysMask]: A mask of [SystemUiOverlay] enum values that denotes /// the overlays to show. /// - /// Return Value: - /// - /// boolean indicating if the preference was conveyed successfully to the - /// embedder. - /// /// Platform Specific Notes: /// /// If the overlay is unsupported on the platform, enabling or disabling /// that overlay is a no-op and always return true. - static Future setEnabledSystemUIOverlays(int overlaysMask) { - Completer completer = new Completer(); - _systemChromeProxy.setEnabledSystemUiOverlays(overlaysMask, (bool success) { - completer.complete(success); + static Future setEnabledSystemUIOverlays(List overlays) async { + await PlatformMessages.sendJSON('flutter/platform', { + 'method': 'SystemChrome.setEnabledSystemUIOverlays', + 'args': >[ _stringify(overlays) ], }); - return completer.future; } /// Specifies the style of the system overlays that are visible on the @@ -118,8 +166,9 @@ class SystemChrome { scheduleMicrotask(() { assert(_pendingStyle != null); if (_pendingStyle != _latestStyle) { - _systemChromeProxy.setSystemUiOverlayStyle(_pendingStyle, (bool success) { - // Ignored. + PlatformMessages.sendJSON('flutter/platform', { + 'method': 'SystemChrome.setSystemUIOverlayStyle', + 'args': [ _pendingStyle.toString() ], }); _latestStyle = _pendingStyle; } diff --git a/packages/flutter/lib/src/services/system_sound.dart b/packages/flutter/lib/src/services/system_sound.dart index 54b39b33366..299c01fd043 100644 --- a/packages/flutter/lib/src/services/system_sound.dart +++ b/packages/flutter/lib/src/services/system_sound.dart @@ -4,37 +4,25 @@ import 'dart:async'; -import 'package:flutter_services/platform/system_sound.dart' as mojom; -import 'package:flutter_services/platform/system_sound.dart' show SystemSoundType; +import 'platform_messages.dart'; -import 'shell.dart'; - -export 'package:flutter_services/platform/system_sound.dart' show SystemSoundType; - -mojom.SystemSoundProxy _initSystemSoundProxy() { - return shell.connectToApplicationService('mojo:flutter_platform', mojom.SystemSound.connectToService); +/// A sound provided by the system +enum SystemSoundType { + /// A short indication that a button was pressed. + click, } -final mojom.SystemSoundProxy _systemChromeProxy = _initSystemSoundProxy(); - /// Allows easy access to the library of short system specific sounds for /// common tasks. class SystemSound { SystemSound._(); /// Play the specified system sound. If that sound is not present on the - /// system, this method is a no-op and returns `true`. - /// - /// Return Value: - /// - /// boolean indicating if the intent to play the specified sound was - /// successfully conveyed to the embedder. No sound may actually play if the - /// device is muted or the sound was not available on the platform. - static Future play(SystemSoundType type) { - Completer completer = new Completer(); - _systemChromeProxy.play(type, (bool success) { - completer.complete(success); + /// system, this method is a no-op. + static Future play(SystemSoundType type) async { + await PlatformMessages.sendJSON('flutter/platform', { + 'method': 'SystemSound.play', + 'args': [ type.toString() ], }); - return completer.future; } } diff --git a/packages/flutter/lib/src/services/url_launcher.dart b/packages/flutter/lib/src/services/url_launcher.dart index b8cba51cd8b..5feb840ad99 100644 --- a/packages/flutter/lib/src/services/url_launcher.dart +++ b/packages/flutter/lib/src/services/url_launcher.dart @@ -4,16 +4,7 @@ import 'dart:async'; -import 'package:flutter_services/platform/url_launcher.dart' as mojom; -import 'shell.dart'; - -mojom.UrlLauncherProxy _initUrlLauncherProxy() { - return shell.connectToApplicationService( - mojom.UrlLauncher.serviceName, - mojom.UrlLauncher.connectToService); -} - -final mojom.UrlLauncherProxy _connectedUrlLauncherService = _initUrlLauncherProxy(); +import 'platform_messages.dart'; /// Allows applications to delegate responsbility of handling certain URLs to /// the underlying platform. @@ -27,18 +18,10 @@ class UrlLauncher { /// /// * [urlString]: The URL string to be parsed by the underlying platform and /// before it attempts to launch the same. - /// - /// Return Value: - /// - /// boolean indicating if the intent to handle the URL was successfully - /// conveyed to the to underlying platform and the platform could - /// successfully handle the same. The platform is responsible for URL - /// parsing. - static Future launch(String urlString) { - Completer completer = new Completer(); - _connectedUrlLauncherService.launch(urlString, (bool success) { - completer.complete(success); + static Future launch(String urlString) async { + await PlatformMessages.sendJSON('flutter/platform', { + 'method': 'UrlLauncher.launch', + 'args': [ urlString ], }); - return completer.future; } } diff --git a/packages/flutter/test/services/system_chrome_test.dart b/packages/flutter/test/services/system_chrome_test.dart index 99bd3a0576f..c7f47797d80 100644 --- a/packages/flutter/test/services/system_chrome_test.dart +++ b/packages/flutter/test/services/system_chrome_test.dart @@ -4,12 +4,11 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter_services/platform/system_chrome.dart' as mojom; void main() { testWidgets('SystemChrome overlay style test', (WidgetTester tester) async { // The first call is a cache miss and will queue a microtask - SystemChrome.setSystemUIOverlayStyle(mojom.SystemUiOverlayStyle.light); + SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light); expect(tester.binding.microtaskCount, equals(1)); // Flush all microtasks @@ -17,7 +16,7 @@ void main() { expect(tester.binding.microtaskCount, equals(0)); // The second call with the same value should be a no-op - SystemChrome.setSystemUIOverlayStyle(mojom.SystemUiOverlayStyle.light); + SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light); expect(tester.binding.microtaskCount, equals(0)); }); }