Hibok
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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