【问题标题】:Cannot receive specific user push notification using azure notification hub无法使用 Azure 通知中心接收特定用户推送通知
【发布时间】:2016-11-29 23:59:48
【问题描述】:

我正在尝试学习使用 azure 移动应用,但在使用 NotificationHub 时遇到了严重问题。我有 Azure 的 Imagine 订阅。我创建了一个带有 azure 后端的 android 移动应用。我在 azure 门户上创建了一个与 azure 移动应用关联的通知中心。 为了在通知中心注册应用程序,我使用了本教程中的代码:

https://docs.microsoft.com/en-gb/azure/notification-hubs/notification-hubs-android-push-notification-google-fcm-get-started

用户在 azure 后端通过身份验证之前使用他们的 google 帐户、microsoft 帐户或 facebook 帐户。通过为表脚本 Users.js 编写的以下节点 js 代码将新用户插入到表 Users 中。我想要一个推送通知来欢迎新用户

var azureMobileApps = require('azure-mobile-apps');
var logger = require('azure-mobile-apps/src/logger');
var table = azureMobileApps.table();

table.access = 'authenticated';

/**
* Adds the email address from the claims to the context item - used for
* insert operations
* @param {Context} context the operation context
* @returns {Promise} context execution Promise
*/
function addEmailToContext(context) {
    /*
    * Getting claim fields
    */
    return context.user.getIdentity().then((data) => {
       if( data.microsoftaccount != undefined){
            context.item.email = data.microsoftaccount.claims.emailaddress;
            context.item.name = data.microsoftaccount.claims.givenname;
            context.item.surname = data.microsoftaccount.claims.surname;           
       }
       if( data.google != undefined){
            context.item.email = data.google.claims.emailaddress;
            context.item.name = data.google.claims.givenname;
            context.item.surname = data.google.claims.surname;
            context.item.picture_url = data.google.claims.picture;
       }
       if( data.facebook != undefined){
            context.item.email = data.facebook.claims.emailaddress;
            context.item.name = data.facebook.claims.givenname;
            context.item.surname = data.facebook.claims.surname;
       }

       logger.info('[tables/Users.js] --> NEW USER REGISTERED:'
                +'\n\t Name:'+context.item.name
                +'\n\t Surname:'+context.item.surname
                +'\n\t Email:'+context.item.email);


    // Execute the insert.  The insert returns the results as a Promise,
    // Do the push as a post-execute action within the promise flow.
    return context.execute()
        .then(function (results) {
            // Only do the push if configured
            if (context.push) {
                // Mobile Apps adds a user tag when registering for push notifications

                 // Define the GCM payload.
                 var payload = {
                     "data": {
                         "message": 'Welcome '+context.item.username
                     }
                 };       

                context.push.gcm.send(context.user.id, payload, function (error) {
                    if (error) {
                        logger.error('Error while sending push notification: ', error);
                    } else {
                        logger.info('Push notification sent successfully!');
                    }
                });
            }
            // Don't forget to return the results from the context.execute()
            return results;
        })
        .catch(function (error) {
            logger.error('Error while running context.execute: ', error);
        });
    });
}

// CREATE - add or overwrite the authenticated user
table.insert(addEmailToContext);

module.exports = table;

根据How to use the Azure Mobile Apps Node.js SDK教程中的“如何:使用标签向经过身份验证的用户发送推送通知”

“当认证用户注册推送通知时,用户ID标签会自动添加到注册中。” 因此,在 Users.js 中,按照本教程的建议,我编写了以下代码来向用户发送推送通知。

context.push.gcm.send(context.user.id, payload, function (error) {
                    if (error) {
                        logger.error('Error while sending push notification: ', error);
                    } else {
                        logger.info('Push notification sent successfully!');
                    }
                });

使用此代码可以成功发送推送通知,但设备没有收到任何通知。如果我使用 null 而不是 context.user.id 那么所有设备都会正确接收推送通知

context.push.gcm.send(null, payload, function (error) {
                    if (error) {
                        logger.error('Error while sending push notification: ', error);
                    } else {
                        logger.info('Push notification sent successfully!');
                    }
                });

当用户注册到集线器时,我还尝试调用以下自定义 API 来创建标签。调用的API如下:

var logger = require('azure-mobile-apps/src/logger');

exports.post = function(req, res) {
    logger.info('[api/registerTag.js] --> Invoked');

        // Get the notification hub used by the mobile app.
        var push = req.azureMobile.push,
            installationId = req.get('X-ZUMO-INSTALLATION-ID'),
            tags = req.body.tag.toString();



        // Define an update tags operation.
        var updateOperation = [{
            "op": "add",
            "path": "/tags",
            "value": tags
        }];

        // Update the installation to add the new tags.
        push.patchInstallation(installationId, updateOperation, function(error) {
            if(error){
                logger.error('[api/registerTag.js] --> An error occurred while adding'
                            +'the following tags: \n\t'+tags, error);
                res.status(error.statusCode).send(error.detail);
            } else {
                logger.info('[api/registerTag.js] --> The following tags have been added' 
                            +'to the Notification Hub: \n\t'+tags, error);
                res.status(200).send(tags);
            }
        });
};

在控制台上打印标签已成功添加。但是,如果我然后像这样修改 Users.js 代码:

...
// Only do the push if configured
            if (context.push) {
                // Mobile Apps adds a user tag when registering for push notifications
                var userTag = '_UserId:' + context.user.id;
                logger.info("TAG   "+userTag);

                 // Define the GCM payload.
                 var payload = {
                     "data": {
                         "message": 'Welcome '+context.item.username
                     }
                 };       

                context.push.gcm.send(userTag, payload, function (error) {
                    if (error) {
                        logger.error('Error while sending push notification: ', error);
                    } else {
                        logger.info('Push notification sent successfully!');
                    }
                });
            }
...

再次没有收到任何东西。我还尝试了将标签列入白名单或使用移动应用程序的“推送”部分自动添加它们,如图所示:

图片链接:i.stack.imgur.com/KBvQI.png

但问题仍然存在。希望可以有人帮帮我。谢谢。

【问题讨论】:

    标签: android node.js azure azure-mobile-services azure-notificationhub


    【解决方案1】:

    经过多次测试,我成功重现了你的问题,也遇到了同样的问题。为了满足您的要求,我在 Android 客户端做了一些修改:

    1、在MainActivity类中缓存认证用户。以下是我的代码 sn-p。更多详情可以参考here

    public static final String SHAREDPREFFILE = "temp";    
    public static final String USERIDPREF = "uid";    
    public static final String TOKENPREF = "tkn";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        try {
            // Create the Mobile Service Client instance, using the provided Mobile Service URL and key
            mClient = new MobileServiceClient(
                    "https://yourwebsitename.azurewebsites.net",
                    this).withFilter(new ProgressFilter());
    
            // Extend timeout from default of 10s to 20s
            mClient.setAndroidHttpClientFactory(new OkHttpClientFactory() {
                @Override
                public OkHttpClient createOkHttpClient() {
                    OkHttpClient client = new OkHttpClient();
                    client.setReadTimeout(20, TimeUnit.SECONDS);
                    client.setWriteTimeout(20, TimeUnit.SECONDS);
                    return client;
                }
            });
    
            authenticate();
    
        } catch (MalformedURLException e) {
            createAndShowDialog(new Exception("There was an error creating the Mobile Service. Verify the URL"), "Error");
        } catch (Exception e){
            createAndShowDialog(e, "Error");
        }
    }
    
    private void authenticate() {
        // We first try to load a token cache if one exists.
        if (loadUserTokenCache(mClient)) {
            createTable();
            register();
        }
        // If we failed to load a token cache, login and create a token cache
        else {
            // Login using the Google provider.
            ListenableFuture<MobileServiceUser> mLogin = mClient.login(MobileServiceAuthenticationProvider.Google);
    
            Futures.addCallback(mLogin, new FutureCallback<MobileServiceUser>() {
                @Override
                public void onFailure(Throwable exc) {
                    createAndShowDialog("You must log in. Login Required", "Error");
                }
                @Override
                public void onSuccess(MobileServiceUser user) {
                    createAndShowDialog(String.format("You are now logged in - %1$2s", user.getUserId()), "Success");
                    cacheUserToken(mClient.getCurrentUser());
                    createTable();
                    register();
                }
            });
        }
    }
    
    private void cacheUserToken(MobileServiceUser user) {
        SharedPreferences prefs = getSharedPreferences(SHAREDPREFFILE, Context.MODE_PRIVATE);
        Editor editor = prefs.edit();
        editor.putString(USERIDPREF, user.getUserId());
        editor.putString(TOKENPREF, user.getAuthenticationToken());
        editor.commit();
    }
    
    private void register() {
        NotificationsManager.handleNotifications(this, NotificationSettings.SenderId, MyHandler.class);
        registerWithNotificationHubs();
    }
    

    2、在RegistrationIntentService类中将regID = hub.register(FCM_token).getRegistrationId();替换为以下代码:

    regID = hub.register(FCM_token, prefs.getString("uid", "")).getRegistrationId();
    

    3,确保将下面的行添加到onHandleIntent方法中的第一行。

    SharedPreferences prefs = getSharedPreferences("temp", Context.MODE_PRIVATE);
    

    【讨论】:

    • 非常感谢!!推送通知现在使用 context.push.gcm.send(context.user.id, [...] ) 按预期工作。非常感谢您的帮助:D
    • 还有一件事!您是否知道是否有任何方法可以直观地调试通知中心并在此链接link 上查看 Visual Studio Server Explorer 中显示的标签,但使用 免费想象订阅乙>?不幸的是,此订阅不允许我在 Visual Studio 的服务器资源管理器中查看通知中心:(
    • 启动 Visual Studio,单击 view 找到 Server Explorer,登录 Azure 并展开以找到您的通知中心。双击它会给你一个包含当前注册的窗口。
    • 不幸的是,我收到以下消息:“服务器资源管理器不支持一个或多个订阅”。我为学生免费提供了 Imagine 订阅(DreamSpark 优惠)。
    猜你喜欢
    • 2015-11-26
    • 2020-12-24
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    • 2016-02-24
    • 2013-01-21
    • 2019-08-25
    • 1970-01-01
    相关资源
    最近更新 更多