Browse Source

android notification done

master
amin 1 year ago
parent
commit
8039bbf63a
21 changed files with 430 additions and 157 deletions
  1. +5
    -0
      android/app/build.gradle
  2. +29
    -0
      android/app/google-services.json
  3. +12
    -6
      android/app/src/main/AndroidManifest.xml
  4. +3
    -0
      android/settings.gradle
  5. +50
    -0
      ios/Runner/AppDelegate.swift
  6. +30
    -0
      ios/Runner/GoogleService-Info.plist
  7. +60
    -20
      lib/main.dart
  8. +3
    -1
      lib/screens/auth/login_screen.dart
  9. +4
    -2
      lib/screens/auth/otp_screen.dart
  10. +5
    -4
      lib/screens/auth/state/state.dart
  11. +103
    -112
      lib/screens/home/screen.dart
  12. +3
    -2
      lib/screens/meeting/screen.dart
  13. +3
    -4
      lib/screens/private_meeting/screen.dart
  14. +3
    -2
      lib/screens/report/screen.dart
  15. +10
    -4
      lib/services/auth/auth.dart
  16. +40
    -0
      lib/services/notification/notification_service.dart
  17. +4
    -0
      macos/Flutter/GeneratedPluginRegistrant.swift
  18. +56
    -0
      pubspec.lock
  19. +3
    -0
      pubspec.yaml
  20. +3
    -0
      windows/flutter/generated_plugin_registrant.cc
  21. +1
    -0
      windows/flutter/generated_plugins.cmake

+ 5
- 0
android/app/build.gradle View File

@@ -1,5 +1,8 @@
plugins {
id "com.android.application"
// START: FlutterFire Configuration
id 'com.google.gms.google-services'
// END: FlutterFire Configuration
id "kotlin-android"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin"
@@ -42,3 +45,5 @@ android {
flutter {
source = "../.."
}

apply plugin: 'com.google.gms.google-services'

+ 29
- 0
android/app/google-services.json View File

@@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "392489806594",
"project_id": "folad-neiriz",
"storage_bucket": "folad-neiriz.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:392489806594:android:76b6661258b6f56f3b301b",
"android_client_info": {
"package_name": "com.example.qadirneyriz"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyAuDK456j4fFdNqrzQRDYyWRcB0VkQ2bCY"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

+ 12
- 6
android/app/src/main/AndroidManifest.xml View File

@@ -1,10 +1,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application
android:label="Mizban"
android:name="${applicationName}"
@@ -18,10 +20,6 @@
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
@@ -31,11 +29,19 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name="io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingService"
android:exported="true"
tools:replace="android:exported">
</service>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="high_importance_channel" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and


+ 3
- 0
android/settings.gradle View File

@@ -19,6 +19,9 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.1.0" apply false
// START: FlutterFire Configuration
id "com.google.gms.google-services" version "4.3.15" apply false
// END: FlutterFire Configuration
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
}



+ 50
- 0
ios/Runner/AppDelegate.swift View File

@@ -1,5 +1,7 @@
import Flutter
import UIKit
import Firebase
import FirebaseMessaging

@main
@objc class AppDelegate: FlutterAppDelegate {
@@ -7,7 +9,55 @@ import UIKit
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// مقداردهی Firebase
FirebaseApp.configure()
// ثبت Plugin های Flutter
GeneratedPluginRegistrant.register(with: self)

// تنظیمات Notification Center
UNUserNotificationCenter.current().delegate = self
Messaging.messaging().delegate = self

// درخواست مجوز نوتیفیکیشن
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
if let error = error {
print("Error requesting notification permissions: \(error)")
}
print("Permission granted: \(granted)")
}
// ثبت دستگاه برای دریافت Remote Notifications
application.registerForRemoteNotifications()
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

// متد دریافت APNs Token و ارسال آن به Firebase
override func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Messaging.messaging().apnsToken = deviceToken
}
}

