Last active
February 22, 2023 02:41
-
-
Save AlexV525/e4b60cb3553d98c12d9a806d297b2698 to your computer and use it in GitHub Desktop.
How to set the highest refresh rate on Android in Flutter using `flutter_displaymode`?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// | |
/// [Author] Alex (https://github.com/AlexV525) | |
/// [Date] 2022/03/07 23:25 | |
/// | |
import 'dart:async'; | |
import 'dart:io'; | |
import 'package:device_info_plus/device_info_plus.dart'; | |
import 'package:flutter/gestures.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter_displaymode/flutter_displaymode.dart'; | |
void main() async { | |
WidgetsFlutterBinding.ensureInitialized(); | |
if (Platform.isAndroid) { | |
DeviceUtil.androidInfo = await DeviceInfoPlugin().androidInfo; | |
} | |
DeviceUtil.setHighestRefreshRate(); | |
runApp(const App()); | |
} | |
class App extends StatefulWidget { | |
const App({Key? key}) : super(key: key); | |
@override | |
State<App> createState() => AppState(); | |
} | |
class AppState extends State<App> with WidgetsBindingObserver { | |
@override | |
void initState() { | |
super.initState(); | |
DeviceUtil.setHighestRefreshRate(); | |
} | |
@override | |
void didChangeAppLifecycleState(AppLifecycleState state) { | |
if (state == AppLifecycleState.resumed) { | |
DeviceUtil.setHighestRefreshRate(); | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
return const MaterialApp(home: SizedBox.shrink()); | |
} | |
} | |
class DeviceUtil { | |
const DeviceUtil._(); | |
static AndroidDeviceInfo? androidInfo; | |
static DisplayMode? _highestRefreshRateMode; | |
static Future<void> setHighestRefreshRate() async { | |
if (!Platform.isAndroid || androidInfo?.version.sdkInt == null) { | |
return; | |
} | |
// Apply only on Android 23+. | |
final int sdkInt = DeviceUtil.androidInfo!.version.sdkInt!; | |
if (sdkInt < 23) { | |
return; | |
} | |
// Delay 1 second since bindings will need to reconnect. | |
await Future.delayed(const Duration(seconds: 1)); | |
final DisplayMode current = await FlutterDisplayMode.active; | |
// Search for the highest refresh rate and save. | |
if (_highestRefreshRateMode == null) { | |
final List<DisplayMode> modes = await FlutterDisplayMode.supported; | |
modes.removeWhere( | |
(DisplayMode e) => | |
e.width != current.width || e.height != current.height, | |
); | |
if (modes.isNotEmpty) { | |
modes.sort( | |
(DisplayMode a, DisplayMode b) => | |
a.refreshRate.compareTo(b.refreshRate), | |
); | |
_highestRefreshRateMode = modes.lastOrNull; | |
} | |
} | |
final DisplayMode? highest = _highestRefreshRateMode; | |
if (highest == null) { | |
return; | |
} | |
// Apply when the current refresh rate is lower than the highest. | |
if (current.refreshRate < highest.refreshRate) { | |
print( | |
'Setting a higher refresh rate ' | |
'from ${current.refreshRate} ' | |
'to ${highest.refreshRate}.', | |
); | |
await FlutterDisplayMode.setPreferredMode(highest); | |
final DisplayMode newMode = await FlutterDisplayMode.active; | |
// Only apply resampling when the refresh rate has been updated. | |
if (newMode.refreshRate > current.refreshRate) { | |
GestureBinding.instance.resamplingEnabled = true; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment