Flutter 通知问题

问题描述 投票:0回答:1

我们正在开发一个** flutter应用程序**,它允许用户安排药物提醒,以便他们可以添加名称和剂量等......以及他们想要收到通知的时间,因此我们尝试使用很棒的通知打包并实现它,但通知没有来,那么我们能做什么? (我们使用firebase firestore来存储数据)

这里是通知设置的代码片段:

import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fireproject/Medicine_log/models/medicine.dart';
import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz;
import 'package:fireproject/Medicine_log/models/medicine.dart';

// Notification service class for managing and scheduling notifications.
class NotificationService {
  // Firestore instance for fetching medication data.
  final FirebaseFirestore _firestore = FirebaseFirestore.instance;
  // Variable to keep track of notification IDs.
  int _notificationId = 0;

  // Constructor to initialize time zones for scheduling.
  NotificationService() {
    tz.initializeTimeZones();
  }

  // Method to handle events when a notification is created.
  @pragma('vm:entry-point')
  static Future<void> onNotificationCreatedMethod(
      ReceivedNotification receivedNotification) async {}

  // Method to handle events when a notification is displayed.
  @pragma('vm:entry-point')
  static Future<void> onNotificationsDisplayedMethod(
      ReceivedNotification receivedNotification) async {}

  // Method to handle events when a notification dismiss action is received.
  @pragma('vm:entry-point')
  static Future<void> onDismissActionReceivedMethod(
      ReceivedAction receivedAction) async {}

  // Method to handle events when a user taps on a notification or action button.
  @pragma('vm:entry-point')
  static Future<void> onActionReceiveMethod(
      ReceivedAction receivedAction) async {}

  // Method to schedule notifications based on the medicine data.
  Future<void> scheduleNotificationsBasedOnMedicine() async {
    // Set the timezone location for scheduling.
    final location = tz.getLocation('Asia/Amman');

    // Fetch all medicines from Firestore.
    QuerySnapshot querySnapshot = await _firestore.collection('medicine').get();

    for (var doc in querySnapshot.docs) {
      Medicine medicine = Medicine.fromFirestore(doc);

      // Loop through each reminder time for the medicine.
      for (var reminderTimestamp in medicine.reminderTime) {
        DateTime utcScheduledTime = reminderTimestamp.toDate();
        tz.TZDateTime scheduledTime =
            tz.TZDateTime.from(utcScheduledTime, location);

        // Schedule the notification.
        await AwesomeNotifications().createNotification(
          content: NotificationContent(
            id: _notificationId++, // Incrementing ID for each notification.
            channelKey: 'basic_channel',
            title: 'Medicijne Herinnering', // Title for the notification.
            body:
                '${medicine.dosage} ${medicine.name} innemen.', // Body text for the notification.
          ),
          schedule: NotificationCalendar.fromDate(
              date: scheduledTime), // Scheduling details.
        );
      }
    }
  }
}




这是添加提醒页面:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fireproject/notification/notification_serivce.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:intl/intl.dart';
import 'package:fireproject/Medicine_log/models/medicine.dart';
import 'package:fireproject/Medicine_log/widgets/time_input.dart';
import 'package:fireproject/Medicine_log/widgets/medication_card.dart';
import 'package:multi_select_flutter/multi_select_flutter.dart';
import '../widgets/date_selector.dart';
import '../widgets/footer.dart';
import '../widgets/input_style.dart';
import '../services/medication_service.dart';
import 'package:timezone/timezone.dart' as tz;

class medScreen extends StatefulWidget {
  final Medicine? medicineToEdit;
  const medScreen(
      {super.key, this.medicineToEdit}); // Constructor for HomeScreen

  @override
  State<medScreen> createState() => _HomeScreenState();
}

// FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
//     FlutterLocalNotificationsPlugin();

class _HomeScreenState extends State<medScreen> {
  final GlobalKey<FormState> _formKey =
      GlobalKey<FormState>(); // Form key for validation
  final ValueNotifier<int> selectedImageIndexNotifier = ValueNotifier<int>(-1);
  final List<String> _allDays = [
    'Monday',
    'Tuesday',
    'Wednesday',
    'Thursday',
    'Friday',
    'Saturday',
    'Sunday',
  ];