// افزودن پروتکل‌های UNUserNotificationCenterDelegate و MessagingDelegate
extension AppDelegate: UNUserNotificationCenterDelegate, MessagingDelegate {
// مدیریت دریافت توکن Firebase
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("Firebase FCM Token: \(fcmToken ?? "No Token")")
// اگر نیاز به ارسال توکن به سرور دارید، اینجا انجام دهید.
}
// مدیریت پیام‌های دریافت‌شده هنگام باز بودن اپلیکیشن
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
let userInfo = notification.request.content.userInfo
print("Foreground Notification Received: \(userInfo)")
completionHandler([.banner, .sound, .badge])
}
}

+ 30
- 0
ios/Runner/GoogleService-Info.plist View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>API_KEY</key>
<string>AIzaSyDmiLNq_t5wyqDE2VW1wGyt6kArchRvLAQ</string>
<key>GCM_SENDER_ID</key>
<string>392489806594</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.example.qadirneyriz</string>
<key>PROJECT_ID</key>
<string>folad-neiriz</string>
<key>STORAGE_BUCKET</key>
<string>folad-neiriz.firebasestorage.app</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
<false></false>
<key>IS_APPINVITE_ENABLED</key>
<true></true>
<key>IS_GCM_ENABLED</key>
<true></true>
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:392489806594:ios:feeba2107eb852ec3b301b</string>
</dict>
</plist>

+ 60
- 20
lib/main.dart View File

@@ -1,3 +1,5 @@
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:hive_flutter/hive_flutter.dart';
@@ -13,9 +15,52 @@ import 'package:qadirneyriz/screens/private_meeting/state.dart';
import 'package:qadirneyriz/screens/report/state.dart';
import 'package:qadirneyriz/setting/setting.dart';

void main() async {
final FirebaseMessaging messaging = FirebaseMessaging.instance;

Future<void> initializeApp() async {
await Firebase.initializeApp();
await Hive.initFlutter();
await setting.userLocalDb.openBox();
await requestNotificationPermission();
await getToken();
setupMessageListener();
}

Future<void> requestNotificationPermission() async {
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);

if (settings.authorizationStatus == AuthorizationStatus.authorized) {
print('User granted permission');
} else {
print('User declined or has not granted permission');
}
}

Future<void> getToken() async {
String? token = await messaging.getToken();
print("Device Token: $token");
// You can send the token to your server here if needed
}

void setupMessageListener() {
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Message received: ${message.notification?.title}');
print('Message body: ${message.notification?.body}');
// You can use a Dialog or Toast to display the message here
});
}

