Add ergonomic wrappers for Flutter platform services (#3636)
These wrappers also give us a chance to document what these services do. Fixes #3164
This commit is contained in:
parent
5497ba182f
commit
870c361915
@ -3,7 +3,7 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
/// System services exposed to Flutter apps.
|
/// System services exposed to Flutter apps.
|
||||||
///
|
///
|
||||||
/// To use, import `package:flutter/services.dart`.
|
/// To use, import `package:flutter/services.dart`.
|
||||||
///
|
///
|
||||||
/// For example, this library includes [fetch], which fetches data from the
|
/// For example, this library includes [fetch], which fetches data from the
|
||||||
@ -18,8 +18,12 @@ export 'src/services/activity.dart';
|
|||||||
export 'src/services/app_messages.dart';
|
export 'src/services/app_messages.dart';
|
||||||
export 'src/services/asset_bundle.dart';
|
export 'src/services/asset_bundle.dart';
|
||||||
export 'src/services/binding.dart';
|
export 'src/services/binding.dart';
|
||||||
|
export 'src/services/haptic_feedback.dart';
|
||||||
export 'src/services/image_cache.dart';
|
export 'src/services/image_cache.dart';
|
||||||
export 'src/services/image_decoder.dart';
|
export 'src/services/image_decoder.dart';
|
||||||
export 'src/services/image_resource.dart';
|
export 'src/services/image_resource.dart';
|
||||||
export 'src/services/keyboard.dart';
|
export 'src/services/keyboard.dart';
|
||||||
|
export 'src/services/path_provider.dart';
|
||||||
export 'src/services/shell.dart';
|
export 'src/services/shell.dart';
|
||||||
|
export 'src/services/system_chrome.dart';
|
||||||
|
export 'src/services/system_sound.dart';
|
||||||
|
@ -66,14 +66,14 @@ class _DatePickerState extends State<DatePicker> {
|
|||||||
_DatePickerMode _mode = _DatePickerMode.day;
|
_DatePickerMode _mode = _DatePickerMode.day;
|
||||||
|
|
||||||
void _handleModeChanged(_DatePickerMode mode) {
|
void _handleModeChanged(_DatePickerMode mode) {
|
||||||
userFeedback.performHapticFeedback(HapticFeedbackType.virtualKey);
|
HapticFeedback.vibrate();
|
||||||
setState(() {
|
setState(() {
|
||||||
_mode = mode;
|
_mode = mode;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleYearChanged(DateTime dateTime) {
|
void _handleYearChanged(DateTime dateTime) {
|
||||||
userFeedback.performHapticFeedback(HapticFeedbackType.virtualKey);
|
HapticFeedback.vibrate();
|
||||||
setState(() {
|
setState(() {
|
||||||
_mode = _DatePickerMode.day;
|
_mode = _DatePickerMode.day;
|
||||||
});
|
});
|
||||||
@ -82,7 +82,7 @@ class _DatePickerState extends State<DatePicker> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _handleDayChanged(DateTime dateTime) {
|
void _handleDayChanged(DateTime dateTime) {
|
||||||
userFeedback.performHapticFeedback(HapticFeedbackType.virtualKey);
|
HapticFeedback.vibrate();
|
||||||
if (config.onChanged != null)
|
if (config.onChanged != null)
|
||||||
config.onChanged(dateTime);
|
config.onChanged(dateTime);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:flutter/services.dart' show HapticFeedbackType, userFeedback;
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
import 'colors.dart';
|
import 'colors.dart';
|
||||||
@ -129,7 +129,7 @@ class _TimePickerState extends State<TimePicker> {
|
|||||||
_TimePickerMode _mode = _TimePickerMode.hour;
|
_TimePickerMode _mode = _TimePickerMode.hour;
|
||||||
|
|
||||||
void _handleModeChanged(_TimePickerMode mode) {
|
void _handleModeChanged(_TimePickerMode mode) {
|
||||||
userFeedback.performHapticFeedback(HapticFeedbackType.virtualKey);
|
HapticFeedback.vibrate();
|
||||||
setState(() {
|
setState(() {
|
||||||
_mode = mode;
|
_mode = mode;
|
||||||
});
|
});
|
||||||
|
@ -3,13 +3,13 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:sky_services/activity/activity.mojom.dart';
|
import 'package:sky_services/activity/activity.mojom.dart';
|
||||||
|
|
||||||
import 'shell.dart';
|
import 'shell.dart';
|
||||||
|
|
||||||
export 'package:sky_services/activity/activity.mojom.dart';
|
export 'package:sky_services/activity/activity.mojom.dart' show Activity, Intent, ComponentName, StringExtra;
|
||||||
|
|
||||||
|
|
||||||
// Dart wrapper around Activity mojo service available in Flutter on Android.
|
// Dart wrapper around Activity mojo service available in Flutter on Android.
|
||||||
//
|
//
|
||||||
@ -21,7 +21,7 @@ export 'package:sky_services/activity/activity.mojom.dart';
|
|||||||
|
|
||||||
/// Open a document into a new task rooted at the activity launched by
|
/// Open a document into a new task rooted at the activity launched by
|
||||||
/// this Intent.
|
/// this Intent.
|
||||||
///
|
///
|
||||||
/// See Android's Intent.FLAG_ACTIVITY_NEW_DOCUMENT.
|
/// See Android's Intent.FLAG_ACTIVITY_NEW_DOCUMENT.
|
||||||
const int NEW_DOCUMENT = 0x00080000; // ignore: constant_identifier_names
|
const int NEW_DOCUMENT = 0x00080000; // ignore: constant_identifier_names
|
||||||
|
|
||||||
@ -44,24 +44,6 @@ ActivityProxy _initActivityProxy() {
|
|||||||
final ActivityProxy _activityProxy = _initActivityProxy();
|
final ActivityProxy _activityProxy = _initActivityProxy();
|
||||||
final Activity activity = _activityProxy.ptr;
|
final Activity activity = _activityProxy.ptr;
|
||||||
|
|
||||||
UserFeedbackProxy _initUserFeedbackProxy() {
|
|
||||||
UserFeedbackProxy proxy = new UserFeedbackProxy.unbound();
|
|
||||||
_activityProxy.ptr.getUserFeedback(proxy);
|
|
||||||
return proxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
final UserFeedbackProxy _userFeedbackProxy = _initUserFeedbackProxy();
|
|
||||||
final UserFeedback userFeedback = _userFeedbackProxy.ptr;
|
|
||||||
|
|
||||||
PathServiceProxy _initPathServiceProxy() {
|
|
||||||
PathServiceProxy proxy = new PathServiceProxy.unbound();
|
|
||||||
shell.connectToService(null, proxy);
|
|
||||||
return proxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
final PathServiceProxy _pathServiceProxy = _initPathServiceProxy();
|
|
||||||
final PathService pathService = _pathServiceProxy.ptr;
|
|
||||||
|
|
||||||
Color _cachedPrimaryColor;
|
Color _cachedPrimaryColor;
|
||||||
String _cachedLabel;
|
String _cachedLabel;
|
||||||
|
|
||||||
@ -81,7 +63,3 @@ void updateTaskDescription({ String label, Color color }) {
|
|||||||
|
|
||||||
_activityProxy.ptr.setTaskDescription(description);
|
_activityProxy.ptr.setTaskDescription(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getAppDataDir() async => (await _pathServiceProxy.ptr.getAppDataDir()).path;
|
|
||||||
Future<String> getFilesDir() async => (await _pathServiceProxy.ptr.getFilesDir()).path;
|
|
||||||
Future<String> getCacheDir() async => (await _pathServiceProxy.ptr.getCacheDir()).path;
|
|
||||||
|
@ -5,30 +5,28 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:mojo/core.dart' as core;
|
import 'package:mojo/core.dart' as core;
|
||||||
import 'package:sky_services/flutter/platform/app_messages.mojom.dart';
|
import 'package:sky_services/flutter/platform/app_messages.mojom.dart' as mojom;
|
||||||
|
|
||||||
import 'shell.dart';
|
import 'shell.dart';
|
||||||
|
|
||||||
// APIs for exchanging messages with the host application.
|
mojom.ApplicationMessagesProxy _initHostAppMessagesProxy() {
|
||||||
|
mojom.ApplicationMessagesProxy proxy = new mojom.ApplicationMessagesProxy.unbound();
|
||||||
ApplicationMessagesProxy _initHostAppMessagesProxy() {
|
|
||||||
ApplicationMessagesProxy proxy = new ApplicationMessagesProxy.unbound();
|
|
||||||
shell.connectToViewAssociatedService(proxy);
|
shell.connectToViewAssociatedService(proxy);
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ApplicationMessagesProxy _hostAppMessagesProxy = _initHostAppMessagesProxy();
|
final mojom.ApplicationMessagesProxy _hostAppMessagesProxy = _initHostAppMessagesProxy();
|
||||||
|
|
||||||
typedef Future<String> HostMessageCallback(String message);
|
typedef Future<String> HostMessageCallback(String message);
|
||||||
typedef Object _SendStringResponseFactory(String response);
|
typedef Object _SendStringResponseFactory(String response);
|
||||||
|
|
||||||
class _ApplicationMessagesImpl extends ApplicationMessages {
|
class _ApplicationMessagesImpl extends mojom.ApplicationMessages {
|
||||||
final Map<String, HostMessageCallback> handlers = <String, HostMessageCallback>{};
|
final Map<String, HostMessageCallback> handlers = <String, HostMessageCallback>{};
|
||||||
|
|
||||||
_ApplicationMessagesImpl() {
|
_ApplicationMessagesImpl() {
|
||||||
shell.provideService(ApplicationMessages.serviceName,
|
shell.provideService(mojom.ApplicationMessages.serviceName,
|
||||||
(core.MojoMessagePipeEndpoint endpoint) {
|
(core.MojoMessagePipeEndpoint endpoint) {
|
||||||
ApplicationMessagesStub stub = new ApplicationMessagesStub.fromEndpoint(endpoint);
|
mojom.ApplicationMessagesStub stub = new mojom.ApplicationMessagesStub.fromEndpoint(endpoint);
|
||||||
stub.impl = this;
|
stub.impl = this;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -46,6 +44,8 @@ class _ApplicationMessagesImpl extends ApplicationMessages {
|
|||||||
|
|
||||||
final _ApplicationMessagesImpl _appMessages = new _ApplicationMessagesImpl();
|
final _ApplicationMessagesImpl _appMessages = new _ApplicationMessagesImpl();
|
||||||
|
|
||||||
|
/// A service that can be implemented by the host application and the
|
||||||
|
/// Flutter framework to exchange application-specific messages.
|
||||||
class HostMessages {
|
class HostMessages {
|
||||||
/// Send a message to the host application.
|
/// Send a message to the host application.
|
||||||
static Future<String> sendToHost(String messageName, String message) async {
|
static Future<String> sendToHost(String messageName, String message) async {
|
||||||
|
44
packages/flutter/lib/src/services/haptic_feedback.dart
Normal file
44
packages/flutter/lib/src/services/haptic_feedback.dart
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:sky_services/flutter/platform/haptic_feedback.mojom.dart' as mojom;
|
||||||
|
|
||||||
|
import 'shell.dart';
|
||||||
|
|
||||||
|
mojom.HapticFeedbackProxy _initHapticFeedbackProxy() {
|
||||||
|
mojom.HapticFeedbackProxy proxy = new mojom.HapticFeedbackProxy.unbound();
|
||||||
|
shell.connectToViewAssociatedService(proxy);
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
final mojom.HapticFeedbackProxy _hapticFeedbackProxy = _initHapticFeedbackProxy();
|
||||||
|
|
||||||
|
/// Allows access to the haptic feedback interface on the device. This API is
|
||||||
|
/// intentionally terse since it invokes default platform behavior. It is not
|
||||||
|
/// suitable for use if you require more flexible access to device sensors and
|
||||||
|
/// peripherals.
|
||||||
|
class HapticFeedback {
|
||||||
|
HapticFeedback._();
|
||||||
|
|
||||||
|
/// Provides haptic feedback to the user for a short duration.
|
||||||
|
///
|
||||||
|
/// Platform Specific Notes:
|
||||||
|
///
|
||||||
|
/// * _iOS_: Uses the platform "sound" for vibration (via
|
||||||
|
/// 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<bool> vibrate() async {
|
||||||
|
return (await _hapticFeedbackProxy.ptr.vibrate()).success;
|
||||||
|
}
|
||||||
|
}
|
49
packages/flutter/lib/src/services/path_provider.dart
Normal file
49
packages/flutter/lib/src/services/path_provider.dart
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:sky_services/flutter/platform/path_provider.mojom.dart' as mojom;
|
||||||
|
|
||||||
|
import 'shell.dart';
|
||||||
|
|
||||||
|
mojom.PathProviderProxy _initPathProviderProxy() {
|
||||||
|
mojom.PathProviderProxy proxy = new mojom.PathProviderProxy.unbound();
|
||||||
|
shell.connectToViewAssociatedService(proxy);
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
final mojom.PathProviderProxy _pathProviderProxy = _initPathProviderProxy();
|
||||||
|
|
||||||
|
/// Returns commonly used locations on the filesystem.
|
||||||
|
class PathProvider {
|
||||||
|
PathProvider._();
|
||||||
|
|
||||||
|
/// Path to the temporary directory on the device. Files in this directory
|
||||||
|
/// may be cleared at any time. This does *not* return a new temporary
|
||||||
|
/// directory. Instead, the caller is responsible for creating
|
||||||
|
/// (and cleaning up) files or directories within this directory. This
|
||||||
|
/// directory is scoped to the calling application.
|
||||||
|
///
|
||||||
|
/// Examples:
|
||||||
|
///
|
||||||
|
/// * _iOS_: `NSTemporaryDirectory()`
|
||||||
|
/// * _Android_: `getCacheDir()` on the context.
|
||||||
|
static Future<Directory> getTemporaryDirectory() async {
|
||||||
|
return new Directory((await _pathProviderProxy.ptr.temporaryDirectory()).path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Path to a directory where the application may place files that are private
|
||||||
|
/// to the application and will only be cleared when the application itself
|
||||||
|
/// is deleted.
|
||||||
|
///
|
||||||
|
/// Examples:
|
||||||
|
///
|
||||||
|
/// * iOS: `NSDocumentsDirectory`
|
||||||
|
/// * Android: The AppData directory.
|
||||||
|
static Future<Directory> getApplicationDocumentsDirectory() async {
|
||||||
|
return new Directory((await _pathProviderProxy.ptr.applicationDocumentsDirectory()).path);
|
||||||
|
}
|
||||||
|
}
|
62
packages/flutter/lib/src/services/system_chrome.dart
Normal file
62
packages/flutter/lib/src/services/system_chrome.dart
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:sky_services/flutter/platform/system_chrome.mojom.dart' as mojom;
|
||||||
|
|
||||||
|
import 'shell.dart';
|
||||||
|
|
||||||
|
export 'package:sky_services/flutter/platform/system_chrome.mojom.dart' show DeviceOrientation, SystemUIOverlay;
|
||||||
|
|
||||||
|
mojom.SystemChromeProxy _initSystemChromeProxy() {
|
||||||
|
mojom.SystemChromeProxy proxy = new mojom.SystemChromeProxy.unbound();
|
||||||
|
shell.connectToViewAssociatedService(proxy);
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
final mojom.SystemChromeProxy _systemChromeProxy = _initSystemChromeProxy();
|
||||||
|
|
||||||
|
/// Controls specific aspects of the embedder interface.
|
||||||
|
class SystemChrome {
|
||||||
|
SystemChrome._();
|
||||||
|
|
||||||
|
/// Specifies the set of orientations the application interface can
|
||||||
|
/// be displayed in.
|
||||||
|
///
|
||||||
|
/// Arguments:
|
||||||
|
///
|
||||||
|
/// * `device_orientation_mask`: 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<bool> setPreferredOrientations(int deviceOrientationMask) async {
|
||||||
|
return (await _systemChromeProxy.ptr.setPreferredOrientations(deviceOrientationMask)).success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Specifies the set of overlays visible on the embedder when the
|
||||||
|
/// application is running. The embedder may choose to ignore unsupported
|
||||||
|
/// overlays
|
||||||
|
///
|
||||||
|
/// Arguments:
|
||||||
|
///
|
||||||
|
/// * `style`: 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<bool> setEnabledSystemUIOverlays(int overlaysMask) async {
|
||||||
|
return (await _systemChromeProxy.ptr.setEnabledSystemUiOverlays(overlaysMask)).success;
|
||||||
|
}
|
||||||
|
}
|
37
packages/flutter/lib/src/services/system_sound.dart
Normal file
37
packages/flutter/lib/src/services/system_sound.dart
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:sky_services/flutter/platform/system_sound.mojom.dart' as mojom;
|
||||||
|
|
||||||
|
import 'shell.dart';
|
||||||
|
|
||||||
|
export 'package:sky_services/flutter/platform/system_sound.mojom.dart' show SystemSoundType;
|
||||||
|
|
||||||
|
mojom.SystemSoundProxy _initSystemSoundProxy() {
|
||||||
|
mojom.SystemSoundProxy proxy = new mojom.SystemSoundProxy.unbound();
|
||||||
|
shell.connectToViewAssociatedService(proxy);
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<bool> play(mojom.SystemSoundType type) async {
|
||||||
|
return (await _systemChromeProxy.ptr.play(type)).success;
|
||||||
|
}
|
||||||
|
}
|
@ -217,7 +217,7 @@ class LongPressDraggable<T> extends DraggableBase<T> {
|
|||||||
..onStart = (Point position) {
|
..onStart = (Point position) {
|
||||||
Drag result = onStart(position);
|
Drag result = onStart(position);
|
||||||
if (result != null)
|
if (result != null)
|
||||||
userFeedback.performHapticFeedback(HapticFeedbackType.virtualKey);
|
HapticFeedback.vibrate();
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user