We are implementing an application using Unity 3d and we are consuming the Azure Push Notification REST API.
But there are a couple of issues and questions on how to successfully send and receive the message.
For testing we are using Advanced Rest client extension for chrome.
We are able to create the registration by using the native template ( check https://msdn.microsoft.com/en-us/library/azure/dn223265.aspx )
<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom">
<content type="application/xml">
<GcmRegistrationDescription xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">
<Tags></Tags>
<GcmRegistrationId>Some Id from somewhere</GcmRegistrationId>
</GcmRegistrationDescription>
</content>
</entry>
So far we are sending the request with empty Tags, and we are not sure what the GcmRegistration should be, the weird thing is that no matter what we send there we get a valid response.
<entry a:etag="W/"1"">
<id>https://cloudservicechat-ns.servicebus.windows.net/cloudservicechat/registrations/8760279628548469956-1956153846630646542-1?api-version=2015-01</id>
<title type="text">8760279628548469956-1956153846630646542-1</title>
<published>2016-06-01T15:15:16Z</published>
<updated>2016-06-01T15:15:16Z</updated>
<link rel="self" href="https://cloudservicechat-ns.servicebus.windows.net/cloudservicechat/registrations/8760279628548469956-1956153846630646542-1?api-version=2015-01" />
<content type="application/xml">
<GcmRegistrationDescription>
<ETag>1</ETag>
<ExpirationTime>2016-08-30T15:15:16.215Z</ExpirationTime>
<RegistrationId>8760279628548469956-1956153846630646542-1</RegistrationId>
<GcmRegistrationId>Some Id from somewhere</GcmRegistrationId>
</GcmRegistrationDescription>
</content>
</entry>
Now we are trying to send the notification (https://msdn.microsoft.com/en-us/library/azure/dn223273.aspx) but we are not sure of the correct payload to use from azure when using GCM
According to the documentation in GCM
the payload would be something like this
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification" : {
"body" : "great match!",
"title" : "Portugal vs. Denmark",
"icon" : "myicon"
}
}
However no matter what we do, we always get an Unauthorized response.
Also tried to use the registration using templates, but we are not sure what we should add in (check https://msdn.microsoft.com/en-us/library/azure/dn223265.aspx)
So the questions would be
* Where we can get the GcmRegistrationId from?
* How we should replace format the {BodyTemplate}
* What would be a valid notification payload to use using Azure Test Send
Thanks for the help
Based from this documentation, you need to add the parameter gcmRegistrationId in the MyHandler class to override the onRegistered method, which registers your device with the mobile service Notification Hub. Example:
#Override
public void onRegistered(Context context, final String gcmRegistrationId) {
super.onRegistered(context, gcmRegistrationId);
new AsyncTask<Void, Void, Void>() {
protected Void doInBackground(Void... params) {
try {
ToDoActivity.mClient.getPush().register(gcmRegistrationId, null);
return null;
}
catch(Exception e) {
// handle error
}
return null;
}
}.execute();
}
You can read in this documentation the steps on how to use templates to send platform-agnostic notifications targeting all your devices across platforms, and to personalize broadcast notification to each device.
The standard way to send push notifications is to send, for each notification that is to be sent, a specific payload to platform notification services (WNS, APNS). For example, to send an alert to APNS, the payload is a Json object of the following form:
{"aps": {"alert" : "Hello!" }}
You can check these related threads:
Adding Google GCM Api Key Azure Notification Hub Error
NotificationHubUnauthorizedException: Unauthorized on Azure Notification Hub registration
Related
I created Azure Notification Hub and added the server key from Firebase to the section "GCM/FCM" in notification hub. After which, I used the shared access key and notification hub name to create the installation (following the Azure documentation). Here's the code that I used:
[FunctionName("TestFunction")]
public static async Task<IActionResult> RunAsync(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]
HttpRequest req, ILogger log)
{
var deviceUpdate = new DeviceInstallation()
{
installationId = "<myInstallationid>",
pushChannel = "<DeviceTokenGeneratedByFirebase>",
platform = "fcm",
tags = new string[] {"notificationhubtag1"},
};
var responseMessage = new HttpResponseMessage();
try
{
responseMessage = await Put(deviceUpdate);
}
catch
{
log.LogInformation("exception occured");
}
return new OkObjectResult(responseMessage);
}
// Custom API
public static async Task<HttpResponseMessage> Put(DeviceInstallation deviceUpdate)
{
NotificationHubClient hub = new NotificationHubClient(fullAccessConnString, hubName);
Installation installation = new Installation();
installation.InstallationId = deviceUpdate.installationId;
installation.PushChannel = deviceUpdate.pushChannel;
installation.Tags = deviceUpdate.tags;
switch (deviceUpdate.platform)
{
case "mpns":
installation.Platform = NotificationPlatform.Mpns;
break;
case "wns":
installation.Platform = NotificationPlatform.Wns;
break;
case "apns":
installation.Platform = NotificationPlatform.Apns;
break;
case "fcm":
installation.Platform = NotificationPlatform.Fcm;
break;
default:
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
await hub.CreateOrUpdateInstallationAsync(installation);
return new HttpResponseMessage(HttpStatusCode.OK);
}
public class DeviceInstallation
{
public string installationId { get; set; }
public string platform { get; set; }
public string pushChannel { get; set; }
public string[] tags { get; set; }
}
When I run this code, I get a successful message back. The Azure portal itself does not show much information about the no. of devices registered or active devices information in the Azure notification hub. However, I was able to confirm that the installation exists by making a GET request to the installation API directly through this call:
https://<myNotificationHubNameSpace>.servicebus.windows.net/<myHubName>/installations/<myInstallationId>/?api-version=2015-01
This call returned me a 200 OK with the installation I created from the earlier step. The response looked like this:
{"installationId":"<myInstallationId>","pushChannel":"<DeviceTokenGeneratedByFireBase>","pushChannelExpired":false,"platform":"gcm","expirationTime":"9999-12-31T23:59:59.9999999Z","tags":["notificationhubtag1"]}
So, I went to the Azure Notification Hub and sent a test message from the "Test Send" tab and used the tag "notificationhubtag1" in the SendTo tags field. I got back the successful message that said "The Notification was successfully sent to the Push Notification System" and also got the Registration number.
However, I don't see any notifications being sent to the app itself. How can I debug more information about this specific message being pushed. Where did it get pushed?
Is there any way to find more information on the pushed messages, installed devices etc on the notification hub itself? I found an old post about checking logs which said to switch to standard tier instead of free Tier for more information. I have made the switch to standard tier but I don't see any difference in the way overview or activity logs is displayed to me between Free or Standard Tier.
Notification Hubs acts as a bit of a proxy. So the message you saw in the Portal when performing the test send means it did successfully hand off the notification to FCM to be sent and got a success response back from FCM. This also means the device token was valid.
At that point there is no additional data Notification Hubs can provide since it is no longer in the system.
When we've seen issues like this in the past it tends to imply there is something not quite right in the app configuration itself. Likely there is some logic missing for handling the notification intent.
From the code snippet above, it looks like you are creating the installation from some server side piece and not from the application. My assumption is this means you are still working on integrating the Android SDK for Notification Hubs, since the normal flow is to have devices register themselves with the Hub.
We document the full end-to-end steps here: https://learn.microsoft.com/en-us/azure/notification-hubs/notification-hubs-android-push-notification-google-fcm-get-started
I would mostly recommend looking closely at the various code changes necessary on the Android side. Manifest updates and code changes. If you continue to have issues receiving notifications, please feel free to open a support request in the Portal and we can dig deeper into what's going on.
Looking at the docs for the SignalR bindings to send a message to a specified user you include the UserId property on the message as such -
[FunctionName("SendMessage")]
public static Task SendMessage(
[HttpTrigger(AuthorizationLevel.Anonymous, "post")]object message,
[SignalR(HubName = "chat")]IAsyncCollector<SignalRMessage> signalRMessages)
{
return signalRMessages.AddAsync(
new SignalRMessage
{
// the message will only be sent to these user IDs
UserId = "userId1",
Target = "newMessage",
Arguments = new [] { message }
});
}
This example is taken straight from the documentation, but the comment implies you message multiple userids, even though the property is a string and not an array.
How would you specify multiple users? (If for example, they are in a private chat channel together) Or is this mistake in the wording of the comment and you would need to send a message per user?
With other versions of SignalR I would put them in a group, but bindings for this do not exist for functions.
Group operations were introduced in the latest release.
Now you can:
Send a message to a group using GroupName in SignalRMessage
Add/remove user in a group using IAsyncCollector<SignalRGroupAction> output
Unfortunately just like the doc says, right now with Azure function binding we can only send message to one user or to all clients.
See the code of current extension SDK Microsoft.Azure.WebJobs.Extensions.SignalRService v1.0.0-preview1-10002.
It shows the extension has only two methods SendToAll and SendToUser.
Task SendToAll(string hubName, SignalRData data);
Task SendToUser(string hubName, string userId, SignalRData data);
The comment confused you is actually for old sample, the author forgot to modify it.
Good news is that support for group operation is under progress.
I'm using Spring Integration in a project that integrates (successfully) various ReST/JSON and SOAP endpoints.
Now I need to call a BusinessWorks instance that is configured to accept Plain-Old-Xml-over-HTTP.
From the "Spring Integration in Action book", I got a hint that I should use int-ws:outbound-gateway for this.
This configuration generates the correct request, but in SOAP:
<int-ws:outbound-gateway
uri="..."
request-channel="request" reply-channel="reply"
marshaller="marshaller" unmarshaller="unmarshaller"/>
I can't figure out how to configure this to send the object in the payload as POX (no SOAP envelope).
I tried this:
<int-ws:outbound-gateway
uri="..."
request-channel="request" reply-channel="reply"
marshaller="marshaller" unmarshaller="unmarshaller"
message-factory="poxMessageFactory"/>
<bean id="poxMessageFactory"
class="org.springframework.ws.pox.dom.DomPoxMessageFactory"/>
The request seems to switch correctly to XML only but the body of the request is empty (no trace of the object present in the Spring Integration payload).
Can someone tell me what I am doing wrong or how to achieve what I am trying to do?
I think this is an omission in the AbstractWebServiceOutboundGateway:
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
Object payload = this.requestMessage.getPayload();
if (message instanceof SoapMessage) {
this.doWithMessageInternal(message, payload);
AbstractWebServiceOutboundGateway.this.headerMapper
.fromHeadersToRequest(this.requestMessage.getHeaders(), (SoapMessage) message);
if (this.requestCallback != null) {
this.requestCallback.doWithMessage(message);
}
}
}
Pay attention to the if (message instanceof SoapMessage) {.
So, indeed we miss there the fact that message can be different type.
Please, open JIRA bug on the matter.
Meanwhile as a workaround I would suggest you to use WebServiceTemplate directly instead of <int-ws:outbound-gateway> you can call it from the <service-activator> using marshalSendAndReceive() method for interaction.
So I'm using azure mobile services backend to try and make a custom API. However I can't seem to connect to even the template table from the client. When you make a new Azure Mobile Service using the template they provide you with this values API controller that resembles this format
[MobileAppController]
public class ValuesController : ApiController
{
// GET api/values
[Route("api/values")]
public string Get()
{
return "test";
}
}
From the client I'm trying to invoke this endpoint like this
var result = mobileService.InvokeApiAsync<string>("values", HttpMethod.Get, null).Result;
And for some reason I keep getting this exception
{"The request could not be completed. (Bad Request)"}
{Method: GET, RequestUri: 'http://localhost:58457/api/values', Version: 1.1, Content: <null>, Headers:
{
X-ZUMO-FEATURES: AT
X-ZUMO-INSTALLATION-ID: b04f4e19-4f41-46ed-9767-9c1352037559
Accept: application/json
User-Agent: ZUMO/1.3
User-Agent: (lang=Managed; os=Windows; os_version=6.1.65536.7601; arch=Win32NT; version=1.3.30324.0)
X-ZUMO-VERSION: ZUMO/1.3 (lang=Managed; os=Windows; os_version=6.1.65536.7601; arch=Win32NT; version=1.3.30324.0)
}}
This is only the template too, so I need this to work before I get any of my custom endpoints up and running. Any ideas on what the issue may be?
You can opt out of version checking by setting a value of true for the app setting MS_SkipVersionCheck. Specify this either in your web.config or in the Application Settings section of the Azure Portal.
ms_skipversioncheck to true in the portal.
You say Mobile Service, but the controller you're using is MobileAppController.
This indicates you're actually using Mobile App. If you look in your server project packages.config, you may see something like this.
<package id="Microsoft.Azure.Mobile.Server" version="1.0.119.0" targetFramework="net45" />
I suspect that the 400 you are getting is because you're using a Mobile Client version less than 2.0.0.
In your client project package config, try using a newer client version, such as:
<package id="Microsoft.Azure.Mobile.Client" version="2.0.1" targetFramework="win81" />
You should also inspect the body of the 400 response to get an explicit error message. I expect it to say something like:
{"message":"No API version was specified in the request, this request needs to specify a ZUMO-API-VERSION of '2.0.0'. For more information and supported clients see: http://go.microsoft.com/fwlink/?LinkId=690568#2.0.0"}
I have gone through the below link
https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-client-and-server-versioning
which actually says both Mobile Apps client and server SDKs are originally based on those in Mobile Services, but they are not compatible with each other. That is, you must use a Mobile Apps client SDK with a Mobile Apps server SDK and similarly for Mobile Services. This contract is enforced through a special header value used by the client and server SDKs, ZUMO-API-VERSION.
So, you must add Headers in the request
HEADERS: ZUMO-API-VERSION: 2.0.0
Or
http://localhost/api/values/get?ZUMO-API-VERSION=2.0.0
Or
You can opt out of version checking by setting a value of true for the app setting MS_SkipVersionCheck, specify this in your web.config under
Actually even if you specify what version of client you are using in your package.config you will still get the same error of Bad Request. No Zumo version specified. You must pass into your InvokeApiAsync method a parameter specifying the version. For example:
var arguments = new Dictionary<string, string>
{
{"ZUMO-API-VERSION", "2.0.0" }
};
var result = MobileService.InvokeApiAsync<string>("CONTROLLERSNAME", "HttpMethod.Get", arguements).Result;
and bingo it will work.
I'm trying to get a registration on the Azure Notification Hub working from html/javascript code running in a web view host (Phonegap / Intel XDK). There is no client library available, so I try to use the REST API (documentation: ).
I have the following Javascript code:
function registerWithAzureNotificationHub()
{
var sas = "Endpoint=sb://eventpusher-ns.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=69XuYoluyBKl6JkkN03Z1oNC7cFSZ4Ku0ZWmPuWoJzs=";
var data = '<?xml version="1.0" encoding="utf-8"?>\
<entry xmlns="http://www.w3.org/2005/Atom">\
<content type="application/xml">\
<MpnsRegistrationDescription xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">\
<Tags>myTag, myOtherTag</Tags>\
<ChannelUri>https://eventpusher-ns.servicebus.windows.net/eventpusher</ChannelUri>\
</MpnsRegistrationDescription>\
</content>\
</entry>';
if (AppMobi.iswp8) {
window.alert("IS WP8");
}
else
{
window.alert("IS NOT WP8");
}
$.ajax({
type:"POST",
url: "https://eventpusher-ns.servicebus.windows.net/EVENTPUSHER/registrations/?api-version=2013-08",
contentType: "application/atom+xml;type=entry;charset=utf-8",
headers: {
"Authorization": sas,
"x-ms-version": "2013-08"
},
dataType: "xml",
data: data,
success: function(d) { window.alert("SUCCESS!"); },
error: function(msg) { window.alert("FAILURE:" + JSON.stringify(msg)); }
});
window.alert("SENT!");
}
In the above case I use the Intel XDK with the code running on a WP8 device, so I register for MPNS (Microsoft Push Notification Service).
The above code fails, and returns without descriptive information about the cause of the error.
Questions:
Is it possible to register a mobile device for Azure Notification Hub from javascript code using REST services?
What could be wrong with the above code? Is the ChannelUri the correct Uri?
It is definitely possible top use the REST interface from javascript.
In your code there are two main problems:
in the ChannelURI you should put the channelURI retrieved from the WindowsPhone HttpPushNotificationChannel (as in this tutorial).
the authorization header is a token that is created for your specific request. As described here
A sample using WinJS is available. We will work on having a PhoneGap specific sample very soon!
I did post a server side snippet to register the device with token to the hub and to be able to send out the notification here :
How to register devices to Azure Notification Hub from server side(with NodeJS sdk) ?
I also have the client side code using ngCordova and PushPlugin in Ionic, let me know if anyone wants to see it.