void main() async {
WidgetsFlutterBinding.ensureInitialized();
await initializeApp(); // Initialize Firebase and other services
runApp(
MultiProvider(
providers: [
@@ -41,51 +86,46 @@ class MyApp extends StatefulWidget {
class _MyAppState extends State<MyApp> {
late AuthState state;
String language = setting.userLocalDb.getUser().language;

@override
void initState() {
super.initState();
Future.delayed(Duration.zero, () async {
state = Provider.of(context, listen: false);
state = Provider.of<AuthState>(context, listen: false);
setState(() {
language = state.language;
});
});
super.initState();
}

// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return Consumer<AuthState>(
builder: (context, value, child) {
return MaterialApp.router(
theme: ThemeData(
colorScheme: ColorScheme.light(
// تغییر رنگ اصلی تایم پیکر
primary: config.ui.mainGreen,
// تغییر رنگ متن
),
buttonTheme: ButtonThemeData(
colorScheme: ColorScheme.light(
primary: Colors.green, // رنگ دکمه‌ها
),
),
useMaterial3: true,
fontFamily: 'Font',
scaffoldBackgroundColor: Colors.white),
colorScheme: ColorScheme.light(primary: config.ui.mainGreen),
buttonTheme: ButtonThemeData(
colorScheme: ColorScheme.light(primary: Colors.green),
),
useMaterial3: true,
fontFamily: 'Font',
scaffoldBackgroundColor: Colors.white,
),
debugShowCheckedModeBanner: false,
routerDelegate: router.routerDelegate,
routeInformationParser: router.routeInformationParser,
routeInformationProvider: router.routeInformationProvider,
localizationsDelegates: const [
AppLocalizations.delegate, // Add this line
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
locale: Locale(value.language),
supportedLocales: const [
Locale('en'), // English
Locale('fa'), // Persian
Locale('en'),
Locale('fa'),
],
);
},


+ 3
- 1
lib/screens/auth/login_screen.dart View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:qadirneyriz/config/config.dart';
import 'package:qadirneyriz/main.dart';
import 'package:qadirneyriz/screens/auth/state/state.dart';
import 'package:qadirneyriz/utils/enums/status.dart';
import 'package:qadirneyriz/utils/tools/tools.dart';
@@ -151,8 +152,9 @@ class _LoginScreenState extends State<LoginScreen> {
isError: true,
context,
);
} else {
} else { String? token = await messaging.getToken();
final status = await state.login(
fcm_token: token??'',
mobile: phoneController.text,
password: passwordController.text);
if (status == Status.ready) {


+ 4
- 2
lib/screens/auth/otp_screen.dart View File

@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'package:qadirneyriz/config/config.dart';
import 'package:qadirneyriz/main.dart';
import 'package:qadirneyriz/screens/auth/state/state.dart';
import 'package:qadirneyriz/utils/enums/status.dart';
import 'package:qadirneyriz/utils/timer/apt_simple_timer_with_controller.dart';
@@ -182,9 +183,10 @@ class _OtpScreenState extends State<OtpScreen> {
}

void otpCheckCode(onSubmitted, AuthState value) async {
String? token = await messaging.getToken();
if (onSubmitted.length == 4) {
final status =
await value.login(mobile: widget.phoneNumber, otp: onSubmitted);
final status = await value.login(
mobile: widget.phoneNumber, otp: onSubmitted, fcm_token: token ?? '');
if (status == Status.ready) {
context.goNamed('navigate', pathParameters: {'tab': '0'});
} else if (status == Status.error) {


+ 5
- 4
lib/screens/auth/state/state.dart View File

@@ -22,13 +22,16 @@ class AuthState extends ChangeNotifier {
Map? errorsLogin;

Future<Status> login(
{required String mobile, String? password, String? otp}) async {
{required String mobile,
String? password,
String? otp,
required String fcm_token}) async {
assert(password != null || otp != null);
statusLogin = Status.loading;
notifyListeners();
try {
final result = await authServises.loginApi(
mobile: mobile, password: password, otp: otp);
mobile: mobile, password: password, otp: otp, fcm_token: fcm_token);
if (result == null) {
statusLogin = Status.error;
} else {
@@ -88,6 +91,4 @@ class AuthState extends ChangeNotifier {
// print(statusSendotp);
return statusSendotp;
}


}

+ 103
- 112
lib/screens/home/screen.dart View File

@@ -38,8 +38,9 @@ class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
DateTime now = DateTime.now();
String dateMiladi =
Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now));
String dateMiladi = setting.userLocalDb.getUser().language == 'fa'
? Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now))
: DateFormat('yyyy-MM-dd').format(now);
String dateJalali = Tools.convertToPersianDigits(
'${setting.timeNow.day} ${Tools.getMonthName(setting.timeNow.month)} ${setting.timeNow.year}');

@@ -123,29 +124,38 @@ class _HomeScreenState extends State<HomeScreen> {
final meeting = value
.todayMeetingsModel!.meetings![index];
return Padding(
padding: const EdgeInsets.only(
right: 5, left: 1),
child: Stack(
children: [
CustomCardMeeting(
status: meeting.accepted ?? 0,
titel: meeting.subject != null
? meeting.subject!.subject ?? ''
: '',
fromTime: meeting.azHour ?? '',
toTime: meeting.taHour ?? "",
location: meeting.location != null
? meeting.location!.address ?? ''
: '',
date: meeting.dateJalali ?? '',
cardId: meeting.id ?? 0,
),
Positioned(
child: Container(
padding: const EdgeInsets.only(
right: 5, left: 1),
child: Stack(
children: [
CustomCardMeeting(
status: meeting.accepted ?? 0,
titel: meeting.subject != null
? meeting.subject!.subject ?? ''
: '',
fromTime: meeting.azHour ?? '',
toTime: meeting.taHour ?? "",
location: meeting.location != null
? meeting.location!.address ??
''
: '',
date: meeting.dateJalali ?? '',
cardId: meeting.id ?? 0,
),
Positioned(
left: setting.userLocalDb
.getUser()
.language ==
'fa'
? 20
: 280,
top: 20,
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(10),
color: Colors.green),
borderRadius:
BorderRadius.circular(10),
color: Colors.green,
),
child: Padding(
padding:
const EdgeInsets.all(5.0),
@@ -156,13 +166,11 @@ class _HomeScreenState extends State<HomeScreen> {
fontSize: 12,
color: Colors.white),
),
)),
left: 30,
top: 20,
),
],
),
);
),
),
),
],
));
} else {
// آیتم از لیست `privateMeetings`
final privateMeeting = value
@@ -192,6 +200,12 @@ class _HomeScreenState extends State<HomeScreen> {
toTime: privateMeeting.taHour ?? '',
),
Positioned(
left: setting.userLocalDb
.getUser()
.language ==
'fa'
? 20
: 250,
child: Container(
decoration: BoxDecoration(
borderRadius:
@@ -208,7 +222,6 @@ class _HomeScreenState extends State<HomeScreen> {
color: Colors.white),
),
)),
left: 30,
top: 20,
),
],
@@ -343,86 +356,7 @@ class _HomeScreenState extends State<HomeScreen> {
const SizedBox(
height: 30,
),
Consumer<HomeState>(
builder: (context, value, child) {
switch (value.statusLogOut) {
case Status.loading:
return const LoadingWidget();

default:
return Row(
mainAxisAlignment:
MainAxisAlignment
.center,
crossAxisAlignment:
CrossAxisAlignment
.center,
children: [
CustomButton(
fontSize: 13,
color: config
.ui.mainGreen,
onPressed: () {
Navigator.pop(
context);
},
hieght: 50,

// width: 150,
text: AppLocalizations
.of(context)!
.no,
),
const SizedBox(
width: 10,
),
CustomButton(
fontSize: 13,
hieght: 50,
// width: 150,
text: AppLocalizations
.of(context)!
.logout,
textColor:
Colors.black,
color: const Color(
0xffD0D5ED),

onPressed: () async {
final status =
await value
.logOut();
if (status ==
Status.error) {
Tools.showCustomSnackBar(
context,
text: value
.messageLogOut ??
AppLocalizations.of(
context)!
.error,
isError:
true);
} else if (status ==
Status.ready) {
context
.pushReplacementNamed(
'login');
Tools.showCustomSnackBar(
context,
text: value
.messageLogOut ??
'Done successfully',
isError:
false);
}
},
),
],
);
}
},
),
logOutButton(),
const SizedBox(
height: 40,
)
@@ -458,6 +392,63 @@ class _HomeScreenState extends State<HomeScreen> {
},
);
}

