Azure Push Notification Error from IOS Xcode - ios

I feel I am the first one in the universe trying to get iOS swift working with Azure, not much help out there.
I followed this Create an iOS app
and then Add Push Notifications to your iOS App. I am supposed to be able to do a successful push notification from iPhone, but I get this error. btw: I can get my C# code to trigger in visual studio in my pc (using this tutorial), so the request seems to be working, but the response sucks. Any one knows how to fix it!!
Error registering for notifications: Optional("Error Domain=com.Microsoft.MicrosoftAzureMobile.ErrorDomain Code=-1302 \"{\"message\":\"An error has occurred.\"}\" UserInfo={com.Microsoft.MicrosoftAzureMobile.ErrorRequestKey=<NSMutableURLRequest: 0x14cebf780> { URL: http://<mysite>.azurewebsites.net/push/installations/1E32E9B5-E976-4CCD-BD61-D026D3F4FF1C }, com.Microsoft.MicrosoftAzureMobile.ErrorResponseKey=<NSHTTPURLResponse: 0x14cec54b0> { URL: http://<mysite>.azurewebsites.net/push/installations/1E32E9B5-E976-4CCD-BD61-D026D3F4FF1C } { status code: 500, headers {\n \"Content-Length\" = 36;\n \"Content-Type\" = \"application/json; charset=utf-8\";\n Date = \"Wed, 11 May 2016 21:39:39 GMT\";\n Server = \"Microsoft-IIS/8.0\";\n \"Set-Cookie\" = \"ARRAffinity=8d79cd782ff16b44f7f280b76e2bc5564d86e0d1b228227b8e0033f4bb1c4582;Path=/;Domain=<mysite>.azurewebsites.net\";\n \"X-Powered-By\" = \"ASP.NET\";\n} }, NSLocalizedDescription={\"message\":\"An error has occurred.\"}}")
UPDATE #1
The only url I have is the one per the tutorial. The rest of the code is identical to the ones I mentioned in the links (I copied it character by character):
class ClientManager {
static let sharedClient = MSClient(applicationURLString: "http://<mysite>.azurewebsites.net")
}
UPDATE #2
#Pau Senabre I am working with swift not Objective-C per my question (see my tags under question), so I don't have an .m file per your step #1. I also don't have the logErrorIfNotNil you mentioned. My method (which is generated by Azure before modifications) looks like this:
#IBAction func addItem(sender : AnyObject) {
self.performSegueWithIdentifier("addItem", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!)
{
if segue.identifier == "addItem" {
let todoController = segue.destinationViewController as! ToDoItemViewController
todoController.delegate = self
}
}
UPDATE #3
#Pau Senabre My goal is to do mobile apps/services, not mobile engagement. See the difference here. btw: I had followed the azure engagement example when I started playing with it and had worked for me. But my need now is web/mobile apps. So, does what you suggested still apply for my need?

Could you please post some code? I think you may be using a wrong URL in a certain place.

