usePushNotifications.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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. } as any)
  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. });
  33. return () => {
  34. Notifications.removeNotificationSubscription(notificationListener.current!);
  35. Notifications.removeNotificationSubscription(responseListener.current!);
  36. };
  37. }, []);
  38. return {
  39. expoPushToken,
  40. notification
  41. };
  42. };
  43. async function registerForPushNotificationAsync() {
  44. let token;
  45. // Check if the device is a physical device, because this only works for physical devices not simulators
  46. if (Device.isDevice) {
  47. const { status: existingStatus } = await Notifications.getPermissionsAsync();
  48. let finalStatus = existingStatus;
  49. if (existingStatus !== 'granted') {
  50. const { status } = await Notifications.requestPermissionsAsync();
  51. finalStatus = status;
  52. }
  53. if (finalStatus !== 'granted') {
  54. alert('需要通知權限才能接收充電狀態更新。請前往「設定」>「通知」中開啟 CrazyCharge 的通知權限。');
  55. return;
  56. }
  57. //if we have permission, then get the token
  58. token = await Notifications.getExpoPushTokenAsync({
  59. projectId: Constants.expoConfig?.extra?.eas?.projectId
  60. });
  61. if (Platform.OS === 'android') {
  62. Notifications.setNotificationChannelAsync('default', {
  63. name: 'default',
  64. importance: Notifications.AndroidImportance.MAX,
  65. vibrationPattern: [0, 250, 250, 250],
  66. lightColor: '#FF231F7C'
  67. });
  68. }
  69. return token;
  70. } else {
  71. }
  72. }