Consumer<HomeState> logOutButton() {
return Consumer<HomeState>(
builder: (context, value, child) {
switch (value.statusLogOut) {
case Status.loading:
return const LoadingWidget();

default:
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CustomButton(
fontSize: 13,
color: config.ui.mainGreen,
onPressed: () {
Navigator.pop(context);
},
hieght: 50,

// width: 150,
text: AppLocalizations.of(context)!.no,
),
const SizedBox(
width: 10,
),
CustomButton(
fontSize: 13,
hieght: 50,
// width: 150,
text: AppLocalizations.of(context)!.logout,
textColor: Colors.black,
color: const Color(0xffD0D5ED),

onPressed: () async {
final status = await value.logOut();
if (status == Status.error) {
Tools.showCustomSnackBar(context,
text: value.messageLogOut ??
AppLocalizations.of(context)!.error,
isError: true);
} else if (status == Status.ready) {
setting.userLocalDb.logOut();
context.pushReplacementNamed('login');
Tools.showCustomSnackBar(context,
text: value.messageLogOut ?? 'Done successfully',
isError: false);
}
},
),
],
);
}
},
);
}
}

class ItemInGrid extends StatelessWidget {


+ 3
- 2
lib/screens/meeting/screen.dart View File

@@ -67,8 +67,9 @@ class _MeetingsScreenState extends State<MeetingsScreen> {
@override
Widget build(BuildContext context) {
DateTime now = DateTime.now();
String dateMiladi =
Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now));
String dateMiladi = setting.userLocalDb.getUser().language == 'fa'
? Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now))
: DateFormat('yyyy-MM-dd').format(now);
String dateJalali = Tools.convertToPersianDigits(
'${setting.timeNow.day} ${Tools.getMonthName(setting.timeNow.month)} ${setting.timeNow.year}');
// فرمت کردن تاریخ


