usePushNotifications.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { useEffect, useState, useRef } from 'react';
  2. import * as Notifications from 'expo-notifications';
  3. import * as Device from 'expo-device';
  4. import Constants from 'expo-constants';
  5. import { Platform } from 'react-native';
  6. export interface PushNotificationState {
  7. notification?: Notifications.Notification;
  8. expoPushToken?: Notifications.ExpoPushToken;
  9. }
  10. export const usePushNotifications = (): PushNotificationState => {
  11. const [expoPushToken, setExpoPushToken] = useState<Notifications.ExpoPushToken | undefined>();
  12. const [notification, setNotification] = useState<Notifications.Notification | undefined>();
  13. const notificationListener = useRef<Notifications.Subscription>();
  14. const responseListener = useRef<Notifications.Subscription>();
  15. useEffect(() => {
  16. Notifications.setNotificationHandler({
  17. handleNotification: async () => ({
  18. shouldPlaySound: true,
  19. shouldShowAlert: true,
  20. shouldSetBadge: true,
  21. vibrate: true,
  22. shouldShowWhenInForeground: true
  23. })
  24. });
  25. registerForPushNotificationAsync().then((token) => {
  26. setExpoPushToken(token);
  27. });
  28. notificationListener.current = Notifications.addNotificationReceivedListener((notification) => {
  29. setNotification(notification);
  30. });
  31. responseListener.current = Notifications.addNotificationResponseReceivedListener((response) => {
  32. console.log(response);
  33. });
  34. return () => {
  35. Notifications.removeNotificationSubscription(notificationListener.current!);
  36. Notifications.removeNotificationSubscription(responseListener.current!);
  37. };
  38. }, []);
  39. return {
  40. expoPushToken,
  41. notification
  42. };
  43. };
  44. async function registerForPushNotificationAsync() {
  45. let token;
  46. // Check if the device is a physical device, because this only works for physical devices not simulators
  47. if (Device.isDevice) {
  48. const { status: existingStatus } = await Notifications.getPermissionsAsync();
  49. let finalStatus = existingStatus;
  50. if (existingStatus !== 'granted') {
  51. const { status } = await Notifications.requestPermissionsAsync();
  52. finalStatus = status;
  53. }
  54. if (finalStatus !== 'granted') {
  55. alert('需要通知權限才能接收充電狀態更新。請前往「設定」>「通知」中開啟 CrazyCharge 的通知權限。');
  56. return;
  57. }
  58. //if we have permission, then get the token
  59. token = await Notifications.getExpoPushTokenAsync({
  60. projectId: Constants.expoConfig?.extra?.eas?.projectId
  61. });
  62. if (Platform.OS === 'android') {
  63. Notifications.setNotificationChannelAsync('default', {
  64. name: 'default',
  65. importance: Notifications.AndroidImportance.MAX,
  66. vibrationPattern: [0, 250, 250, 250],
  67. lightColor: '#FF231F7C'
  68. });
  69. }
  70. // console.log('token', token);
  71. return token;
  72. } else {
  73. console.log('Must use physical device for Push Notifications');
  74. }
  75. }