Hibok
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 
 

453 行
15 KiB

  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'dart:math';
  4. import 'package:chat/data/UserData.dart';
  5. import 'package:chat/generated/i18n.dart';
  6. import 'package:chat/home/InfoList.dart';
  7. import 'package:chat/home/ProgramDetail.dart';
  8. import 'package:chat/home/rich_title.dart';
  9. import 'package:chat/models/received_notification.dart';
  10. import 'package:flutter/cupertino.dart';
  11. import 'package:flutter/material.dart';
  12. import 'package:flutter_app_badger/flutter_app_badger.dart';
  13. import 'package:flutter_local_notifications/flutter_local_notifications.dart';
  14. import 'package:jpush_flutter/jpush_flutter.dart';
  15. import 'package:rxdart/rxdart.dart';
  16. import 'MessageMgr.dart';
  17. class LocalNotificationUtil {
  18. static bool isBackground = false;
  19. ///是否在后台
  20. static int badgerCount = 0;
  21. ///角标计数
  22. BuildContext mContext;
  23. factory LocalNotificationUtil() => _getInstance();
  24. static LocalNotificationUtil get instance => _getInstance();
  25. static LocalNotificationUtil _instance;
  26. static const String PAYLOAD_DATE = 'date';
  27. static const String PAYLOAD_FRIENDS = 'friends';
  28. /// date+@+节目id
  29. static const String PAYLOAD_OTHER = 'other';
  30. /// 其他
  31. LocalNotificationUtil._internal() {
  32. // 初始化
  33. }
  34. static LocalNotificationUtil _getInstance() {
  35. if (_instance == null) {
  36. _instance = new LocalNotificationUtil._internal();
  37. }
  38. return _instance;
  39. }
  40. FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
  41. FlutterLocalNotificationsPlugin();
  42. // Streams are created so that app can respond to notification-related events since the plugin is initialised in the `main` function
  43. BehaviorSubject<ReceivedNotification> didReceiveLocalNotificationSubject =
  44. BehaviorSubject<ReceivedNotification>();
  45. BehaviorSubject<String> selectNotificationSubject = BehaviorSubject<String>();
  46. void initJPush() {
  47. JPush jpush = new JPush();
  48. ///ios一定要加这句
  49. jpush.applyPushAuthority(
  50. new NotificationSettingsIOS(sound: true, alert: true, badge: true));
  51. jpush.addEventHandler(
  52. // 接收通知回调方法。
  53. onReceiveNotification: (Map<String, dynamic> message) async {
  54. print("flutter onReceiveNotification: $message");
  55. Map jExtra = message['extras'];
  56. print('onOpenNotification jExtra:$jExtra');
  57. if (jExtra.containsKey('cn.jpush.android.EXTRA')) {
  58. ///android
  59. Map map = json.decode(jExtra['cn.jpush.android.EXTRA']);
  60. //申请好友推送
  61. if (map['Type'] == 6) {
  62. MessageMgr().emit('do_friend_apply');
  63. }
  64. return;
  65. } else {
  66. ///ios
  67. //申请好友推送
  68. if (jExtra['Type'] == 6) {
  69. MessageMgr().emit('do_friend_apply');
  70. }
  71. }
  72. },
  73. // 点击通知回调方法。
  74. onOpenNotification: (Map<String, dynamic> message) async {
  75. print("flutter onOpenNotification: $message");
  76. print("flutter onOpenNotification extras: ${message['extras']}");
  77. // flutter onOpenNotification: {aps: {alert: {title: ddd, body: 大幅度发}, badge: 1, sound: default}, payload: other@1, extras: {payload: other@1}, _j_uid: 33833979419, _j_msgid: 29273440739312177, _j_business: 1}
  78. Map jExtra = message['extras'];
  79. print('onOpenNotification jExtra:$jExtra');
  80. if (jExtra.containsKey('cn.jpush.android.EXTRA')) {
  81. ///android
  82. Map map = json.decode(jExtra['cn.jpush.android.EXTRA']);
  83. print('map: $map');
  84. String payload = getPayload(map);
  85. print('onOpenNotification payload:$payload');
  86. goPage(payload);
  87. return;
  88. } else {
  89. ///ios
  90. print("flutter jExtra : $jExtra");
  91. String payload = getPayload(jExtra);
  92. print('onOpenNotification payload:$payload');
  93. goPage(payload);
  94. }
  95. },
  96. // 接收自定义消息回调方法。
  97. onReceiveMessage: (Map<String, dynamic> message) async {
  98. print("flutter自定义 onReceiveMessage: $message");
  99. },
  100. );
  101. jpush.setup(
  102. appKey: "13dd603952a6632d1dd3ac54",
  103. channel: "theChannel",
  104. production: false,
  105. debug: true, // 设置是否打印 debug 日志
  106. );
  107. jpush.getRegistrationID().then((rid) {
  108. print('jpush getRegistrationID $rid ');
  109. });
  110. }
  111. void setAlias() {
  112. JPush jpush = new JPush();
  113. print('flutter jpush setAlias ${UserData().basicInfo.userId.toString()}');
  114. jpush.setAlias(UserData().basicInfo.userId.toString()).then((map) {});
  115. jpush.addTags(
  116. ["yueliao", 'yueliao_' + UserData().language.toString()],
  117. ).then((map) {});
  118. if (Platform.isIOS) {
  119. jpush.getLaunchAppNotification().then((map) {
  120. print('getLaunchAppNotification $map');
  121. Map jExtra = map['extras'];
  122. String payload = getPayload(jExtra);
  123. print('onOpenNotification payload:$payload');
  124. goPage(payload);
  125. FlutterAppBadger.removeBadge();
  126. }).catchError((error) {
  127. print('getLaunchAppNotificationerror $error');
  128. });
  129. }
  130. }
  131. void removeAlias() {
  132. JPush jpush = new JPush();
  133. jpush.deleteAlias();
  134. jpush.stopPush();
  135. }
  136. void initState(BuildContext context) {
  137. this.mContext = context;
  138. if (hasInit) {
  139. return;
  140. }
  141. hasInit = true;
  142. didReceiveLocalNotificationSubject.stream
  143. .listen((ReceivedNotification receivedNotification) async {
  144. print('ios低版本推送点击:${receivedNotification.payload}');
  145. await showDialog(
  146. context: mContext,
  147. builder: (BuildContext context) => CupertinoAlertDialog(
  148. title: receivedNotification.title != null
  149. ? Text(receivedNotification.title)
  150. : null,
  151. content: receivedNotification.body != null
  152. ? Text(receivedNotification.body)
  153. : null,
  154. actions: [
  155. CupertinoDialogAction(
  156. isDefaultAction: false,
  157. child: Text(I18n.of(mContext).cancel),
  158. onPressed: () async {
  159. Navigator.of(mContext, rootNavigator: true).pop();
  160. },
  161. ),
  162. CupertinoDialogAction(
  163. isDefaultAction: true,
  164. child: Text(I18n.of(mContext).determine),
  165. onPressed: () async {
  166. Navigator.of(mContext, rootNavigator: true).pop();
  167. goPage(receivedNotification.payload);
  168. },
  169. ),
  170. ],
  171. ),
  172. );
  173. });
  174. print('点击事件----selectNotificationSubject --');
  175. selectNotificationSubject.stream.listen((String payload) async {
  176. print('这里---推送点击');
  177. goPage(payload);
  178. });
  179. setAlias();
  180. }
  181. static bool hasInit = false;
  182. void initLocalPush() async {
  183. // needed if you intend to initialize in the `main` function
  184. WidgetsFlutterBinding.ensureInitialized();
  185. // NOTE: if you want to find out if the app was launched via notification then you could use the following call and then do something like
  186. // change the default route of the app
  187. // var notificationAppLaunchDetails =
  188. // await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
  189. var initializationSettingsAndroid =
  190. AndroidInitializationSettings('ic_launcher_1');
  191. ///android推送图标在drawable文件夹
  192. var initializationSettingsIOS = IOSInitializationSettings(
  193. onDidReceiveLocalNotification:
  194. (int id, String title, String body, String payload) async {
  195. print('onDidReceiveLocalNotification $payload');
  196. didReceiveLocalNotificationSubject.add(ReceivedNotification(
  197. id: id, title: title, body: body, payload: payload));
  198. });
  199. var initializationSettings = InitializationSettings(
  200. initializationSettingsAndroid, initializationSettingsIOS);
  201. print('点击事件初始化');
  202. bool isOK = await flutterLocalNotificationsPlugin.initialize(
  203. initializationSettings, onSelectNotification: (String payload) async {
  204. print('AAA这里---推送点击');
  205. selectNotificationSubject.add(payload);
  206. });
  207. print('点击事件初始化----$isOK');
  208. }
  209. String getPayload(Map notifition) {
  210. String payload = 'default';
  211. int type = int.parse(notifition['Type'].toString());
  212. print('onOpenNotification type:$type');
  213. switch (type) {
  214. case 1:
  215. payload = PAYLOAD_DATE + '@' + notifition['Id'].toString();
  216. break;
  217. case 2:
  218. payload = PAYLOAD_OTHER + '@' + InfoType.Apply.toString();
  219. break;
  220. case 3:
  221. payload = PAYLOAD_OTHER + '@' + InfoType.Apply.toString();
  222. break;
  223. case 4:
  224. payload = PAYLOAD_OTHER + '@' + InfoType.Money.toString();
  225. break;
  226. case 5:
  227. payload = PAYLOAD_OTHER + '@' + InfoType.System.toString();
  228. break;
  229. case 6:
  230. payload = PAYLOAD_FRIENDS + '@' + InfoType.Apply.toString();
  231. break;
  232. case 7:
  233. payload = PAYLOAD_OTHER + '@' + InfoType.System.toString();
  234. break;
  235. default:
  236. payload = 'default';
  237. break;
  238. }
  239. return payload;
  240. }
  241. void goPage(String payload) {
  242. print('goPage payload: $payload');
  243. print('### 开始跳转');
  244. if (payload != null) {
  245. if (payload == 'default') {
  246. return;
  247. }
  248. if (payload.startsWith(PAYLOAD_DATE)) {
  249. Navigator.of(mContext).push(
  250. MaterialPageRoute(
  251. builder: (mContext) {
  252. return ProgramDetailPage(
  253. programId: int.parse(payload.split('@')[1]),
  254. );
  255. },
  256. ),
  257. );
  258. } else if (payload.startsWith(PAYLOAD_FRIENDS)) {
  259. MessageMgr().emit('goto_new_friends');
  260. } else {
  261. int type = int.parse(payload.split('@')[1]);
  262. String title = '';
  263. switch (type) {
  264. case InfoType.Apply:
  265. title = I18n.of(mContext).application_notice;
  266. break;
  267. case InfoType.Money:
  268. title = I18n.of(mContext).wallet_reminder;
  269. break;
  270. case InfoType.System:
  271. title = I18n.of(mContext).appName;
  272. break;
  273. }
  274. Navigator.of(mContext).push(
  275. new MaterialPageRoute(
  276. builder: (context) {
  277. return InfoListPage(
  278. title: title,
  279. type: type,
  280. );
  281. },
  282. ),
  283. );
  284. }
  285. print('notification payload: ' + payload);
  286. }
  287. }
  288. Future<void> show(String title, String content, {int id}) async {
  289. if (!isBackground || !UserData().privatyMsgPushSwitch) {
  290. // print('程序在前台,不发生推送通知 || 用户关闭推送');
  291. return;
  292. }
  293. showNotification(title, content, id: id);
  294. }
  295. Future<void> showOtherNotification(
  296. Map notifition, String defaultTitle, String defaultContent) async {
  297. int type = notifition['Type'];
  298. String payload = 'default';
  299. bool needPush = true;
  300. switch (type) {
  301. case 1:
  302. needPush = UserData().newDateSwitch;
  303. payload = PAYLOAD_DATE + '@' + notifition['Id'].toString();
  304. break;
  305. case 2:
  306. needPush = UserData().applyCheckSwitch;
  307. payload = PAYLOAD_OTHER + '@' + InfoType.Apply.toString();
  308. break;
  309. case 3:
  310. needPush = UserData().acceptCheckSwitch;
  311. payload = PAYLOAD_OTHER + '@' + InfoType.Apply.toString();
  312. break;
  313. case 4:
  314. needPush = UserData().checkPhotoSwitch;
  315. payload = PAYLOAD_OTHER + '@' + InfoType.Money.toString();
  316. break;
  317. case 5:
  318. needPush = UserData().codeSucessSwitch;
  319. payload = PAYLOAD_OTHER + '@' + InfoType.System.toString();
  320. break;
  321. case 6:
  322. // needPush = UserData().codeSucessSwitch;
  323. payload = PAYLOAD_FRIENDS + '@' + InfoType.Apply.toString();
  324. break;
  325. case 7:
  326. payload = PAYLOAD_OTHER + '@' + InfoType.System.toString();
  327. break;
  328. default:
  329. payload = 'default';
  330. break;
  331. }
  332. print('showOtherNotification payload $payload');
  333. if (selectNotificationSubject == null) {
  334. print('selectNotificationSubject == null');
  335. } else {
  336. print('selectNotificationSubject 不空');
  337. }
  338. if (flutterLocalNotificationsPlugin == null) {
  339. print('flutterLocalNotificationsPlugin == null');
  340. } else {
  341. print('flutterLocalNotificationsPlugin 不空');
  342. }
  343. if (needPush) {
  344. showNotification(defaultTitle, defaultContent, payload: payload);
  345. }
  346. }
  347. void showNotification(String title, String content,
  348. {payload = 'default', int id}) async {
  349. if (id == null) {
  350. id = Random().nextInt(1000);
  351. }
  352. var androidPlatformChannelSpecifics = AndroidNotificationDetails(
  353. '668123', 'com.cyhd.henhoandroid.push', 'private message push',
  354. importance: Importance.Max, priority: Priority.High, ticker: title);
  355. var iOSPlatformChannelSpecifics = IOSNotificationDetails();
  356. var platformChannelSpecifics = NotificationDetails(
  357. androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
  358. print('payload- $payload');
  359. await flutterLocalNotificationsPlugin
  360. .show(id, title, content, platformChannelSpecifics, payload: payload);
  361. badgerCount++;
  362. FlutterAppBadger.updateBadgeCount(badgerCount);
  363. ///等极光修复了iOS本地推送点击事件后改为下面的方法
  364. // var fireDate = DateTime.fromMillisecondsSinceEpoch(
  365. // DateTime.now().millisecondsSinceEpoch + 3000);
  366. // var localNotification = LocalNotification(
  367. // id: 234,
  368. // title: 'fadsfa',
  369. // buildId: 1,
  370. // content: 'fdas',
  371. // fireTime: fireDate,
  372. // subtitle: 'fasf',
  373. // badge: 5,
  374. // extra: {"fa": "0"});
  375. // JPush jpush = new JPush();
  376. // jpush.sendLocalNotification(localNotification);
  377. }
  378. Future<void> cleanAllNotifications() async {
  379. await flutterLocalNotificationsPlugin.cancelAll();
  380. FlutterAppBadger.removeBadge();
  381. JPush jpush = new JPush();
  382. if (Platform.isIOS) {
  383. jpush.setBadge(0);
  384. }
  385. badgerCount = 0;
  386. FlutterAppBadger.updateBadgeCount(badgerCount);
  387. }
  388. void startPush() {
  389. JPush jpush = new JPush();
  390. jpush.resumePush();
  391. }
  392. void pausePush() {
  393. JPush jpush = new JPush();
  394. jpush.stopPush();
  395. }
  396. void dispose() {
  397. // if(didReceiveLocalNotificationSubject !=null && selectNotificationSubject !=null){
  398. // didReceiveLocalNotificationSubject.close();
  399. // selectNotificationSubject.close();
  400. // }
  401. }
  402. }