はじめに
package:flutter/foundation.dart
で提供されるdebugDefaultTargetPlatformOverride
について解説します。
2020/03/10 追記
Add Linux and Windows target platformsのissueで正式対応されたため、本記事のdebugDefaultTargetPlatformOverride
の対応が不要になります!まだmaster
チャンネルのみですが。
用途
用途は主に以下の2つです。
- 今時点でFlutterのデスクトップ向けのコードを書く場合 (以下のサンプルコード参照)
- 例えばAndroid端末でiOS仕様の挙動の確認をしたいなど (実機と異なるプラットフォームの動作確認) の場合
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app/my_app.dart';
void _setOverrideForDesktop() {
if (kIsWeb) return;
if (Platform.isMacOS) {
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
} else if (Platform.isLinux || Platform.isWindows) {
debugDefaultTargetPlatformOverride = TargetPlatform.android; // ← Linux/Windowsデスクトップ向けはこれが必要!
} else if (Platform.isFuchsia) {
debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
}
}
void main() {
_setOverrideForDesktop();
runApp(MyMaterialApp());
}
debugDefaultTargetPlatformOverrideとは何?
debugDefaultTargetPlatformOverride
は本来ターゲットとするプラットフォームから強制的に別のプラットフォーム向けの挙動に変えるためのデバッグ専用のプロパティです。
debugDefaultTargetPlatformOverride
はデフォルトnullで、この場合はアプリがターゲットのプラットフォーム向けの挙動になります。一方、上記のように何らかの値が設定されている場合には、強制的に指定されたプラットフォームの挙動をするようになります。
デスクトップ for Linux/Windows向けの現状
foundation/_platform_io.dartのソースコードを見てみると、WindowsやLinuxの正式対応がまだされておらず、debugDefaultTargetPlatformOverride
を使って何かのプラットフォームを指定しないとダメなことがわかります。
import 'dart:io';
import 'assertions.dart';
import 'platform.dart' as platform;
/// The dart:io implementation of [platform.defaultTargetPlatform].
platform.TargetPlatform get defaultTargetPlatform {
platform.TargetPlatform result;
if (Platform.isIOS) {
result = platform.TargetPlatform.iOS;
} else if (Platform.isMacOS) {
result = platform.TargetPlatform.macOS;
} else if (Platform.isAndroid) {
result = platform.TargetPlatform.android;
} else if (Platform.isFuchsia) {
result = platform.TargetPlatform.fuchsia;
}
assert(() {
if (Platform.environment.containsKey('FLUTTER_TEST'))
result = platform.TargetPlatform.android;
return true;
}());
if (platform.debugDefaultTargetPlatformOverride != null)
result = platform.debugDefaultTargetPlatformOverride;
if (result == null) {
throw FlutterError(
'Unknown platform.\n'
'${Platform.operatingSystem} was not recognized as a target platform. '
'Consider updating the list of TargetPlatforms to include this platform.'
);
}
return result;
}
プラットフォーム毎に何が違う?
では、プラットフォーム毎に何が違うのでしょうか?
それを解決するためには、defaultTargetPlatform
をFlutter Frameworkのソースコードで grep してみると分かります。
一番分かりやすいのは、CupertinoSwitch
です。
ソースコードのflutter/packages/flutter/lib/src/cupertino/switch.dartを見てみます。
iOSだけHapticFeedback.lightImpact()
をコールしています。
void _emitVibration() {
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
HapticFeedback.lightImpact();
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.macOS:
break;
}
}
HapticFeedback.lightImpact()
を追いかけてみると、SystemChannels APIを利用してプラットフォーム側のバイブレーション機能を呼び出しています。
結局この場合はハードウェアの実物がないと特に差分無しという感じになりますね。
なお、SystemCHannels APIんついては、Flutter プラットフォーム固有機能を利用するためのSystemChannels APIについてにまとめていますので参考にして下さい。
flutter/packages/flutter/lib/src/services/haptic_feedback.dar
/// Provides a haptic feedback corresponding a collision impact with a light mass.
///
/// On iOS versions 10 and above, this uses a `UIImpactFeedbackGenerator` with
/// `UIImpactFeedbackStyleLight`. This call has no effects on iOS versions
/// below 10.
///
/// On Android, this uses `HapticFeedbackConstants.VIRTUAL_KEY`.
static Future<void> lightImpact() async {
await SystemChannels.platform.invokeMethod<void>(
'HapticFeedback.vibrate',
'HapticFeedbackType.lightImpact',
);
}