Android 中的推送通知仅在 PhoneGap 应用程序在前台使用 node-pushnotifications 时有效

Posted

技术标签:

【中文标题】Android 中的推送通知仅在 PhoneGap 应用程序在前台使用 node-pushnotifications 时有效【英文标题】:Push notifications in Android only work when PhoneGap app is in foreground using node-pushnotifications 【发布时间】:2020-11-18 18:30:52 【问题描述】:

在我的 PhoneGap / Cordova 应用程序(使用 Framework7)中,我使用 <plugin name="phonegap-plugin-push" source="npm" spec="2.3.0" /> 来启用推送通知。在项目文件夹的根目录中,我放置了google-services.json 文件。当用户登录我的应用程序时,设备令牌会在我的服务器上注册。接下来,我使用node-pushnotifications 模块向这些令牌发送推送通知。

对于 ios 设备,一切都按预期运行,但对于 android,它仅在应用处于前台时才有效。当我在应用程序处于后台时发送推送通知时,似乎什么都没有发生。当应用程序打开(回到前台)时,显示已错过的通知(更准确地说,弹出消息显示“新消息已到达”,对于每个“错过”的推送通知,这是预期的行为当应用程序处于前台模式时)。

我在 *** 上找到了几个相关的问题和答案,但它们并没有解决我的问题,但也许我在这些答案中遗漏了一些东西?例如,有人建议您需要指定一个message 变量。但是当我将它包含在服务器代码中时,会发生解析错误。另外,根据我对node-pushnotifications 模块说明的阅读,这应该没有必要。

===

更新 1

当我使用 Firebase 控制台向 Android 设备发送推送消息时,一切正常(当应用处于后台时,推送消息会显示)。我怀疑原因在于node-pushnotifications 模块。

到目前为止我所尝试的node-pushnotifications 模块设置中,我有:

    icon设置为默认值; 将sound设置为默认值; 将ID设置为SenderID(导致失败-->通知未发送); 将phonegap 设置为false(导致失败 --> 未发送通知)

===

更新 2

当应用程序处于后台时(但不是在应用程序关闭时),使用 node-gcm 模块正确传递推送通知。

===

欢迎任何帮助使用node-pushnotifications 完成这项工作。我很乐意在需要时提供更多解释和细节。

应用中的代码

基于http://macdonst.github.io/push-workshop/提供的代码

注意。对于SenderID,我使用了 Firebase 中/由 Firebase 生成的发件人 ID 密钥。

var message = 
    // Application Constructor
    initialize: function() 
        this.bindEvents();
    ,
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() 
        document.addEventListener('deviceready', this.onDeviceReady, false);
        document.getElementById("toggleBtn").addEventListener('click', this.toggle, false);
    ,
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicitly call 'app.receivedEvent(...);'
    onDeviceReady: function() 
      message.push = PushNotification.init(
           "android": 
             "senderID": "**********"
           ,
           "ios": 
             "sound": true,
             "vibration": true,
             "badge": false
           ,
           "windows": 
       );

       message.push.on('registration', function(data) 
           var oldRegId = localStorage.getItem('registrationId');
           if (oldRegId !== data.registrationId) 
               // Save new registration ID
               localStorage.setItem('registrationId', data.registrationId);
               // Post registrationId to your app server as the value has changed
               var uname= window.localStorage.getItem('uname');
               var pwd= window.localStorage.getItem('pwd');
               var devicetoken=localStorage.getItem('registrationId');
               
               var dataString="uname="+uname+"&pwd="+pwd+"&devicetoken="+devicetoken+"&updateregistration=yes";
            
                $.ajax(
                    type:"POST",  
                    url:"******************", data: dataString,
                    crossDomain: true,
                    cache: false, 
                    success:function(data)  
                      
                      
                );  
   
           
       );

       message.push.on('error', function(e) 
           console.log("push error = " + e.message);
       );

        message.push.on('notification', function(data) 
          console.log('notification event');
            
          app.dialog.alert("You have a new message", function () 
              
                        app.views.main.router.navigate('/messages/');

            );
        
        );
    
;

message.initialize();

服务器上的代码

基于https://github.com/appfeel/node-pushnotifications提供的代码

注意。对于gcm id,我使用了由 Firebase 生成的服务器密钥。

// Step 1: configure push notification settings
var PushNotifications = require('node-pushnotifications')

const settings = 
    gcm: 
       id: '*******',
       phonegap: true, // phonegap compatibility mode, see below (defaults to false)
    ,
    apn: 
       token: 
            key: '*******', // optionally: fs.readFileSync('./certs/key.p8')
            keyId: '*******',
            teamId: '*******',
        ,
        production: true // true for APN production environment, false for APN sandbox environment,
        //...
    ,
    isAlwaysUseFCM: false, // true all messages will be sent through node-gcm (which actually uses FCM)
;
const push = new PushNotifications(settings);

// Step 2 create the notification
const data = 
    title: 'New push notification', // REQUIRED for Android
    topic: '**********', // REQUIRED for iOS (apn and gcm)
    /* The topic of the notification. When using token-based authentication, specify the bundle ID of the app.
     * When using certificate-based authentication, the topic is usually your app's bundle ID.
     * More details can be found under https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns
     */
    body: 'Powered by AppFeel',
    custom: 
        sender: 'AppFeel',
    ,
    priority: 'high', // gcm, apn. Supported values are 'high' or 'normal' (gcm). Will be translated to 10 and 5 for apn. Defaults to 'high'
    collapseKey: '', // gcm for android, used as collapseId in apn
    contentAvailable: true, // gcm, apn. node-apn will translate true to 1 as required by apn.
    delayWhileIdle: true, // gcm for android
    restrictedPackageName: '', // gcm for android
    dryRun: false, // gcm for android
    icon: '', // gcm for android
    image: '', // gcm for android
    style: '', // gcm for android
    picture: '', // gcm for android
    tag: '', // gcm for android
    color: '', // gcm for android
    clickAction: '', // gcm for android. In ios, category will be used if not supplied
    locKey: '', // gcm, apn
    locArgs: '', // gcm, apn
    titleLocKey: '', // gcm, apn
    titleLocArgs: '', // gcm, apn
    retries: 1, // gcm, apn
    encoding: '', // apn
    badge: 2, // gcm for ios, apn
    sound: 'ping.aiff', // gcm, apn
    android_channel_id: '', // gcm - Android Channel ID
    notificationCount: 0, // fcm for android. badge can be used for both fcm and apn
    alert:  // apn, will take precedence over title and body
        title: 'title',
        body: 'body'
        // details: https://github.com/node-apn/node-apn/blob/master/doc/notification.markdown#convenience-setters
    ,
    silent: false, // apn, will override badge, sound, alert and priority if set to true
    /*
     * A string is also accepted as a payload for alert
     * Your notification won't appear on ios if alert is empty object
     * If alert is an empty string the regular 'title' and 'body' will show in Notification
     */
    // alert: '',
    launchImage: '', // apn and gcm for ios
    action: '', // apn and gcm for ios
    category: '', // apn and gcm for ios
    // mdm: '', // apn and gcm for ios. Use this to send Mobile Device Management commands.
    // https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/MobileDeviceManagementProtocolRef/3-MDM_Protocol/MDM_Protocol.html
    urlArgs: '', // apn and gcm for ios
    truncateAtWordEnd: true, // apn and gcm for ios
    mutableContent: 0, // apn
    threadId: '', // apn
    pushType: undefined, // apn. valid values are 'alert' and 'background' (https://github.com/parse-community/node-apn/blob/master/doc/notification.markdown#notificationpushtype)
    expiry: Math.floor(Date.now() / 1000) + 28 * 86400, // unit is seconds. if both expiry and timeToLive are given, expiry will take precedence
    timeToLive: 28 * 86400,
    headers: [], // wns
    launch: '', // wns
    duration: '', // wns
    consolidationKey: 'my notification', // ADM
