
Wakelock Plus는 Flutter 앱에서 디바이스의 화면이 자동으로 꺼지는 것을 방지하는 패키지입니다. 특히 동영상 재생, 프레젠테이션, 게임, 운동 앱 등에서 화면이 계속 켜져있어야 하는 상황에 필수적입니다.
dependencies:
flutter:
sdk: flutter
wakelock_plus: ^1.2.8
flutter pub get
import 'package:wakelock_plus/wakelock_plus.dart';
// 화면 꺼짐 방지 활성화
await WakelockPlus.enable();
// 화면 꺼짐 방지 비활성화
await WakelockPlus.disable();
// 현재 wakelock이 활성화되어 있는지 확인
bool isEnabled = await WakelockPlus.enabled;
print('Wakelock 상태: $isEnabled');
// 현재 상태를 반전시키기
bool currentState = await WakelockPlus.enabled;
if (currentState) {
await WakelockPlus.disable();
} else {
await WakelockPlus.enable();
}
enum AppState { idle, working, gaming, presenting }
class WakelockManager {
static AppState _currentState = AppState.idle;
static Future<void> updateState(AppState newState) async {
_currentState = newState;
switch (newState) {
case AppState.idle:
await WakelockPlus.disable();
break;
case AppState.working:
case AppState.gaming:
case AppState.presenting:
await WakelockPlus.enable();
break;
}
}
static AppState get currentState => _currentState;
static Future<bool> get isWakelockEnabled => WakelockPlus.enabled;
}
class TimedWakelock {
static Timer? _timer;
static Future<void> enableForDuration(Duration duration) async {
await WakelockPlus.enable();
_timer?.cancel();
_timer = Timer(duration, () async {
await WakelockPlus.disable();
print('Wakelock이 자동으로 해제되었습니다.');
});
}
static Future<void> cancel() async {
_timer?.cancel();
await WakelockPlus.disable();
}
}
// 사용 예시
TimedWakelock.enableForDuration(Duration(minutes: 30)); // 30분 후 자동 해제
class ConditionalWakelock {
static bool _userPreference = true;
static bool _batteryOptimized = false;
static Future<void> enableIfAllowed() async {
if (_userPreference && !_batteryOptimized) {
await WakelockPlus.enable();
}
}
static void setUserPreference(bool enabled) {
_userPreference = enabled;
if (!enabled) {
WakelockPlus.disable();
}
}
static void setBatteryOptimization(bool optimized) {
_batteryOptimized = optimized;
if (optimized) {
WakelockPlus.disable();
}
}
}
class WakelockToggleWidget extends StatefulWidget {
final String title;
final VoidCallback? onChanged;
const WakelockToggleWidget({
Key? key,
this.title = 'Keep Screen On',
this.onChanged,
}) : super(key: key);
_WakelockToggleWidgetState createState() => _WakelockToggleWidgetState();
}
class _WakelockToggleWidgetState extends State<WakelockToggleWidget> {
bool _isEnabled = false;
void initState() {
super.initState();
_checkWakelockStatus();
}
Future<void> _checkWakelockStatus() async {
bool enabled = await WakelockPlus.enabled;
setState(() => _isEnabled = enabled);
}
Future<void> _toggleWakelock() async {
if (_isEnabled) {
await WakelockPlus.disable();
} else {
await WakelockPlus.enable();
}
bool newState = await WakelockPlus.enabled;
setState(() => _isEnabled = newState);
widget.onChanged?.call();
}
Widget build(BuildContext context) {
return Card(
child: ListTile(
leading: Icon(
_isEnabled ? Icons.screen_lock_portrait : Icons.screen_lock_landscape,
color: _isEnabled ? Colors.green : Colors.grey,
),
title: Text(widget.title),
subtitle: Text(_isEnabled ? '화면이 꺼지지 않습니다' : '화면이 자동으로 꺼집니다'),
trailing: Switch(
value: _isEnabled,
onChanged: (_) => _toggleWakelock(),
activeColor: Colors.green,
),
onTap: _toggleWakelock,
),
);
}
}
// ❌ 잘못된 사용
class BadExample extends StatefulWidget {
void initState() {
super.initState();
WakelockPlus.enable(); // 항상 켜둠 - 배터리 소모
}
}
// ✅ 올바른 사용
class GoodExample extends StatefulWidget {
void initState() {
super.initState();
// 필요할 때만 활성화
}
void startImportantTask() {
WakelockPlus.enable(); // 작업 시작 시에만
}
void finishImportantTask() {
WakelockPlus.disable(); // 작업 완료 시 해제
}
}
class ProperLifecycleManagement extends StatefulWidget with WidgetsBindingObserver {
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.paused:
// 앱이 백그라운드로 갈 때 해제
WakelockPlus.disable();
break;
case AppLifecycleState.resumed:
// 필요한 경우에만 다시 활성화
if (shouldKeepScreenOn()) {
WakelockPlus.enable();
}
break;
}
}
void dispose() {
WidgetsBinding.instance.removeObserver(this);
WakelockPlus.disable(); // 반드시 해제
super.dispose();
}
}
class UserFriendlyWakelock {
static const String _prefKey = 'wakelock_enabled';
static Future<bool> getUserPreference() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getBool(_prefKey) ?? true;
}
static Future<void> setUserPreference(bool enabled) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setBool(_prefKey, enabled);
}
static Future<void> enableWithUserConsent() async {
bool userAllowed = await getUserPreference();
if (userAllowed) {
await WakelockPlus.enable();
}
}
}
class WakelockDebugger {
static void startMonitoring() {
Timer.periodic(Duration(seconds: 5), (timer) async {
bool isEnabled = await WakelockPlus.enabled;
print('Wakelock 상태: ${isEnabled ? "활성화" : "비활성화"}');
});
}
static Future<void> logStateChange(String action) async {
bool stateBefore = await WakelockPlus.enabled;
print('[$action] 이전 상태: $stateBefore');
// 액션 수행 후
await Future.delayed(Duration(milliseconds: 100));
bool stateAfter = await WakelockPlus.enabled;
print('[$action] 이후 상태: $stateAfter');
}
}
void main() {
group('Wakelock Tests', () {
test('should enable wakelock', () async {
await WakelockPlus.enable();
bool isEnabled = await WakelockPlus.enabled;
expect(isEnabled, true);
});
test('should disable wakelock', () async {
await WakelockPlus.disable();
bool isEnabled = await WakelockPlus.enabled;
expect(isEnabled, false);
});
test('should toggle wakelock', () async {
bool initialState = await WakelockPlus.enabled;
if (initialState) {
await WakelockPlus.disable();
} else {
await WakelockPlus.enable();
}
bool finalState = await WakelockPlus.enabled;
expect(finalState, !initialState);
});
});
}
Wakelock Plus는 사용자 경험을 크게 향상시킬 수 있는 강력한 도구입니다. 하지만 배터리 소모와 사용자 편의성 사이의 균형을 잘 맞춰야 합니다.