Commit 7421b5a0 authored by Gavin An's avatar Gavin An

fcm 동작 이해

parent 5bbe2a21
...@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME ...@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
...@@ -20,7 +20,7 @@ plugins { ...@@ -20,7 +20,7 @@ plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0" id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.2.2" apply false id "com.android.application" version "8.2.2" apply false
id "org.jetbrains.kotlin.android" version "1.9.10" apply false id "org.jetbrains.kotlin.android" version "1.9.10" apply false
id "com.google.gms.google-services" version "4.3.15" apply false id "com.google.gms.google-services" version "4.4.1" apply false
} }
include ":app" include ":app"
...@@ -5,11 +5,13 @@ import 'package:dispatcher_test/firebase_options.dart'; ...@@ -5,11 +5,13 @@ import 'package:dispatcher_test/firebase_options.dart';
import 'package:dispatcher_test/notification_page.dart'; import 'package:dispatcher_test/notification_page.dart';
import 'package:dispatcher_test/speech_to_text_page.dart'; import 'package:dispatcher_test/speech_to_text_page.dart';
import 'package:dispatcher_test/text_to_speech_page.dart'; import 'package:dispatcher_test/text_to_speech_page.dart';
import 'package:dispatcher_test/text_to_speech_util.dart';
import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:speech_to_text/speech_to_text.dart';
const List<String> sample = [ const List<String> sample = [
'배고프다', '배고프다',
...@@ -26,10 +28,76 @@ const List<String> sample = [ ...@@ -26,10 +28,76 @@ const List<String> sample = [
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
await setupFlutterNotifications(); await setupFlutterNotifications();
showFlutterNotification(message);
// If you're going to use other Firebase services in the background, such as Firestore, // If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call `initializeApp` before using other Firebase services. // make sure you call `initializeApp` before using other Firebase services.
print('Handling a background message ${message.messageId}'); print('Handling a background message ${message.messageId}');
// RemoteMessage? msg = await FirebaseMessaging.instance.getInitialMessage();
// showFlutterNotification(msg);
RemoteNotification? notification = message.notification;
if (notification != null) {
TextToSpeechUtil.speakTo(notification.body ?? '');
}
}
void showFlutterNotification(RemoteMessage? message) {
if (message == null) return;
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
'타이틀: ${notification.title}',
'바디: ${notification.body}',
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channelDescription: channel.description,
icon: 'launch_background',
),
),
);
}
}
/// Create a [AndroidNotificationChannel] for heads up notifications
late AndroidNotificationChannel channel;
bool isFlutterLocalNotificationsInitialized = false;
/// Initialize the [FlutterLocalNotificationsPlugin] package.
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
Future<void> setupFlutterNotifications() async {
if (isFlutterLocalNotificationsInitialized) {
return;
}
channel = const AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
description:
'This channel is used for important notifications.', // description
importance: Importance.high,
);
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
/// Create an Android Notification Channel.
///
/// We use this channel in the `AndroidManifest.xml` file to override the
/// default FCM channel to enable heads up notifications.
await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation
<AndroidFlutterLocalNotificationsPlugin>()?.createNotificationChannel(channel);
/// Update the iOS foreground notification presentation options to allow
/// heads up notifications.
await FirebaseMessaging
.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
isFlutterLocalNotificationsInitialized = true;
} }
...@@ -37,9 +105,15 @@ void main() async { ...@@ -37,9 +105,15 @@ void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
// FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
FirebaseFirestore.instance.settings = const Settings( FirebaseFirestore.instance.settings = const Settings(
persistenceEnabled: true, persistenceEnabled: true,
); );
// final fcmToken = await FirebaseMessaging.instance.getToken();
// print('fcmToken: $fcmToken');
if (!kIsWeb) {
await setupFlutterNotifications();
}
runApp(const MyApp()); runApp(const MyApp());
} }
...@@ -52,21 +126,6 @@ class MyApp extends StatelessWidget { ...@@ -52,21 +126,6 @@ class MyApp extends StatelessWidget {
return MaterialApp( return MaterialApp(
title: 'Dispatcher TEST', title: 'Dispatcher TEST',
theme: ThemeData( theme: ThemeData(
// This is the theme of your application.
//
// TRY THIS: Try running your application with "flutter run". You'll see
// the application has a purple toolbar. Then, without quitting the app,
// try changing the seedColor in the colorScheme below to Colors.green
// and then invoke "hot reload" (save your changes or press the "hot
// reload" button in a Flutter-supported IDE, or press "r" if you used
// the command line to start the app).
//
// Notice that the counter didn't reset back to zero; the application
// state is not lost during the reload. To reset the state, use hot
// restart instead.
//
// This works for code too, not just values: Most code changes can be
// tested with just a hot reload.
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true, useMaterial3: true,
), ),
...@@ -77,16 +136,6 @@ class MyApp extends StatelessWidget { ...@@ -77,16 +136,6 @@ class MyApp extends StatelessWidget {
class MyHomePage extends StatefulWidget { class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title}); const MyHomePage({super.key, required this.title});
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title; final String title;
@override @override
...@@ -112,20 +161,9 @@ class _MyHomePageState extends State<MyHomePage> { ...@@ -112,20 +161,9 @@ class _MyHomePageState extends State<MyHomePage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
// TRY THIS: Try changing the color here to a specific color (to
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
// change color while the other colors stay the same.
backgroundColor: Theme.of(context).colorScheme.inversePrimary, backgroundColor: Theme.of(context).colorScheme.inversePrimary,
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title), title: Text(widget.title),
), ),
body: Column( body: Column(
......
...@@ -107,14 +107,14 @@ class _TextToSpeechPageState extends State<TextToSpeechPage> { ...@@ -107,14 +107,14 @@ class _TextToSpeechPageState extends State<TextToSpeechPage> {
Future<dynamic> _getEngines() async => await flutterTts.getEngines; Future<dynamic> _getEngines() async => await flutterTts.getEngines;
Future<void> _getDefaultEngine() async { Future<void> _getDefaultEngine() async {
var engine = await flutterTts.getDefaultEngine; dynamic engine = await flutterTts.getDefaultEngine;
if (engine != null) { if (engine != null) {
print(engine); print(engine);
} }
} }
Future<void> _getDefaultVoice() async { Future<void> _getDefaultVoice() async {
var voice = await flutterTts.getDefaultVoice; dynamic voice = await flutterTts.getDefaultVoice;
if (voice != null) { if (voice != null) {
print(voice); print(voice);
} }
...@@ -233,9 +233,10 @@ class _TextToSpeechPageState extends State<TextToSpeechPage> { ...@@ -233,9 +233,10 @@ class _TextToSpeechPageState extends State<TextToSpeechPage> {
} else } else
return const Text('Loading engines...'); return const Text('Loading engines...');
}); });
} else } else {
return Container(width: 0, height: 0); return Container(width: 0, height: 0);
} }
}
Widget _futureBuilder() => FutureBuilder<dynamic>( Widget _futureBuilder() => FutureBuilder<dynamic>(
future: _getLanguages(), future: _getLanguages(),
...@@ -246,7 +247,8 @@ class _TextToSpeechPageState extends State<TextToSpeechPage> { ...@@ -246,7 +247,8 @@ class _TextToSpeechPageState extends State<TextToSpeechPage> {
return const Text('Error loading languages...'); return const Text('Error loading languages...');
} else } else
return const Text('Loading Languages...'); return const Text('Loading Languages...');
}); },
);
Widget _inputSection() => Container( Widget _inputSection() => Container(
alignment: Alignment.topCenter, alignment: Alignment.topCenter,
...@@ -265,12 +267,27 @@ class _TextToSpeechPageState extends State<TextToSpeechPage> { ...@@ -265,12 +267,27 @@ class _TextToSpeechPageState extends State<TextToSpeechPage> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
_buildButtonColumn(Colors.green, Colors.greenAccent, Icons.play_arrow,
'PLAY', _speak),
_buildButtonColumn( _buildButtonColumn(
Colors.red, Colors.redAccent, Icons.stop, 'STOP', _stop), Colors.green,
Colors.greenAccent,
Icons.play_arrow,
'PLAY',
_speak,
),
_buildButtonColumn(
Colors.red,
Colors.redAccent,
Icons.stop,
'STOP',
_stop,
),
_buildButtonColumn( _buildButtonColumn(
Colors.blue, Colors.blueAccent, Icons.pause, 'PAUSE', _pause), Colors.blue,
Colors.blueAccent,
Icons.pause,
'PAUSE',
_pause,
),
], ],
), ),
); );
...@@ -299,8 +316,13 @@ class _TextToSpeechPageState extends State<TextToSpeechPage> { ...@@ -299,8 +316,13 @@ class _TextToSpeechPageState extends State<TextToSpeechPage> {
), ),
])); ]));
Column _buildButtonColumn(Color color, Color splashColor, IconData icon, Column _buildButtonColumn(
String label, Function func) { Color color,
Color splashColor,
IconData icon,
String label,
Function func,
) {
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
......
import 'package:flutter_tts/flutter_tts.dart';
class TextToSpeechUtil {
static Future<void> speakTo(String str) async {
FlutterTts flutterTts = FlutterTts();
await flutterTts.setVolume(1);
await flutterTts.setSpeechRate(0.5);
await flutterTts.setPitch(1);
await flutterTts.speak(str);
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment