[英]Wants to send push notification using one signal when new document is added in the flutter app.Should I use launchUrl() method for it?
下面是 AddNewDocument.dart 文件。 每當我添加任何文檔時,它都應該向用戶顯示新的推送通知,並且應該導航到文檔詳細信息頁面。 有什么方法可以實現嗎?
import 'package:AtDocHUB/Controller/DocumentController.dart';
import 'package:AtDocHUB/Model/Document.dart';
import 'package:AtDocHUB/View/Document/DocumentPage.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:form_field_validator/form_field_validator.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:jiffy/jiffy.dart';
DateTime now = DateTime.now();
String formattedDate = DateFormat("yyyy-MM-dd").format(now);
//import 'package:flutter_text_form_field/flutter_text_form_field.dart';
class AddNewDocument extends StatefulWidget {
@override
State createState() {
return _AddNewDocumentState();
}
}
class _AddNewDocumentState extends State<AddNewDocument> {
late final String date1;
late String datainput;
final List<String> items1 = ["Open", "Closed", "Cancel", "Submitted"];
String? selectedItem;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
TextEditingController docTitleController = TextEditingController();
TextEditingController tokenNoController = TextEditingController();
TextEditingController partyNameController = TextEditingController();
TextEditingController startDateController = TextEditingController();
TextEditingController endDateController = TextEditingController();
late String docType = docTypeController.text;
final List<String> items = [
"Residential",
"Commercial",
];
String? selectedValue;
List<DropdownMenuItem<String>> _addDividersAfterItems(List<String> items) {
List<DropdownMenuItem<String>> _menuItems = [];
for (var item in items) {
_menuItems.addAll(
[
DropdownMenuItem<String>(
value: item,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
item,
style: const TextStyle(
fontSize: 14,
),
),
),
),
//If it's last item, we will not add Divider after it.
if (item != items.last)
const DropdownMenuItem<String>(
enabled: false,
child: Divider(),
),
],
);
}
return _menuItems;
}
List<int> _getDividersIndexes() {
List<int> _dividersIndexes = [];
for (var i = 0; i < (items.length * 2) - 1; i++) {
//Dividers indexes will be the odd indexes
if (i.isOdd) {
_dividersIndexes.add(i);
}
}
return _dividersIndexes;
}
@override
void dispose() {
docStatusController.dispose();
docTypeController.dispose();
super.dispose();
}
@override
Future<Document>? _futureDocument;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromARGB(255, 3, 87, 156),
title: Text('Add New Document'),
leading: IconButton(
icon: BackButtonIcon(),
onPressed: () => Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => DocumentPage()))),
),
body:
//Container(
SafeArea(
child: SingleChildScrollView(
child: Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(10),
child: (_futureDocument == null)
? buildColumn()
: buildFutureBuilder(),
),
),
),
);
}
Form buildColumn() {
return Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 10,
),
TextFormField(
minLines: 1,
maxLines: 3,
textCapitalization: TextCapitalization.words,
inputFormatters: [
FilteringTextInputFormatter.allow(
RegExp("[ ',-/ a-z A-Z á-ú Á-Ú 0-9]")),
],
controller: docTitleController,
style: TextStyle(fontSize: 12),
keyboardType: TextInputType.multiline,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
border: OutlineInputBorder(),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Document Title',
hintText: 'Document title required'),
// validator: ,
validator:
MultiValidator([RequiredValidator(errorText: 'Required*')]),
),
SizedBox(
height: 20,
),
Wrap(
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.4,
child: TextFormField(
style: TextStyle(fontSize: 12),
minLines: 1,
maxLines: 2,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(14)
],
controller: tokenNoController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
counterText: "",
border: OutlineInputBorder(),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Token No',
hintText: 'Token no required'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter token No';
} else if (value.length < 14) {
return 'Please enter 14 digits number';
}
return null;
},
),
),
SizedBox(
width: 15,
),
SizedBox(
height: 20,
),
SizedBox(
width: MediaQuery.of(context).size.width,
child: TextFormField(
minLines: 1,
maxLines: 4,
inputFormatters: [
LengthLimitingTextInputFormatter(50),
FilteringTextInputFormatter.allow(RegExp("[a-z A-Z]")),
],
controller: partyNameController,
keyboardType: TextInputType.name,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
border: OutlineInputBorder(),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Party Name',
hintText: 'Party name required'),
validator:
MultiValidator([RequiredValidator(errorText: 'Required*')]),
),
),
SizedBox(
height: 20,
),
SizedBox(
height: 20,
),
Row(
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.4,
child: TextFormField(
// autovalidateMode: AutovalidateMode.onUserInteraction,
//FilteringTextInputFormatter.allow(RegExp("[- 0-9]")),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp("[- 0-9]")),
LengthLimitingTextInputFormatter(10)
],
controller: startDateController,
keyboardType: TextInputType.datetime,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
prefixIcon: Icon(Icons.calendar_month),
border: OutlineInputBorder(),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Start Date',
hintText: 'yyyy-MM-dd',
),
onTap: () async {
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(
1991), //DateTime.now() - not to allow to choose before today.
lastDate: DateTime(2101),
// onConfirm:widget.onChanged,
).then((pickedDate) {
if (pickedDate != null) {
// print(
// pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
String formattedDate =
DateFormat('yyyy-MM-dd').format(pickedDate);
print(formattedDate);
setState(() {
startDateController.text = formattedDate;
//set output date to TextField value.
});
print(startDateController.text);
} else {
print("Date is not selected");
}
});
final int dur = int.parse(durationController.text);
var stDate = DateTime.parse(startDateController.text);
var jiffy = Jiffy(stDate).add(
months: dur,
days: -1,
// days: 1095,
);
DateTime d = jiffy.dateTime;
String s = jiffy.format('yyyy-MM-dd');
setState(() {
endDateController.text = s.toString();
});
},
validator: MultiValidator(
[RequiredValidator(errorText: 'Required*')]),
),
),
SizedBox(
width: 13,
),
SizedBox(
// height: MediaQuery.of(context).size.height * 0.06,
width: MediaQuery.of(context).size.width * 0.5,
child: TextFormField(
// maxLength: 8,
// autovalidateMode: AutovalidateMode.onUserInteraction,
autofocus: false,
controller: endDateController,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp("[- 0-9]")),
LengthLimitingTextInputFormatter(10)
],
keyboardType: TextInputType.datetime,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
// prefixIcon: Icon(Icons.calendar_month),
counterText: "",
border: OutlineInputBorder(),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'End Date',
hintText: ' yyyy-MM-dd'),
onTap: () async {},
validator: MultiValidator(
[RequiredValidator(errorText: 'Required*')]),
),
),
],
),
SizedBox(
height: 20,
),
SizedBox(
// height: MediaQuery.of(context).size.height * 0.06,
width: MediaQuery.of(context).size.width,
child: TextFormField(
minLines: 1,
maxLines: 4,
// autovalidateMode: AutovalidateMode.onUserInteraction,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp("[a-z A-Z 0-9]")),
// FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(50)
],
controller: rentDescController,
keyboardType: TextInputType.multiline,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
border: OutlineInputBorder(),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Rent Description',
hintText: 'Rent Description required'),
// validator:
// MultiValidator([RequiredValidator(errorText: 'Required*')]),
),
),
SizedBox(
height: 20,
),
Container(
//alignment: Alignment.center,
height: 35,
width: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
color: Color.fromARGB(255, 3, 89, 168),
),
child: ElevatedButton(
onPressed: () {
formKey.currentState?.validate();
final isValidForm = formKey.currentState!.validate();
if (isValidForm) {
//formKey.currentState?.validate();
// final int docId = int.parse(docIdController.text).toInt();
final String docTitle = docTitleController.text;
final int tokenNo =
int.parse(tokenNoController.text).toInt();
//final String tokenNo = tokenNoController.text;
final String partyName = partyNameController.text;
final String startDate = startDateController.text;
final String endDate = endDateController.text;
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => DocumentPage()));
setState(() {
_futureDocument = createDocument(
// docId,
docTitle,
tokenNo,
startDate,
endDate,
// createdAt,
);
});
// }
}
},
child: const Text("Save"),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
Color.fromARGB(255, 3, 89, 168))),
))
],
),
);
//])
//);
}
FutureBuilder<Document> buildFutureBuilder() {
return FutureBuilder<Document>(
future: _futureDocument,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.docTitle);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
);
}
}
下面是 main.dart 文件,我在其中初始化了 App Id 和其他必需的東西。推送通知正確地進入應用程序,當我點擊通知時它會打開應用程序。 但我想在新文檔添加到應用程序時顯示推送通知,當用戶點擊該特定通知時,它應該將用戶導航到文檔詳細信息頁面。我還附上了 AddNewDocumentFile.dart。
import 'package:flutter/material.dart';
import 'package:onesignal_flutter/onesignal_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'View/LoginPage.dart';
import 'View/homePageAdmin.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await SharedPrefService.init();
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class SharedPrefService {
static late SharedPreferences pref;
static Future<void> init() async {
pref = await SharedPreferences.getInstance();
var usrEmail = pref.getString('email');
}
}
class _MyAppState extends State<MyApp> {
// This widget is the root of your application.
@override
void initState() {
// TODO: implement initState
super.initState();
initPlatformState();
}
Future<void> initPlatformState() async {
OneSignal.shared.setAppId('e89acaa4-5388-4e3a-bd69-44d197bdcbd7');
OneSignal.shared
.promptUserForPushNotificationPermission()
.then((accepted) {});
}
@override
Widget build(BuildContext context) {
var usrEmail = SharedPrefService.pref.getString('email');
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.indigo,
),
home: usrEmail == null ? LoginPage() : homePageAdmin(),
);
}
}
您只需要調用OneSignal.shared.postNotification(notification);
在您的createDocument
function 完成后。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.