Skip to content

Instantly share code, notes, and snippets.

@AlexV525
Last active February 22, 2023 02:41
Show Gist options
  • Save AlexV525/e4b60cb3553d98c12d9a806d297b2698 to your computer and use it in GitHub Desktop.
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`?
///
/// [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