Step 1: Create a Flutter project
If you haven't installed Flutter yet, follow the instructions on the official Flutter website to do so. After that, create a new Flutter project using the following command:
flutter create push_notification
cd push_notification
Step 2: Set Up dependencies
Add the plugins to your pubspec.yaml file and run flutter pub get
to install the dependencies as shown below.
dependencies:
firebase_core: ^3.12.0
flutter_local_notifications: ^19.0.0
firebase_messaging: ^15.2.2
googleapis_auth: ^1.6.0
http: ^1.2.1
Step 3: Create your Firebase project
1. Create a Firebase Project
Go to the Firebase Consoleand log in with your Google account.
Click on Create a project, enter the project name, and follow the setup instructions.
2. Add Your Flutter App to Firebase
In the Firebase console, select your project and click Add app.
Choose the platform: Android or iOS.
For Android, provide the package name (found in android/app/build.gradle
).
For iOS, provide the Bundle ID (found in ios/Runner.xcodeproj
).
3. Download the Configuration File
For Android, download the google-services.json file and place it inside android/app/.
For iOS, download the GoogleService-Info.plist file and place it inside ios/Runner/.
4. Configure Firebase in the Flutter Project
Update the Android configuration:
Modify android/build.gradle and android/app/build.gradle to include Firebase dependencies.
5. Initialize Firebase in Flutter
import 'package:firebase_core/firebase_core.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(MyApp()); }
Step 4: Create a file named notification_service.dart
in your project. Then, copy and paste the following content into the file.
import 'dart:convert'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; class AppNotification { final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); AndroidNotificationChannel channel = const AndroidNotificationChannel( 'high_app_notif_channel', // id 'High Importance Notifications', // title description: 'This channel is used for important notifications', // description importance: Importance.max, showBadge: true ); initializeFcmNotification() async { await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(channel); const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); final DarwinInitializationSettings initializationSettingsIOS = DarwinInitializationSettings( requestSoundPermission: true, requestBadgePermission: true, requestAlertPermission: true, defaultPresentAlert: true, defaultPresentSound: true, defaultPresentBadge: true, ); final InitializationSettings initializationSettings = InitializationSettings( android: initializationSettingsAndroid, iOS: initializationSettingsIOS, ); await flutterLocalNotificationsPlugin.initialize( initializationSettings, onDidReceiveNotificationResponse: (payload) async{ }, ); await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< IOSFlutterLocalNotificationsPlugin>() ?.requestPermissions( alert: true, badge: true, sound: true, ); await FirebaseMessaging.instance .setForegroundNotificationPresentationOptions( alert: true, badge: true, sound: true, ); FirebaseMessaging.onMessage.listen((RemoteMessage message) async { RemoteNotification? notification = message.notification; AndroidNotification? android = message.notification?.android; if (notification != null && android != null) { flutterLocalNotificationsPlugin.show( notification.hashCode, notification.title, notification.body, NotificationDetails( ///android platform specific android: AndroidNotificationDetails(channel.id, channel.name, channelDescription: channel.description, importance: Importance.max, priority: Priority.high, channelShowBadge: true, enableVibration: true, enableLights: true, icon: android.smallIcon ), iOS: const DarwinNotificationDetails( presentSound: true, presentBadge: true, presentAlert: true), ), payload: jsonEncode(message.data), ); } }, ); FirebaseMessaging.onMessageOpenedApp.listen( (RemoteMessage message) { //log('Message Opened CallBack $message'); //log('Message Opened CallBack'); }, ); } }
Step 5: Go to your Firebase project
Select the project, click on the settings icon, and navigate to Project settings.
Step 6: Create a file named constant.dart
in your project. Then, copy and paste the following content into the file.
class AppConstant{ static final fcmUrl = "https://fcm.googleapis.com/v1/projects"; static final googleApi = "https://www.googleapis.com/auth/cloud-platform"; static final api = '${AppConstant.fcmUrl}/students-app-4b35f/messages:send'; }
In the following line:
static final api = '${AppConstant.fcmUrl}/students-app-4b35f/messages:send';
students-app-4b35f is the project ID. Copy it and replace it with the correct value from your Firebase project.
Step 7: Navigate through the menu bar and click on Service accounts
Then, click on Firebase Admin SDK with the key icon. Next, click on the Generate a new private key button. Save the file securely in a safe location.
Open the downloaded file and copy its content. It is in JSON format.
Step 8: Create a file named notification_network.dart
in your project. Then, copy and paste the following content into the file.
import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:googleapis_auth/auth_io.dart'; import 'package:http/http.dart' as http; import 'package:push_notification/constant.dart'; class SendNotificationAccess{ static final List<String> scopes = [ AppConstant.googleApi ]; static Future<String> getAccessToken() async { final serviceAccountCredentials = ServiceAccountCredentials.fromJson({ "type": "service_account", "project_id": "students-app-4b35f", "private_key_id": "2fa48b2f70407670e0c15998be363fb0ed399f82", "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDVHiDLCJDkNJhc\naA6v3Be7cu3bnfZc3E8reHl0c+lxZl2ygN1dWOpdM8ErhlF8aOHdsgYrGJ3txLhU\nPwHf3WpEiHsm2+dXBoEUPDm4kQkZRy0+HYr0jD2MuMeCiC9Sua62of/gp9tQp6m2\nwpKTle4ZPRpYv5AdTqTitl8EJKGj1JP0+mw19K3o7gTMyoY65T/Aw0RGkjBUBDVm\nZSz6nZYYW4H8M93KjO8jCeCWxUYfUe1qKlkJGLaKbxEOQJ6PiD+Vp6Jk4TOkmHht\n8IKmrm7PFt5Dul2D8aT/CorpMmWopjLp2ZhQOArhzByPpMpUyPPlAsleoYXdbSkX\nD29dBJabAgMBAAECggEAB6m8KyDFOPdtLRFuycMDtXFF/ToaVC91x03fLCFI2ROB\ntfvtOcCLOMu2G+8J+gu5Z2PR1fXeI+EJcboMQrTu78TqjLSmhloNBSG/P5QzfA2z\nokKkrvNl+SvhvJ9R+EsF7bo4fab7e1R0BUbMx3LCK3Unf95ve6ZKxn4hP4BjsYTP\n7otywZn3g4H2B47EPJfEL0VJK87hM85Z+f4679m0kcVgYqbcrGUCi6iNy0fLZ0Fu\nQtT4DvoSTqbsVD6zhakpFbtgJdMCslZYAjI02/qptTB/6RrbYJmOr3LLfM6kNJiL\n3/V1rLRb9WGrucfGGh2f25huEm1oBFPCoMRulMSUwQKBgQD8At1X8a6ZTrBKS1wH\nNc3sXb5e8y/DSv5xHU3gObgrTsNDlo6mNpsZrbFXkjaKdANZkB1JNgjknhgHVRQ/\njzkenYbDj8qSDYjV90EBJJSXhFv9QSbU0IiUci+N4vaX3hl+fMbCSYJZ5GtlzAPu\nRAZuJa0GCEkxeR6oCyc4y1bfWwKBgQDYfatODjQI0XwwpRYWzJmojZuGh+eA5Tih\nwZmPxeDBJ8mn7v0Dg3dobJcBg0V+HyFwBxweqLvsImpgjy6tgWccT0IuK0YMZT9J\nwhwUzEv0v4uOpyFcHE4ldkLnxmVo85YoxjolzSEPXjZjgA6YLh8HU22y8uQ0Q716\n9b0n08QJwQKBgHScCrmn3keYDqDCEBpR/jASDIW492/hYq0Khz9q1dpMPrQmlWk5\nuTj/kyDXSh90oRwvQC3hL+pBcRLrfkwOxLpy36nb/jrowllnaI/T0mHt3/bmz8YH\nnDs8Pt7jl4EcRyWtLPc3tnZL6JoY9fSpS2RqUI6LBPs8dUACsSpphJAjAoGAY/FI\nFyXJcdS7330nAGl9+mk9RlMRVdj8VviYWt5ADwu+Na/H0Ept4qBW6hTfDQV0G1K8\n8Y52CuIsd91B8EmP/2q7o7LIiMpo+DULX7Kc0iVnWPjhFrPeg77fzj4x7MyfIr24\ndGEJhR26QB8LHcgU/P3P48/r+BDZtZ0isPM7SkECgYEAgyAR1hG0rfrd9ajbGLpx\nXGJ7fo6vQW2OG96jGXpg12N70JwKtoAYw2ZaRn7ajSXXh8JFlyw5334uOO97+65D\n6dVG2T0KNh5FsrVptNZgZuc/PJXf4mEkYWVRHzE3VFfc0y4RBgVsN8cHpH9nIe3K\nhCfESjU6fePEAo1dFIUfTco=\n-----END PRIVATE KEY-----\n", "client_email": "firebase-adminsdk-fbsvc@students-app-4b35f.iam.gserviceaccount.com", "client_id": "110426202408684217122", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-fbsvc%40students-app-4b35f.iam.gserviceaccount.com", "universe_domain": "googleapis.com" } ); var client = http.Client(); AuthClient authClient = await clientViaServiceAccount(serviceAccountCredentials, scopes); final accessTokenData = authClient.credentials.accessToken.data; client.close(); return accessTokenData; } static sendNotificationWithHttp({required String token,required String title,required String body}) async { String accessToken = await getAccessToken(); Map<String, dynamic> payload = { "message": { "token": token, "notification": { "body": body, "title": title } } }; final response = await http.post(Uri.parse(AppConstant.api), headers: { 'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json', }, body: jsonEncode(payload)); if (response.statusCode == 200) { if (kDebugMode) { print('Notification send'); } } else { if (kDebugMode) { print('Notification Not send'); } } } }
Replace this part of the code (the JSON) with the content of the JSON file you downloaded.
{ "type": "service_account", "project_id": "students-app-4b35f", "private_key_id": "2fa48b2f70407670e0c15998be363fb0ed399f82", "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDVHiDLCJDkNJhc\naA6v3Be7cu3bnfZc3E8reHl0c+lxZl2ygN1dWOpdM8ErhlF8aOHdsgYrGJ3txLhU\nPwHf3WpEiHsm2+dXBoEUPDm4kQkZRy0+HYr0jD2MuMeCiC9Sua62of/gp9tQp6m2\nwpKTle4ZPRpYv5AdTqTitl8EJKGj1JP0+mw19K3o7gTMyoY65T/Aw0RGkjBUBDVm\nZSz6nZYYW4H8M93KjO8jCeCWxUYfUe1qKlkJGLaKbxEOQJ6PiD+Vp6Jk4TOkmHht\n8IKmrm7PFt5Dul2D8aT/CorpMmWopjLp2ZhQOArhzByPpMpUyPPlAsleoYXdbSkX\nD29dBJabAgMBAAECggEAB6m8KyDFOPdtLRFuycMDtXFF/ToaVC91x03fLCFI2ROB\ntfvtOcCLOMu2G+8J+gu5Z2PR1fXeI+EJcboMQrTu78TqjLSmhloNBSG/P5QzfA2z\nokKkrvNl+SvhvJ9R+EsF7bo4fab7e1R0BUbMx3LCK3Unf95ve6ZKxn4hP4BjsYTP\n7otywZn3g4H2B47EPJfEL0VJK87hM85Z+f4679m0kcVgYqbcrGUCi6iNy0fLZ0Fu\nQtT4DvoSTqbsVD6zhakpFbtgJdMCslZYAjI02/qptTB/6RrbYJmOr3LLfM6kNJiL\n3/V1rLRb9WGrucfGGh2f25huEm1oBFPCoMRulMSUwQKBgQD8At1X8a6ZTrBKS1wH\nNc3sXb5e8y/DSv5xHU3gObgrTsNDlo6mNpsZrbFXkjaKdANZkB1JNgjknhgHVRQ/\njzkenYbDj8qSDYjV90EBJJSXhFv9QSbU0IiUci+N4vaX3hl+fMbCSYJZ5GtlzAPu\nRAZuJa0GCEkxeR6oCyc4y1bfWwKBgQDYfatODjQI0XwwpRYWzJmojZuGh+eA5Tih\nwZmPxeDBJ8mn7v0Dg3dobJcBg0V+HyFwBxweqLvsImpgjy6tgWccT0IuK0YMZT9J\nwhwUzEv0v4uOpyFcHE4ldkLnxmVo85YoxjolzSEPXjZjgA6YLh8HU22y8uQ0Q716\n9b0n08QJwQKBgHScCrmn3keYDqDCEBpR/jASDIW492/hYq0Khz9q1dpMPrQmlWk5\nuTj/kyDXSh90oRwvQC3hL+pBcRLrfkwOxLpy36nb/jrowllnaI/T0mHt3/bmz8YH\nnDs8Pt7jl4EcRyWtLPc3tnZL6JoY9fSpS2RqUI6LBPs8dUACsSpphJAjAoGAY/FI\nFyXJcdS7330nAGl9+mk9RlMRVdj8VviYWt5ADwu+Na/H0Ept4qBW6hTfDQV0G1K8\n8Y52CuIsd91B8EmP/2q7o7LIiMpo+DULX7Kc0iVnWPjhFrPeg77fzj4x7MyfIr24\ndGEJhR26QB8LHcgU/P3P48/r+BDZtZ0isPM7SkECgYEAgyAR1hG0rfrd9ajbGLpx\nXGJ7fo6vQW2OG96jGXpg12N70JwKtoAYw2ZaRn7ajSXXh8JFlyw5334uOO97+65D\n6dVG2T0KNh5FsrVptNZgZuc/PJXf4mEkYWVRHzE3VFfc0y4RBgVsN8cHpH9nIe3K\nhCfESjU6fePEAo1dFIUfTco=\n-----END PRIVATE KEY-----\n", "client_email": "firebase-adminsdk-fbsvc@students-app-4b35f.iam.gserviceaccount.com", "client_id": "110426202408684217122", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-fbsvc%40students-app-4b35f.iam.gserviceaccount.com", "universe_domain": "googleapis.com" }
Step 9: Create a file named form_screen.dart
in your project. Then, copy and paste the following content into the file.
import 'dart:developer'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:push_notification/notification_network.dart'; class FormScreen extends StatefulWidget { const FormScreen({super.key, required this.title}); final String title; @override State<FormScreen> createState() => _FormScreenState(); } class _FormScreenState extends State<FormScreen> { TextEditingController titleCtr = TextEditingController(); TextEditingController descriptionCtr = TextEditingController(); void _incrementCounter() async{ String? fcmToken = await FirebaseMessaging.instance.getToken(); log("fcmToken fcmToken $fcmToken"); SendNotificationAccess.sendNotificationWithHttp( token: fcmToken!,body: descriptionCtr.text.trim(),title: titleCtr.text.trim()); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title), ), body: Center( child: Padding( padding: const EdgeInsets.only(left: 15,right: 15), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ TextFormField( controller: titleCtr, decoration: InputDecoration( hintText: "Title" ), ), SizedBox(height: 50), TextFormField( controller: descriptionCtr, decoration: InputDecoration( hintText: "Descripton" ), ) ], ), ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: const Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. ); } }
If everything is set up correctly, call your view in the main.dart
file and run the project.
import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:push_notification/form_screen.dart'; import 'package:push_notification/notification_service.dart'; void main() async{ WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); final AppNotification appNotification = AppNotification(); appNotification.initializeFcmNotification(); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Push Notifications', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), ), home: const FormScreen(title: 'Push Notifications'), ); } }
Top comments (0)