【问题标题】:IOS Expo Push Notifications when app is in foreground应用程序处于前台时的 IOS Expo 推送通知
【发布时间】:2018-07-04 09:38:11
【问题描述】:

阅读博览会文档:

对于 iOS,处理推送通知是明智之举 在应用程序处于前台时收到,否则用户 永远不会看到他们。应用程序运行时到达的通知 iOS 上的前台不显示在系统通知列表中。一种 常见的解决方案是手动显示通知。为了 例如,如果您在 Messenger for iOS 上收到一条消息,请让该应用程序 前景,但没有打开该对话,您将看到 通知从屏幕顶部向下滑动自定义 通知界面。

我不明白什么是最好的方法?是否有用于显示此类消息的 Expo API?还是我应该创建自己的警报组件?从文档中并不清楚。

谢谢。

【问题讨论】:

  • 是的,Expo 建议您编写一个“通知”组件,以便在应用程序处于前台时显示它。

标签: react-native push-notification expo


【解决方案1】:

现在您可以将其添加到您的应用入口点之一。 shouldShowAlert 是你想要的

import * as Notifications from 'expo-notifications';

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: false,
    shouldSetBadge: false,
  }),
});

【讨论】:

  • 这应该放在你的应用程序的什么地方?在功能组件之前,在 useEffect 内部和之上,在 useEffect 之外?
  • 在 App.js 或 index.js 的外部,如果你愿意,你可以将它放在 useEffect 中,但我在外部没有问题。
  • 对我来说,我只在前台没有收到任何通知。我在堆栈帖子中发布了我的代码,但很奇怪它不起作用。
  • 如果你有链接,我可以看看:)
【解决方案2】:

App.json :

{
  "expo": {
    "notification": {
      "iosDisplayInForeground": true
    }
}

【讨论】:

    【解决方案3】:

    DEMO

    我不确定它是什么时候添加到 Expo 中的,但从 Expo 36 版开始很容易实现。

    要在您的应用处于前台时在 iOS 上显示 Expo Push Notifications,请执行以下操作:

    
    import { Vibration } from "react-native";  
    import { Notifications } from "expo";  
    import * as Permissions from "expo-permissions";  
    import Constants from "expo-constants";
    
    registerForPushNotificationsAsync = async () => {                          
      if (Constants.isDevice) {                                                
        const { status: existingStatus } = await Permissions.getAsync(         
          Permissions.NOTIFICATIONS                                            
        );                                                                     
        let finalStatus = existingStatus;                                      
        if (existingStatus !== "granted") {                                    
          const { status } = await Permissions.askAsync(                       
            Permissions.NOTIFICATIONS                                          
          );                                                                   
          finalStatus = status;                                                
        }                                                                      
        if (finalStatus !== "granted") {                                       
          alert("Failed to get push token for push notification!");            
          return;                                                              
        }                                                                      
        let token = await Notifications.getExpoPushTokenAsync();
        console.log("Go to https://expo.io/notifications and copy the token below to easily send yourself a notification.");
        console.warn("Notifications on iOS (and I believe Android) ONLY WORK ON A PHYSICAL DEVICE, not a simulator or emulator!!!")               
        console.log(token);                                                    
        this.setState({ expoPushToken: token });                               
      } else {                                                                 
        alert("Must use physical device for Push Notifications");              
      }                                                                        
    };                                                                         
    
    componentDidMount() {                                                      
      this.registerForPushNotificationsAsync();                                                
      this._notificationSubscription = Notifications.addListener(              
        this._handleNotification                                               
      );                                                                       
    }
    
    _handleNotification = async notification => {                                                                                    
      if (notification.remote) {
        Vibration.vibrate();                                                  
        const notificationId = Notifications.presentLocalNotificationAsync({      
          title: "Follow @technoplato",  
          body: "To learn yourself goodly (also follow PewDiePie)",                                             
          ios: { _displayInForeground: true } // <-- HERE'S WHERE THE MAGIC HAPPENS                                
        });                                                                       
      }                                                   
    };                                                                                                                                                      
    

    快速简单的健全性检查

    1) 去这里:https://expo.io/notifications

    2) 将应用程序运行时输出的令牌复制到终端。

    3) 在 iOS 上打开您的应用程序。

    4) 从https://expo.io/notifications 向您自己发送一个通知,并观察它即使在您的应用程序处于前台时也会显示。


    备注

    • IOS 模拟器不会收到通知

    • Expo 让通知变得异常简单。老实说,我不敢相信。

    不知道为什么 displayInForeground 默认为 false 并且在文档中并不突出。如果可以,我会为此提交 PR。

    最初在此小吃中找到的代码:https://snack.expo.io/@documentation/pushnotifications?platform=ios

    LocalNotification.ios._displayInForeground 在这里找到:https://docs.expo.io/versions/v36.0.0/sdk/notifications/#localnotification

    【讨论】:

    • 这篇文章是关于本地通知的。 (推送通知是远程通知)
    【解决方案4】:

    截至 2020 年 2 月 20 日,此答案已过时。请参阅https://stackoverflow.com/a/60344280/2441420,了解如何在您的应用程序处于前台时显示 iOS 通知

    没有用于显示这些消息的 Expo API。您可以使用您选择的任何“toast”库并显示通知消息,但这应该是您的全部代码。

    例如,这就是我们现在的做法:

    export default class HomeScreen extends React.Component {
    
      componentDidMount() {
        this.notificationSubscription = Notifications.addListener(
          (notification) => this.handlePushNotification(notification),
        );
      }
    
      handlePushNotification(notification) {
        const { navigation } = this.props;
        PushNotificationsService.handleNotification(notification, navigation);
      }
    

    (...)

    import Toast from 'react-native-root-toast';
    
    export default class PushNotificationsService {
    
      static handleNotification(notification, navigation) {
    
        if (notification.data.screen && notification.origin === 'selected') {
          navigation.navigate(notification.data.screen);
        }
        Toast.show(notification.data.message);
      }
    
    }
    

    Toast 库包括:

    【讨论】:

    • 有没有办法将通知传递给 iOS 默认行为?类似于 PushNotificationsIOS.presentLocalNotification 的那种?
    • @nicholas 在我们的测试Expo 的Notifications.presentLocalNotificationAsync 不幸的是什么也没做。实际上,它做了一件事:它(讽刺地)触发了事件监听器,因此调用了this.handlePushNotification,这会创建一个无限循环并冻结应用程序,但即使我们以这样的方式编写代码以避免循环,我们也可以' t 获得要显示的本地通知。
    • @nicholas 从世博会 v36 开始,不需要管道任何东西。请看我的回答stackoverflow.com/a/60344280/2441420
    • @sandre89 禁用无限循环可能仍需要该解决方法,但您可以通过在LocalNotification 对象中启用 ios._displayInForeground 标志来显示带有Notifications.presentLocalNotificationAsync 的通知。请看我的回答:stackoverflow.com/a/60344280/2441420
    猜你喜欢
    • 2021-04-19
    • 1970-01-01
    • 2017-10-31
    • 2018-08-03
    • 1970-01-01
    • 2017-06-26
    • 2013-01-30
    • 1970-01-01
    相关资源
    最近更新 更多