To UPDATE #2
Check the following link:
https://github.com/Azure/azure-content/blob/master/articles/mobile-engagement/mobile-engagement-ios-swift-get-started.md
In section Modify your Application Delegate make sure you create a reach module and your existing Engagement initialization has all the init Values.
EngagementAgent.init("Endpoint={YOUR_APP_COLLECTION.DOMAIN};SdkKey={YOUR_SDK_KEY};AppId={YOUR_APPID}", modulesArray:[reach])
The error Code provided Error Domain=com.Microsoft.MicrosoftAzureMobile.ErrorDomain Code=-1302 matches to a bad request. If you are entering some data, make beforehand a Data Input Validation:
1 In the TodoService.m file, locate the addItem method search for the [self logErrorIfNotNil:error]; line of code. Beneath that line of code, replace the remainder of the completion block with the following code that checks to see if there was an error in the request and if that error code was –1302, indicating a bad request:
BOOL badRequest = ((error) && (error.code == -1302));
// detect text validation error from service.
if (!badRequest) // The service responded appropriately
{
NSUInteger index = [itemscount];
[(NSMutableArray *)itemsinsertObject:result atIndex:index];
// Let the caller know that we finished
completion(index);
}
2 Build and run; you can see in the Xcode output window that the bad request error from the service was handled:
2012-10-23 22:01:32.169 Quickstart[5932:11303] ERROR Error Domain=com.Microsoft.WindowsAzureMobileServices.ErrorDomain Code=-1302 “Text length must be under 10″ UserInfo=0x7193850 {NSLocalizedDescription=Text length must be under 10, com.Microsoft.WindowsAzureMobileServices.ErrorResponseKey=, com.Microsoft.WindowsAzureMobileServices.ErrorRequestKey=https://task.azure-mobile.net/tables/TodoItem>}
3 Finally, in the TodoService.m file, locate the logErrorIfNotNil method, which handles the logging of errors to the output window. Inside the if code block, just below the line NSLog(#”ERROR %#”, error); add the following if block:
// added to display description of bad request
if (error.code == -1302){
UIAlertView *av =
[[UIAlertView alloc]
initWithTitle:#”Request Failed”
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#”OK”
otherButtonTitles:nil
];
[av show];
}
Aditionally, review the following steps in the Azure Setup, maybe you are missing something at some point:
https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-ios-get-started-push/
1 Create a Notification Hub
This creates a new notification hub and connects it to your mobile app. If you have an existing notification hub, you can choose to connect it to your Mobile App backend instead of creating a new one.
2 Register app for push notifications
Register an App ID for your app. Create an explicit App ID (not a wildcard App ID) and for Bundle ID, use the exact Bundle ID that is in your Xcode quickstart project. It is also crucial that you check the Push Notifications option.
Next, configuring push notifications. You may create either a "Development" or "Distribution" SSL certificate (remember to select the corresponding option in the Azure portal later.)
3 Configure Azure to send push notifications
In the Azure portal, click Browse All > App Services > your Mobile App backend > Settings > Mobile > Push > Apple Push Notification Services > Upload Certificate. Upload the .p12 file, selecting the correct Mode (corresponding to whether the client SSL certificate you generated earlier was Development or Distribution.)
4 Update server project to send push notifications
Replace the PostTodoItem method with the following code:
public async Task<IHttpActionResult> PostTodoItem(TodoItem item)
{
TodoItem current = await InsertAsync(item);
// Get the settings for the server project.
HttpConfiguration config = this.Configuration;
MobileAppSettingsDictionary settings =
this.Configuration.GetMobileAppSettingsProvider().GetMobileAppSettings();
// Get the Notification Hubs credentials for the Mobile App.
string notificationHubName = settings.NotificationHubName;
string notificationHubConnection = settings
.Connections[MobileAppSettingsKeys.NotificationHubConnectionString].ConnectionString;
// Create a new Notification Hub client.
NotificationHubClient hub = NotificationHubClient
.CreateClientFromConnectionString(notificationHubConnection, notificationHubName);
// iOS payload
var appleNotificationPayload = "{\"aps\":{\"alert\":\"" + item.Text + "\"}}";
try
{
// Send the push notification and log the results.
var result = await hub.SendAppleNativeNotificationAsync(appleNotificationPayload);
// Write the success result to the logs.
config.Services.GetTraceWriter().Info(result.State.ToString());
}
catch (System.Exception ex)
{
// Write the failure result to the logs.
config.Services.GetTraceWriter()
.Error(ex.Message, null, "Push.SendAsync Error");
}
return CreatedAtRoute("Tables", new { id = current.Id }, current);
}

this is the proper answer from another question I had earlier, which fixes both: Registration and Receiving push notifications. I said this in here:
I finally have been able to receive notifications last night. I went ahead and redid an entire walk-through of all apple-side installation steps using this tutorial: Sending push notifications to iOS with Azure Notification Hubs then the azure-side of things using this: Create an iOS app and Add Push Notifications to your iOS App. That took care of the registering the app of the device successfully, which I was able to verify using the note of AdrianHall in this thread. But that wasn't enough. The Azure tutorials fell short detailing the steps needed in Xcode, which I found here: [How To] Setup Remote Push Notification in iOS - Swift 2.0 Code I didn't have to setup any "push notification" in Xcode or anything like that.
I hope this detailed answer will save you many hours of digging through.

Related

How to send push certificate to APNS while calling their APIs?

Have been stuck for sending push notification using apns push certificate from my server app (Spring Boot Application). Apple discussed here on an overview of how we can send push with certificate but there is no technical detail about TLS communication (specially, on how I can send my push certificate to APNS and proceed API calls).
Anyone have any reference or article?
Since you mentioned your working on a Spring Boot application I'm assuming you're using Java and Maven.
Our back ends are also written in Java and I recently updated our push notification code by implementing Pushy. It's much much easier to use a library that's battle tested and regularly updated than to write your own. I use pushy to send around 100k push notifications a day on a fairly weak server and have never had any issues with it.
It was fairly simple to implement. Their README is very useful but the summary is add pushy as a dependency in your pom.xml file:
<dependency>
<groupId>com.eatthepath</groupId>
<artifactId>pushy</artifactId>
<version>0.13.11</version>
</dependency>
Here's a simple example for your use-case using stolen code from the README, I did add the comment though:
// Add these lines as class properties
// This creates the object that handles the sending of the push notifications.
// Use ApnsClientBuilder.PRODUCTION_APNS_HOST to send pushes to App Store apps
final ApnsClient apnsClient = new ApnsClientBuilder()
.setApnsServer(ApnsClientBuilder.DEVELOPMENT_APNS_HOST)
.setClientCredentials(new File("/path/to/certificate.p12"), "p12-file-password")
.build();
// The push notification
final SimpleApnsPushNotification pushNotification;
// In some method:
// Creating the object that builds the APNs payload
final ApnsPayloadBuilder payloadBuilder = new ApnsPayloadBuilder();
// setting the text of the push
payloadBuilder.setAlertBody("Example!");
// Builds the anps payload for the push notification
final String payload = payloadBuilder.build();
// The push token of the device you're sending the push to
final String token = TokenUtil.sanitizeTokenString("<efc7492 bdbd8209>");
// Creating the push notification object using the push token, your app's bundle ID, and the APNs payload
pushNotification = new SimpleApnsPushNotification(token, "com.example.myApp", payload);
try {
// Asking the APNs client to send the notification
// and creating the future that will return the status
// of the push after it's sent.
// (It's a long line, sorry)
final PushNotificationFuture<SimpleApnsPushNotification, PushNotificationResponse<SimpleApnsPushNotification>> sendNotificationFuture = apnsClient.sendNotification(pushNotification);
// getting the response from APNs
final PushNotificationResponse<SimpleApnsPushNotification> pushNotificationResponse = sendNotificationFuture.get();
if (pushNotificationResponse.isAccepted()) {
System.out.println("Push notification accepted by APNs gateway.");
} else {
System.out.println("Notification rejected by the APNs gateway: " +
pushNotificationResponse.getRejectionReason());
if (pushNotificationResponse.getTokenInvalidationTimestamp() != null) {
System.out.println("\t…and the token is invalid as of " +
pushNotificationResponse.getTokenInvalidationTimestamp());
}
}
} catch (final ExecutionException e) {
System.err.println("Failed to send push notification.");
e.printStackTrace();
}

Authentication for OneSignal to send automatic notifications to a segment using Firebase in Swift 3

I recently started using OneSignal to send notifications on my firebase based iOS project.
While I can send notifications to specific user and an array of users fine, I can't find documentation on how to set up OneSignal authentication with Firebase so that I can target a specific segment of users automatically through the app.
The code that I am using to send notifications to an array of users (working fine):
//to remove the current user ("playerID") from receiving notification
let indexToDelete = playerIDArray.index(of: playerID)
playerIDArray.remove(at: indexToDelete!)
var count = 0
while count < playerIDArray.count {
OneSignal.postNotification(["contents" : ["en" : "\(usersID!) has sent a message"], "include_player_ids" : ["\(playerIDArray[count])"]])
count = count+1
}
However, when I try to send the notification to a segments, like so:
OneSignal.postNotification(["contents" : ["en" : "\(usersID!) has sent a message"], "included_segments" : ["All"]])
I get this error:
2017-03-09 02:35:30.989 MyApp[3658:87978] ERROR: Create notification failed
I know that I am getting this error due to authorization issues, so I was wondering if anyone knows how to set up this authorization using Firebase?
Thanks so much!
you are actually getting this error because you cannot use "included_segments" as a targeting parameter from you app.
You can only use "include_player_ids".
Documentation here:
https://documentation.onesignal.com/docs/ios-native-sdk#section--postnotification-
If you would like to target segments of users, you may do so from your dashboard:
https://documentation.onesignal.com/docs/sending-notifications#section-selecting-users
or from the OneSignal REST API:
https://documentation.onesignal.com/v3.0/reference#section-send-to-segments

Notification Hub Devices disappearing after Push (APNS)

We have an Azure Notification Hub set up, with APNS Configured in Production Mode, using our Production APNS Certificate.
We register our test devices (using TestFlight / Production build, and certificate) to APNS, and then to ANH with a tag dealer-1. We can send notifications using our production certificate and registered Device ID with success when using APNS directly, however, when we use 'Test Send' we get a 'Successful send' to 1 device (or however many we have registered). The notification is not received. If we then run 'Test Send' again, the are 0 devices to send to.
In the logs, we see 'APNS Errors' per device, per test send. I cannot see any way to view what the errors actually are though so this is an absolutely useless metric.
I have ran through all the troubleshooting steps and confirmed many times that everything is setup in 'Production'.
Having reviewed other questions, the answers have been along the lines of:
.. registering a sandbox certificate and then changing it to production. Unfortunately we created this hub from scratch as Production in an attempt to work around that potential issue.
.. registering sandbox devices (and thus tokens) against the production certificate. Unfortunately I have controlled this closely and ensured that we are only registering TestFlight builds (thus Production) against the ANH.
.. uploading the wrong certificate. I have confirmed with the Push Notification Tester, as above, that the certificate is correct (thumbprint confirmed, re-uploaded, etc) and works to send to the devices via Production APNS endpoint.
The resource name is: eight-technology/react-push-notification-hub
In-app registration process is as follows:
Device registers for push notifications
Registration event is handled in iOS Project (AppDelegate event)..
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
//base.RegisteredForRemoteNotifications(application, deviceToken);
App.ConfigurePushNotifications(deviceToken.ToString());
}
ConfigurePushNotifications is in the XF Shared Project..
public static void ConfigurePushNotifications(string deviceToken)
{
var azureComm = DependencyService.Get<Interop.IAzureCommunication>();
azureComm.RegisterForPushTags(
"sb://eight-technology.servicebus.windows.net/",
".. token ..",
"react-push-notification-hub",
deviceToken,
StateManager.SelectedNodes.Select(m => "dealer-" + m).ToArray());
}
The implementation is pretty much as per the sample code provided (contained in iOS project)
public class AzureCommunication : DealerwebReact.Interop.IAzureCommunication
{
public void RegisterForPushTags(string url, string key, string hubName, string deviceToken, string[] tags)
{
var cs = SBConnectionString.CreateListenAccess(new NSUrl(url), key);
var hub = new SBNotificationHub(cs, hubName);
hub.RegisterNativeAsync(deviceToken, new NSSet(tags), err =>
{
if (err != null)
Console.WriteLine("Error: " + err.Description);
else
Console.WriteLine("Success");
});
}
}
After a frustrating few days, and thanks to the help of Nikita G. and hvaughan3 I finally got to the root cause of my issue. As anticipated it wasn't any of the issues actually outlined, but was to do with the way we handled the cross-plat aspect of the registrations with Xamarin Forms.
That is, we stored our token in a class as a string. The NSData that is received as part of the iOS Device registration in RegisteredForRemoteNotifications has a ToString() method that is incompatible with sending to ANH. Furthermore, RegisterNativeAsync method from the Azure library requires an NSData which I assume Xamarin can morph a string into without warning or error, hence it was unknown that the two were somewhat incompatible.
Basically, to maintain cross platform functionality, we are now simply passing the token around as an object and performing the translation back to the original type in the platform-specific implementation of our push configuration method.
Our registration method now looks like this, note the explicit use of the NSData type so that it remains untouched whilst passing through the Xamarin Forms layer:
public void RegisterForPushTags(string url, string key, string hubName, object deviceToken, string[] tags)
{
var cs = SBConnectionString.CreateListenAccess(new NSUrl(url), key);
var hub = new SBNotificationHub(cs, hubName);
hub.RegisterNativeAsync((NSData)deviceToken, new NSSet(tags), err =>
{
if (err != null)
Console.WriteLine("Error: " + err.Description);
else
Console.WriteLine("Success");
});
}
Is this the guide you used for troubleshooting?
Is there a chance you somehow do any string (or any other type of) processing on the APN handle before you register your device? The 'APNS errors' you're seeing seem to be 'invalid token size'. Since I don't know what's going on in your code, it's hard to suggest what exactly might it be, but maybe would help you.
A similar thing happened to me when the device would register correctly but as soon as a notification was sent, the devices would disappear from the list. It always turned out to be an issue with the APNS certificate that was configured within the Notification Hub was not connected properly to the App ID and/or the app was not being signed with the correct provisioning profile.

Azure Notification Hub: notifications not showing up if sent to group

I have a trouble making notification hub to work.
If I send notification to tag that has only one registration associated with it, then everything's fine. Here's source:
var alert = "{\"aps\":{\"alert\":\"some message(targeted)\"},\"inAppMessage\": \"text\"}";
hub.SendAppleNativeNotificationAsync(alert,"mytag").ContinueWith(t => {
var outcome = t.Result;
Console.WriteLine(outcome);
});
But if I try to sent my notification to all users, like so:
var alert = "{\"aps\":{\"alert\":\"some message(all users)\"},\"inAppMessage\": \"text\"}";
hub.SendAppleNativeNotificationAsync(alert).ContinueWith(t => {
var outcome = t.Result;
Console.WriteLine(outcome);
});
then no one gets the notification. I checked monitor in Azure portal but there were no errors present.
Do you guys have some ideas?
Behavior you described is incorrect. There is one known issue which can potentially cause such kind of errors for Apple only:
If some registrations in the Notification Hub have invalid device token (it typically happens when application switches from test APNS to production or if some fake tokens were used during testing in emulator) then APNS terminates connection during the send and all notifications being sent after that using same connection are just ignored. Right now Notification Hub does not handle this situation correctly.
Way to fix - clean up "bad" registrations. If you are about developing/testing and it is not critical to lose the data - just remove all the registrations. If you have a lot of existing users then email me and we will try to find solution for your particular case.
I had same issue and I tried to set true EnableTestSend property, but no luck. Then I just removed the tags while send notifications. It worked like charm.
NotificationOutcome outcome = null;
var alert = "{\"aps\":{\"alert\":\"" + "From " + user + ": " + message + "\",\"sound\":\"default\"}}";
outcome = await Notifications.Instance.Hub.SendAppleNativeNotificationAsync(alert);

How to get key/value data from PushNotification in PhoneGap Build

I'm using the Push plugin in PhoneGap Build. I am able to send as well as receive push notifications to my device. I'm sending the notification + additional data (specifically which page to load) using the node-gcm library to registered devices. Here's the code on my node.js server:
var gcm = require('node-gcm');
var message = new gcm.Message();
//API Server Key
var sender = new gcm.Sender('GCM API SERVER/BROWSER KEY');
var registrationIds = [];
// Value the payload data to send...
message.addData('message','Hello from Portland, OR!');
message.addData('title','My Push Notification');
message.addData('msgcnt','3');
message.addData('soundname','beep.wav');
message.addDataWithKeyValue('pageid','1234566788'); //THIS IS THE ADDITIONAL DATA I'D
// ... ID LIKE TO SEND TO MY PHONEGAP BUILD APP AND INTERPRET
message.timeToLive = 3;// Duration in seconds to hold and retry to deliver the message in GCM before timing out. Default 4 weeks if not specified
// At least one reg id required
registrationIds.push('REGISTRATION ID');
/**
* Parameters: message-literal, registrationIds-array, No. of retries, callback-function
*/
sender.send(message, registrationIds, 4, function (result) {
console.log("hello" + result);
});
Now that I believe I have sent the additional page data, I'd like to know how I can GET the data from the notification itself inside of my PhoneGap build application.
I'm also using jquery mobile to manage the different html pages (which basically makes each page a separate div inside of one html document) and could use feedback on how to load the notified page with this in mind.
Any help would be greatly appreciated, thanks so much!
-- 24x7
You can get the value of key/pairs of notification in phonegap as follows:
The message text can be retrieved with: e.message
All other key/value pairs can be retrieved with: e.payload.key
For example if you want get the title of the notification(in above) then you will get it in "e.payload.title".
After getting the value you can put conditional statemnets depending upon the value to go to different pages/divs.

Resources