;

【问题讨论】:

【参考方案1】:

这是我实施的解决方案(目前在 Android 10 和 iOS 13.6 上运行和测试)

它可以帮助您轻松地在后台、前台、使用时、手机锁定时显示自定义推送通知。

我在 CLI 中的配置:

cordova -v

7.1.0

cordova platforms

安卓 8.0.0

iOS 4.5.5

cordova plugins

phonegap-plugin-push 2.3.0 "PushPlugin"

phonegap-plugin-multidex 1.0.0 "Multidex"

我正在使用的 JS 应用代码

document.addEventListener("deviceready", registrarDevice, false);

function registrarDevice() 
    try 
        var push = PushNotification.init(
            android: 
                senderID: "YOUR_SENDER_ID_FROM_FIREBASE"
            ,
            browser: 
                pushServiceURL: 'http://push.api.phonegap.com/v1/push'
            ,
            ios: 
                alert: "true",
                badge: "true",
                sound: "true"
            ,
            windows: 
        );

        push.on('registration', function (data) 
            // data.registrationId
            console.log(data);
        );

        push.on('notification', function (data) 
            console.log(data);
            // data.message,
            // data.title,
            // data.count,
            // data.sound,
            // data.image,
            // data.additionalData
        );

        push.on('error', function (e) 
            // e.message
            console.log(e);
        );
     catch (err) 
        console.log("Error registrarDevice: ", err.message);
    

我服务器上的 PHP 代码

class FCM 
    function __construct() 
    

    public function send_push_notification($registatoin_ids, $notification, $device_type) 
        $url = 'https://fcm.googleapis.com/fcm/send';
        if($device_type == "Android")
            $fields = array(
                'to' => $registatoin_ids,
                'data' => $notification
            );
         else 
            $fields = array(
                'to' => $registatoin_ids,
                'notification' => $notification
            );
        
        // Your Firebase Server API Key
        $apikey = "YOUR_FIREBASE_SERVER_API_KEY";
        $headers = array('Authorization:key='.$apikey,'Content-Type:application/json');
        // Open curl connection
        $ch = curl_init();
        // Set the url, number of POST vars, POST data
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
        $result = curl_exec($ch);
        if ($result === FALSE) 
            die('Curl failed: ' . curl_error($ch));
        
        curl_close($ch);
    
   


function notificaciones_android_base($xdevice_destino,$xtitulo,$xtexto)
    $NotificationArray= array();                                                        
    $NotificationArray["body"] = $xtexto;
    $NotificationArray["title"] = $xtitulo;
    $NotificationArray["sound"] = "default";
    $NotificationArray["type"] = 1;

    $fcm = new FCM();
    $retresult = $fcm->send_push_notification($xdevice_destino, $NotificationArray, "Android");

    return $retresult;



$info_test="Greetings folks!, Testing de push message :-)";
echo "<br>".notificaciones_android_base("YOUR_DEVICE_ID","NotificationTitle2021",$info_test);

【讨论】:

谢谢!该应用程序目前正在生产中,我会在一段时间内尝试您的解决方案(然后删除此评论)。 不客气。您目前正在使用 iOS 推送通知吗?

以上是关于Android 中的推送通知仅在 PhoneGap 应用程序在前台使用 node-pushnotifications 时有效的主要内容,如果未能解决你的问题,请参考以下文章

当我的应用程序打开时,我需要推送通知显示,如 Android 中的 whatsapp、Viber(Phonegap)

Sencha Phonegap Android 推送通知

适用于 Android 的 Phonegap 推送通知

单击时,Phonegap 推送通知重定向到应用程序中的特定页面

Phonegap 状态栏通知,Android,iOS

PhoneGap-Android:Urban Airship 从我的服务器推送通知