- main 문서에서는 타이머로 1초마다 1씩 증가시켜서 표시하구요
푸시알림에도 버튼을 달아서 숫자를 표시합니다.
- notification 문서에서는 포어그라운드 서비스에 관한 내용을 정의 했습니다
- 목적은 노티피케이션 버튼의 bt_pause 버튼을 눌러서 main문서의 onPausePressed() 메서드를 호출해서 타이머를 정지시키고 싶습니다
- 글로벌 키를 사용해봤는데도 안돼요.
//main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'notification.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Color.fromARGB(255, 68, 68, 68),
body: timer(
key: timerStateKey,
),
),
);
}
}
final GlobalKey<_timerState> timerStateKey = GlobalKey<_timerState>();
class timer extends StatefulWidget {
const timer({super.key});
@override
State<timer> createState() => _timerState();
}
class _timerState extends State<timer> {
int countingNumber = 0;
Timer? timer;
// 변수 초기화==========================================================//
@override
void initState() {
// TODO: implement initState
super.initState();
permissionWithNotification();
flutterForegroundTaskInit();
startCounting();
}
//=====================================================================//
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Center(
child: Text(
'$countingNumber',
style: TextStyle(fontSize: 40, color: Colors.white70),
),
)
],
);
}
//타이머 시작
void startCounting() {
print('onStartPressed 메서드 호출');
timer = Timer.periodic(const Duration(milliseconds: 1000), (timer) {
onTick(timer);
});
startForegroundTask();
}
//타이머 굴러가게 하는 함수
void onTick(Timer timer) {
setState(() {
countingNumber++;
});
updateForegroundTask_Timer(countingNumber);
}
// 타이머 정지
void onPausePressed() {
print('onPausePressed 메서드 호출');
timer?.cancel();
}
}
--------------------------------------------------------------------------------------------------------
//notification.dart
import 'package:exit_test/main.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
import 'dart:isolate';
//foreground task 서비스 초기화
void flutterForegroundTaskInit() {
print('flutterForegroundTaskInit() 호출');
FlutterForegroundTask.init(
androidNotificationOptions: AndroidNotificationOptions(
channelId: 'test_notificaion',
channelName: 'test notification',
channelDescription: 'test notifications..',
channelImportance: NotificationChannelImportance.LOW,
priority: NotificationPriority.HIGH,
playSound: false,
enableVibration: false,
),
iosNotificationOptions: IOSNotificationOptions(
showNotification: true,
playSound: false,
),
foregroundTaskOptions: const ForegroundTaskOptions(
interval: 5000,
isOnceEvent: false,
autoRunOnBoot: true,
allowWakeLock: true,
allowWifiLock: true,
),
);
}
// 푸시알림 노티피케이션 권한에 대해 요청
void permissionWithNotification() async {
if (await Permission.notification.isDenied &&
!await Permission.notification.isPermanentlyDenied) {
await [Permission.notification].request();
}
}
// 포어그라운드 서비스의 푸시알림 서비스 시작
void startForegroundTask() async {
await FlutterForegroundTask.startService(
notificationTitle: 'TEST',
notificationText: '0',
notificationButtons: [
NotificationButton(id: 'bt_pause', text: 'Pause'),
NotificationButton(id: 'bt_close', text: 'Close'),
],
callback: _startCallback);
print('startForegroundTask() 호출');
}
// 알림패널의 알림을 초마다 갱신
void updateForegroundTask_Timer(int number) {
FlutterForegroundTask.updateService(
notificationTitle: 'TEST', notificationText: '${number.toString()}');
}
// 알림패널 서비스를 종료
void stopForegroundTask() {
FlutterForegroundTask.stopService();
print('ForegroundService 종료');
}
// 백그라운드에서 실행될 콜백 함수
void _startCallback() {
// 여기에 백그라운드에서 실행될 로직을 구현
FlutterForegroundTask.setTaskHandler(MyTaskHandler());
}
class MyTaskHandler extends TaskHandler {
@override
Future<void> onStart(DateTime timestamp, SendPort? sendPort) async {}
@override
Future<void> onEvent(DateTime timestamp, SendPort? sendPort) async {}
@override
Future<void> onRepeatEvent(DateTime timestamp, SendPort? sendPort) async {}
@override
Future<void> onDestroy(DateTime timestamp, SendPort? sendPort) async {}
@override
void onNotificationButtonPressed(String id) {
print('버튼 콜백 호출됨: $id'); // 버튼 ID를 로그에 출력
// TODO: implement onNotificationButtonPressed
super.onNotificationButtonPressed(id);
switch (id) {
case 'bt_pause':
print('버튼 1 클릭됨');
timerStateKey.currentState?.onPausePressed();
break;
case 'bt_close':
print('버튼 2 클릭됨');
break;
default:
print('디폴트');
}
}
}
해봐
선생님 질문 올렸습니다
gpt는 신인데 걔도 모르면 걍 포기하고 자살해라
currentState 라는 식별자는 어디서정의도는거임? 저거 ?붙이면서 널 나오는 거 아님? 참고로 나 플러터 모름.
그냥 글로벌키에 원래 있는건데 ?붙이면 null일수도 아닐수도 있다라는거