  // List of image URLs for medication images
  List imageUrls = [
    'assets/images/—Pngtree—pharmacy drug health tablet pharmaceutical_6861618.png',
    'assets/images/black-outlined-bottle.png',
    'assets/images/black-outlined-pill.png',
    'assets/images/blue-pill.png',
    'assets/images/blue-yellow-tablet.png',
    'assets/images/colored-bottle.png',
    'assets/images/green-pill.png',
    'assets/images/orange-tablet.png',
    'assets/images/pink-pill.png',
    'assets/images/pink-tablet.png',
    'assets/images/white-tablet.png',
  ];

  // Controllers for medication input fields
  final TextEditingController _medicationNameController =
      TextEditingController();
  final TextEditingController _quantityController = TextEditingController();
  final TextEditingController _doseController = TextEditingController();

  List<String> _selectedDays = []; // List to store selected days
  List<Timestamp> _reminderTimes = []; // List to store reminder times
  String selectedImageUrl = ''; // Selected medication image URL

  DateTime _selectedDate = DateTime.now(); // Selected date for medication

  // Function to show the medication input form as a bottom sheet
  void _showFormBottomSheet() {
    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      builder: (BuildContext context) {
        return _buildMedicationFormSheet(context);
      },
    );
  }

  // Future<void> _initializeLocalNotifications() async {
  //   const AndroidInitializationSettings initializationSettingsAndroid =
  //       AndroidInitializationSettings('app_icon');

  //   final InitializationSettings initializationSettings =
  //       InitializationSettings(
  //     android: initializationSettingsAndroid,
  //   );
  //   await flutterLocalNotificationsPlugin.initialize(
  //     initializationSettings,
  //   );
  // }

  // Future<void> _scheduleMedicationNotifications(
  //     List<Timestamp> reminderTimes) async {
  //   for (var time in reminderTimes) {
  //     final dateTime = time.toDate();
  //     await flutterLocalNotificationsPlugin.zonedSchedule(
  //       0,
  //       'Medication Reminder',
  //       'Time to take your medication',
  //       tz.TZDateTime.from(dateTime, tz.local),
  //       const NotificationDetails(
  //         android: AndroidNotificationDetails(
  //           'your channel id',
  //           'your channel name',
  //           importance: Importance.max,
  //           priority: Priority.high,
  //         ),
  //       ),
  //       androidAllowWhileIdle: true,
  //       uiLocalNotificationDateInterpretation:
  //           UILocalNotificationDateInterpretation.absoluteTime,
  //     );
  //   }
  // }

  // Function to update the reminder times
  void _updateReminderTime(List<Timestamp> times) {
    setState(() {
      _reminderTimes = times;
    });
  }

  // Function to update the selected medication image URL
  void _updateSelectedImageUrl(int index) {
    setState(() {
      selectedImageIndexNotifier.value = index;
      selectedImageUrl = imageUrls[index];
    });
  }

  // Function to handle date selection
  void _onDateSelected(DateTime newDate) {
    setState(() {
      _selectedDate = newDate;
    });
  }

  @override
  void initState() {
    // _initializeLocalNotifications();
    super.initState();
    if (widget.medicineToEdit != null) {
      // If editing an existing medicine, populate input fields
      _medicationNameController.text = widget.medicineToEdit!.name;
      _quantityController.text = widget.medicineToEdit!.amount;
      _doseController.text = widget.medicineToEdit!.dosage;
      _selectedDays = widget.medicineToEdit!.days;
      _reminderTimes = widget.medicineToEdit!.reminderTime;
      selectedImageUrl = widget.medicineToEdit!.image;
      // Trigger the bottom sheet to show after the build is complete
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _showFormBottomSheet();
      });
    }
  }

  Future<List<Timestamp>> fetchReminderTimesFromFirestore() async {
    List<Timestamp> reminderTimes = [];

    try {
      // Reference to the 'medicine' collection in Firestore
      CollectionReference medicineCollection =
          FirebaseFirestore.instance.collection('medicine');

      // Fetch documents from Firestore
      QuerySnapshot querySnapshot = await medicineCollection.get();

      // Iterate through each document in the collection
      querySnapshot.docs.forEach((doc) {
        // Extract reminder times from the document data
        List<dynamic> reminderTimesData = doc['reminder_time'];

        // Convert dynamic data to Timestamp objects
        List<Timestamp> reminderTimesForDocument = reminderTimesData
            .map((timeData) => Timestamp.fromMillisecondsSinceEpoch(
                timeData.seconds * 1000)) // Convert seconds to milliseconds
            .toList();

        // Add reminder times to the list
        reminderTimes.addAll(reminderTimesForDocument);
      });
    } catch (e) {
      print('Error fetching reminder times: $e');
      // Return an empty list or handle the error as per your requirement
    }

    return reminderTimes;
  }

  // Function to build the medication input form as a bottom sheet
  Widget _buildMedicationFormSheet(BuildContext context) {
    return SizedBox(
      child: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.only(left: 20, right: 20, top: 40),
          child: Form(
            key: _formKey,
            child: Column(
              children: [
                // Header with back button and title
                Row(
                  children: [
                    IconButton(
                      icon: const Icon(
                        Icons.arrow_back_ios,
                        color: Color(0xffeb6081),
                        size: 20,
                      ),
                      onPressed: () {
                        Navigator.pop(context);
                      },
                      constraints: const BoxConstraints(),
                    ),
                    Expanded(
                      child: Container(
                        alignment: Alignment.centerLeft,
                        child: const Text(
                          'Schedule your medicine intake',
                          style: TextStyle(
                            fontWeight: FontWeight.bold,
                            fontSize: 15,
                            color: Color(0xffeb6081),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 12),
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text('Medicine name'),
                    const SizedBox(
                      height: 8,
                    ),
                    // Input field for medication name
                    inputStyle(
                      prefixIcon: Icons.medication_rounded,
                      hintText: 'Ex. panadol',
                      controller: _medicationNameController,
                    )
                  ],
                ),
                const SizedBox(height: 12),
                Row(
                  children: [
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          const Text('Quantity'),
                          const SizedBox(height: 8),
                          // Input field for medication quantity
                          inputStyle(
                              prefixIcon: Icons.medical_information,
                              hintText: '1 pil/tablet',
                              controller: _quantityController)
                        ],
                      ),
                    ),
                    const SizedBox(width: 20),
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          const Text('Dosage'),
                          const SizedBox(
                            height: 8,
                          ),
                          // Input field for medication dosage
                          inputStyle(
                              prefixIcon: Icons.my_library_add_rounded,
                              hintText: '500mg/ml',
                              controller: _doseController),
                        ],
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 12),

                // MultiSelect widget for selecting days
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    MultiSelectBottomSheetField(
                      initialChildSize: 0.7,
                      maxChildSize: 0.95,
                      listType: MultiSelectListType.CHIP,
                      searchable: true,
                      buttonText: const Text('which days'), // Button text
                      title: const Text(
                          'select days to repeat'), // Title for the selection
                      items: _allDays
                          .map((day) => MultiSelectItem(day, day))
                          .toList(),
                      onConfirm: (values) {
                        // Callback when days are confirmed
                        setState(() {
                          _selectedDays = List<String>.from(values);
                        });
                      },
                      chipDisplay: MultiSelectChipDisplay(
                        onTap: (value) {
                          setState(() {
                            _selectedDays.remove(value);
                          });
                        },
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 12),

                // TimeInputWidget for selecting reminder times
                TimeInputWidget(
                  onTimeChanged: _updateReminderTime,
                ),

                const SizedBox(height: 12),

                // Medication image selection
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text('Medicine type'), // Title for medication image
                    SizedBox(
                      height: 80,
                      child: ListView.builder(
                        scrollDirection: Axis.horizontal,
                        itemCount: imageUrls.length,
                        itemBuilder: (context, index) {
                          return GestureDetector(
                            onTap: () {
                              _updateSelectedImageUrl(
                                  index); // Update the selected image URL
                            },
                            child: ValueListenableBuilder<int>(
                              valueListenable: selectedImageIndexNotifier,
                              builder: (context, selectedImageIndex, child) {
                                return Container(
                                  width: 80,
                                  padding: const EdgeInsets.symmetric(
                                    horizontal: 8.0,
                                  ),
                                  decoration: BoxDecoration(
                                    border: Border.all(
                                      color: selectedImageIndex == index
                                          ? Colors
                                              .blue // Border color when selected
                                          : Colors
                                              .transparent, // No border when not selected
                                      width: 2.0, // Border width
                                    ),
                                  ),
                                  transform: Matrix4.identity()
                                    ..scale(0.8), // Scale down the image
                                  child: Column(
                                    children: [
                                      Expanded(
                                        child: Image.asset(imageUrls[index]),
                                      ),
                                    ],
                                  ),
                                );
                              },
                            ),
                          );
                        },
                      ),
                    ),
                  ],
                ),

                // Submit button for saving medication
                Padding(
                  padding: const EdgeInsets.only(top: 8.0, bottom: 8.0),
                  child: ElevatedButton(
                    style: ButtonStyle(
                      backgroundColor: MaterialStateProperty.resolveWith<Color>(
                        (states) => const Color(0xffeb6081), // Button color
                      ),
                      minimumSize: MaterialStateProperty.resolveWith<Size>(
                        (states) => Size(
                          MediaQuery.of(context).size.width * 0.95,
                          50.0,
                        ),
                      ),
                    ),
                    onPressed: () async {
                      if (_formKey.currentState!.validate()) {
                        // Create or update a Medicine object
                        Medicine medicine = Medicine(
                          id: widget.medicineToEdit
                              ?.id, // Use existing ID if in update mode
                          name: _medicationNameController.text,
                          dosage: _doseController.text,
                          image: selectedImageUrl,
                          days: _selectedDays,
                          reminderTime: _reminderTimes,
                          amount: _quantityController.text,
                        );

                        MedicationService medicationService =
                            MedicationService();

                        try {
                          if (widget.medicineToEdit == null) {
                            // Create mode: Save a new medicine
                            await medicationService.createMedicine(medicine);
                            if (kDebugMode) {
                              print('Medicine created successfully');
                            }
                          } else {
                            // Update mode: Update existing medicine
                            await medicationService.updateMedicine(medicine);
                            if (kDebugMode) {
                              print('Medicine updated successfully');
                            }
                          }

                          

                          // Clear input fields and state variables
                          _medicationNameController.clear();
                          _doseController.clear();
                          _quantityController.clear();
                          _selectedDays.clear();
                          _reminderTimes.clear();
                          selectedImageUrl = '';
                          // _scheduleMedicationNotifications;
                          Navigator.of(context).pop(); // Close the bottom sheet
                        } catch (e) {
                          if (kDebugMode) {
                            print('Error processing medicine: $e');
                          }
                        }
                      }
                    },
                    child: const Text(
                      'ADD', // Button text
                      style: TextStyle(
                          fontSize: 20,
                          fontWeight: FontWeight.normal,
                          color: Colors.white),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    // Format the selected date for display
    String formattedDate =
        DateFormat('d MMMM').format(_selectedDate); // Use _selectedDate

    return Scaffold(
      body: SingleChildScrollView(
        child: Column(
          children: [
            // Display the DateSelector widget
            DateSelector(
              formattedDate: formattedDate,
              onDateSelected: _onDateSelected, // Set up the callback
            ),
            // Display the MedicationCard widget and pass the selected date
            MedicationCard(
                selectedDate:
                    _selectedDate), // Pass the selected date to MedicationCard
          ],
        ),
      ),
      bottomNavigationBar: Footer(
        onButtonPressed: _showFormBottomSheet, // Show the medication input form
      ),
    );
  }
}


android flutter firebase push-notification notifications
1个回答
0
投票

您重新检查这些事情:

  • Android/iOS 配置。
  • 启用通知权限。
© www.soinside.com 2019 - 2024. All rights reserved.