+ 3
- 4
lib/screens/private_meeting/screen.dart View File

@@ -64,8 +64,9 @@ class _PrivateMeetingsScreenState extends State<PrivateMeetingsScreen> {
@override
Widget build(BuildContext context) {
DateTime now = DateTime.now();
String dateMiladi =
Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now));
String dateMiladi = setting.userLocalDb.getUser().language == 'fa'
? Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now))
: DateFormat('yyyy-MM-dd').format(now);
String dateJalali = Tools.convertToPersianDigits(
'${setting.timeNow.day} ${Tools.getMonthName(setting.timeNow.month)} ${setting.timeNow.year}');

@@ -315,8 +316,6 @@ class PrivateMeetingWidget extends StatelessWidget {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
child: Container(
width: 500,
height: 190,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [


+ 3
- 2
lib/screens/report/screen.dart View File

@@ -30,8 +30,9 @@ class _ReportScreenState extends State<ReportScreen> {
@override
Widget build(BuildContext context) {
DateTime now = DateTime.now();
String dateMiladi =
Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now));
String dateMiladi = setting.userLocalDb.getUser().language == 'fa'
? Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now))
: DateFormat('yyyy-MM-dd').format(now);
String dateJalali = Tools.convertToPersianDigits(
'${setting.timeNow.day} ${Tools.getMonthName(setting.timeNow.month)} ${setting.timeNow.year}');
// فرمت کردن تاریخ


+ 10
- 4
lib/services/auth/auth.dart View File

@@ -5,15 +5,20 @@ import 'package:qadirneyriz/utils/result/result.dart';

class AuthServices {
Future<Result?> loginApi(
{required String mobile, String? password, String? otp}) async {
{required String mobile,
String? password,
String? otp,
required String fcm_token}) async {
assert(password != null || otp != null);
try {
Map<String, String> headers = {"Accept": "application/json"};
FormData? formData;
formData = password != null
? FormData.fromMap({"mobile": mobile, "password": password})
: FormData.fromMap({"mobile": mobile, "otp": otp});

? FormData.fromMap(
{"mobile": mobile, "password": password, "device_id": fcm_token})
: FormData.fromMap(
{"mobile": mobile, "otp": otp, "device_id": fcm_token});
print('${formData.fields} resData');
final res = await Dio().post("${config.network.baseUrl}login",
data: formData, options: Options(headers: headers));

@@ -26,6 +31,7 @@ class AuthServices {
return Result(isOk: true, message: res.data['msg']);
}
} on DioException catch (e) {
print(e);
return Result(
isOk: false,
errors: e.response!.data['errors'],


+ 40
- 0
lib/services/notification/notification_service.dart View File

@@ -0,0 +1,40 @@
import 'package:firebase_messaging/firebase_messaging.dart';

class NotificationService {
final FirebaseMessaging _messaging = FirebaseMessaging.instance;

/// درخواست دسترسی به نوتیفیکیشن
Future<void> requestNotificationPermission() async {
NotificationSettings settings = await _messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);

if (settings.authorizationStatus == AuthorizationStatus.authorized) {
print('User granted permission');
} else {
print('User declined or has not granted permission');
}
}

/// دریافت توکن دستگاه
Future<void> getToken() async {
String? token = await _messaging.getToken();
print("Device Token: $token");
// اینجا می‌توانید توکن را به سرور خود ارسال کنید
}

/// تنظیم Listener برای دریافت نوتیفیکیشن‌ها
void setupMessageListener() {
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Message received: ${message.notification?.title}');
print('Message body: ${message.notification?.body}');
// اینجا می‌توانید یک Dialog یا Toast برای نمایش پیام استفاده کنید
});
}
}

+ 4
- 0
macos/Flutter/GeneratedPluginRegistrant.swift View File

@@ -5,11 +5,15 @@
import FlutterMacOS
import Foundation

import firebase_core
import firebase_messaging
import open_file_mac
import path_provider_foundation
import sqflite

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
OpenFilePlugin.register(with: registry.registrar(forPlugin: "OpenFilePlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))


+ 56
- 0
pubspec.lock View File

@@ -9,6 +9,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "72.0.0"
_flutterfire_internals:
dependency: transitive
description:
name: _flutterfire_internals
sha256: "71c01c1998c40b3af1944ad0a5f374b4e6fef7f3d2df487f3970dbeadaeb25a1"
url: "https://pub.dev"
source: hosted
version: "1.3.46"
_macros:
dependency: transitive
description: dart
@@ -262,6 +270,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "8.1.3"
firebase_core:
dependency: "direct main"
description:
name: firebase_core
sha256: "2438a75ad803e818ad3bd5df49137ee619c46b6fc7101f4dbc23da07305ce553"
url: "https://pub.dev"
source: hosted
version: "3.8.0"
firebase_core_platform_interface:
dependency: transitive
description:
name: firebase_core_platform_interface
sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810
url: "https://pub.dev"
source: hosted
version: "5.3.0"
firebase_core_web:
dependency: transitive
description:
name: firebase_core_web
sha256: f967a7138f5d2ffb1ce15950e2a382924239eaa521150a8f144af34e68b3b3e5
url: "https://pub.dev"
source: hosted
version: "2.18.1"
firebase_messaging:
dependency: "direct main"
description:
name: firebase_messaging
sha256: "4d0968ecb860d7baa15a6e2af3469ec5b0d959e51c59ce84a52b0f7632a4aa5a"
url: "https://pub.dev"
source: hosted
version: "15.1.5"
firebase_messaging_platform_interface:
dependency: transitive
description:
name: firebase_messaging_platform_interface
sha256: a2cb3e7d71d40b6612e2d4e0daa0ae759f6a9d07f693f904d14d22aadf70be10
url: "https://pub.dev"
source: hosted
version: "4.5.48"
firebase_messaging_web:
dependency: transitive
description:
name: firebase_messaging_web
sha256: "1554e190f0cd9d6fe59f61ae0275ac12006fdb78b07669f1a260d1a9e6de3a1f"
url: "https://pub.dev"
source: hosted
version: "3.9.4"
fixnum:
dependency: transitive
description:


+ 3
- 0
pubspec.yaml View File

@@ -34,6 +34,9 @@ dependencies:
file_picker: ^8.1.3
permission_handler: ^11.3.1
open_file: ^3.5.9
firebase_core: ^3.8.0
firebase_messaging: ^15.1.5


dev_dependencies:
flutter_test:


+ 3
- 0
windows/flutter/generated_plugin_registrant.cc View File

@@ -6,9 +6,12 @@

#include "generated_plugin_registrant.h"

#include <firebase_core/firebase_core_plugin_c_api.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>

void RegisterPlugins(flutter::PluginRegistry* registry) {
FirebaseCorePluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
}

+ 1
- 0
windows/flutter/generated_plugins.cmake View File

@@ -3,6 +3,7 @@
#

list(APPEND FLUTTER_PLUGIN_LIST
firebase_core
permission_handler_windows
)



Loading…
Cancel
Save