我们正在开发一个** 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
),
);
}
}
您重新检查这些事情: