无法使用 azure 通知中心接收特定用户推送通知

Cannot receive specific user push notification using azure notification hub

我正在尝试学习使用 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 帐户进行身份验证。通过为 table 脚本 Users.js 编写的以下节点 js 代码将新用户插入到 table 用户中。我想要一个 推送通知来欢迎新用户

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

教程中的 "How to: Send push notifications to an authenticated user using tags"

"When an authenticated user registers for push notifications, a user ID tag is automatically added to the registration. " 所以在 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!');
                    }
                });
            }
...

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

图片LINK: i.stack.imgur.com/KBvQI.png

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

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

1、在MainActivityclass缓存认证用户。以下是我的代码片段。更多详情可以参考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 - %1s", 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、在RegistrationIntentServiceclass中将regID = hub.register(FCM_token).getRegistrationId();替换为以下代码:

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

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

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