OneSignal postNotification Failed - ios

I am trying to post a notification to all registered users with OneSignal.
I have a couple of users registered to test with and have successfully sent a notification form the OneSignal website dashboard.
However, when I try the following code, I get the following errors:
[OneSignal postNotification:#{
#"contents" : #{ #"en" : #"Test Message" },
#"object" : #{ #"en" : #"Test Title" },
#"app_id" : #"MY_SECRET_APP_ID",
}
onSuccess:^(NSDictionary *result) {
}
onFailure:^(NSError *error) {
NSLog(#"%#", error.localizedDescription);
}];
Error:
Create notification failed and The operation couldn’t be completed. (OneSignalError error 400.)

You must use a targeting parameter, only include_player_ids may be used from your app. All other targeting parameters such as tags or segments must be used from your server through the OneSignal create notification REST API POST call. You can get the current OneSignal user / player id by calling IdsAvailable.
To send a notification to all users from your server you will need to add the following to your JSON
"included_segments": ["All"],
Also note, object isn't a valid key so it will be ignored. I believe you are looking for headings based on the value you have.

Related

Azure Push Notification Error from IOS Xcode

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.

How to get token_for_business for Facebook login - iOS

How can I get token_for_business from Facebook login? I have setup a business and associated my application with that business. Facebook documentation says you need to call GET /me?fields=token_for_business on User node, and it will return following json.
{
"id": "1234567890"
"token_for_business": "weg23ro87gfewblwjef"
}
I tried by providing token_for_business in parameter list of /me call but didn't work. Need advises.
Edit
I found this URL https://developers.facebook.com/docs/graph-api/reference/v2.5/user and tried by passing token_for_business in param of initWithGraphPath but no gain. I checked in Graph API Explorer and getting the required data. But not sure how to call from my objective-C code.
Edit 2
I Inspected the error object of initWithGraphPath:#"me?fields=token_for_business" call and found following details
Error Domain=com.facebook.sdk.core Code=8 "(null)" UserInfo={com.facebook.sdk:FBSDKGraphRequestErrorCategoryKey=0, com.facebook.sdk:FBSDKGraphRequestErrorHTTPStatusCodeKey=403, com.facebook.sdk:FBSDKErrorDeveloperMessageKey=(#200) Application must be associated with a business. https://business.facebook.com/, com.facebook.sdk:FBSDKGraphRequestErrorGraphErrorCode=200, com.facebook.sdk:FBSDKGraphRequestErrorParsedJSONResponseKey={
body = {
error = {
code = 200;
"fbtrace_id" = "EN9bN/YMloA";
message = "(#200) Application must be associated with a business. https://business.facebook.com/";
type = OAuthException;
};
};
code = 403;
}}
But if I try my app in Graph API Explorer then I'm getting the required data. So now it confusing me.

requestAccessToAccountsWithType return error code 7

I'm using [ACAccountStore requestAccessToAccountsWithType] to get Facebook users info for users had logged in iOs Facebook settings. It still work fine until last week, now it always return error code 7.
Error Domain=com.apple.accounts Code=7 "The Facebook server could not fulfill this access request: remote_app_id does not match stored id (404)" UserInfo=0x7fef59d8a760 {NSLocalizedDescription=The Facebook server could not fulfill this access request: remote_app_id does not match stored id (404)}
I do not know why this happen, and we not changing anything in our settings in developers.facebook.com.
This is my code line.
NSDictionary *options = #{
ACFacebookAppIdKey : [[NSBundle mainBundle] objectForInfoDictionaryKey:#"FacebookAppID"],
ACFacebookPermissionsKey : #[#"email"],
ACFacebookAudienceKey: ACFacebookAudienceFriends
};
ACAccountType *FBaccountType= [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
[self.accountStore requestAccessToAccountsWithType:FBaccountType options:options completion:
^(BOOL granted, NSError *error) {
if (granted) {
} else {
// it always return not granted.
}
}
}];
I don't know why it is happening now.
I have check something from this iOS 6 Facebook posting procedure ends up with "remote_app_id does not match stored id" and this Getting error ACErrorPermissionDenied (error code 7) for Facebook when using Social Framework but not found any luck.
The issue is either of the follows:
there is mismatch between the app_id entered in your xcode project and the app_id you have in developers.facebook.com. Make sure you have setup the plist file properly as pointed out in the Facebook documentation. https://developers.facebook.com/docs/ios/getting-started/#configure
Create a key called FacebookAppID with a string value, and add the app ID there.
Create a key called FacebookDisplayName with a string value, and add the Display Name you configured in the App Dashboard.
Create an array key called URL types with a single array sub-item called URL Schemes. Give this a single item with your app ID prefixed with fb.
If your app_id matches properly, make sure to enter the app store ID in your settings at developers.facebook.com.

Subscribing email address to MailChimp from iOS app

I have added a contact form to my app that allows users to send feedback to me directly via email. I'm using Mandrill and Parse, and it works well!
On the contact form is an "Add me to mailing list…" option, and I'm looking for a way to add the user's email to MailChimp automatically if this option is checked.
I understand that there's a MailChimp API that's accessible by Objective C through a wrapper, though I'm wondering if there's not a more straightforward way to simply add an email to a MailChimp mailing list in iOS/Objective C?
Thanks for reading.
EDIT #1: Progress, but not yet success.
1) I've added cloud code from this answer to Parse (substituting in the two keys, where KEY2 is last three characters of MailChimp key):
var mailchimpApiKey = "MY_MAILCHIMP_KEY";
Parse.Cloud.define("subscribeUserToMailingList", function(request, response) {
if (!request.params ||
!request.params.email){
response.error("Must supply email address, firstname and lastname to Mailchimp signup");
return;
}
var mailchimpData = {
apikey : mailchimpApiKey,
id : request.params.listid,
email : {
email : request.params.email
},
merge_vars : request.params.mergevars
}
var url = "https://KEY2.api.mailchimp.com/2.0/lists/subscribe.json";
Parse.Cloud.httpRequest({
method: 'POST',
url: url,
body: JSON.stringify(mailchimpData),
success: function(httpResponse) {
console.log(httpResponse.text);
response.success("Successfully subscribed");
},
error: function(httpResponse) {
console.error('Request failed with response code ' + httpResponse.status);
console.error(httpResponse.text);
response.error('Mailchimp subscribe failed with response code ' + httpResponse.status);
}
});
});
2) And I've added this Objective-C code to my iOS project (adding in my MailChimp list ID):
[PFCloud callFunctionInBackground:#"subscribeUserToMailingList" withParameters:#{#"listid":#"MY_LIST_ID",#"email":userEmail,#"mergevars":#{#"FNAME":firstName,#"LNAME":lastName}}
block:^(NSString *result, NSError *error){
if (error) {
//error
} else {
}
}];
The result? This error:
Error Domain=Parse Code=141 "The operation couldn’t be completed. (Parse error 141.)" … {error=Mailchimp subscribe failed with response code 500, code=141}
EDIT #2: More progress, but not yet success.
The previous error was being caused by an attempt to add an email address to the mailing list that was already there. I am now getting no errors and a "Successfully subscribed" result in the block above. However, logging in to MailChimp, the new address is still not there.
OK, turns out the code is fine! Please use, share, and enjoy.
The issue was that MailChimp (smartly) requires double opt-in for mailing lists.
The first opt-in is running this code with a specific userEmail, and it results in an email being sent to your to-be-added user.
The email asks them to confirm their subscription, and if they do so (it's a link in the email), that's the second opt-in. Then, their email is added to your list.
So, bottom line is that the code doesn't automatically add a user to your mailing list—their confirmation is still required. It's a nice way to make sure people on your mailing list actually want to be there (i.e., have a chance of reading your emails)!

Is there a way to send user-specific push notifications for iOS devices?

I would like to know if I can create a service to send customized user-specific push notifications for iOS.
Example
#"Hey %#, how you doin", firstName"
Is this possible?
Unless I completely misunderstood what you need, no answer has what you need.
Here's a relevant example from the APNS guide :
let’s consider an example. The provider specifies the following dictionary as the value of the alert property:
{ "aps" :
{
"alert" : {
"loc-key" : "GAME_PLAY_REQUEST_FORMAT",
"loc-args" : [ "Jenna", "Frank"]
}
}
}
When the device receives the notification, it uses "GAME_PLAY_REQUEST_FORMAT" as a key to look up the associated string value in the Localizable.strings file in the .lproj directory for the current language. Assuming the current localization has an Localizable.strings entry such as this:
"GAME_PLAY_REQUEST_FORMAT" = "%# and %# have invited you to play Monopoly";
the device displays an alert with the message “Jenna and Frank have invited you to play Monopoly”.
Of course. Check out the APNS programming guide, specifically the payload, which you can customize on your server before you send it to the user's device.
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html
Also note that if you know when the notification should appear (not at a dynamic time) then look into local notifications, which don't require a server backend.
You can use any service for Push Notification (as listed) or do it by yourself.
In your code, when you receive the Push Notification message:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(#"Received notification: %#", userInfo);
//here you should treat your received data
}
There are some very good solutions for iOS push notifications service that use APNS. No need to implement it on your own.
PushApps - free for 1M notifications per month, and unlimited notifications for 19.99 per month, and you can import your users via the API or by sending the a csv file - documentation
Urban Airship - free up to 1M notifications per month, afterwards you are charged per 1000 notifications
Parse - also free for the first 1M notifications
PushWoosh - free for 1M devices, premium plans are from 39 EURO
If you have to implement it on your own, have a look at easyAPNS if you want to host it yourself.
Another good site for info is Ray Wenderlich's site which hosts a 2 part tutorial:
Apple Push Notification Services Tutorial: Part 1/2
Apple Push Notification Services Tutorial: Part 2/2
Or this, Apple Push Notification module for Node.js.
Of course you can...
You need to create your own back-end php file for push notification service, you can send json data from your app to the php file and use $GET to achieve the data you want, including device token, message, badge number... please refer to this
in your viewController
NSString *finalUrl =[NSString stringWithFormat:#"%#/pushService.php?device_token=%#&passphrase=%#&msg=%#",baseURL,device_token,passphrase,msg];
NSURL *url =[NSURL URLWithString:finalUrl];
NSData *jsonData = [NSData dataWithContentsOfURL:url];
if(jsonData != nil)
{
NSError *error = nil;
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
NSLog(#"result: %#", result);
}else
{
NSLog(#"connection error!");
}
pushService.php file
// Put your device token here (without spaces):
$deviceToken = $GET['device_token'];
// Put your private key's passphrase here
$passphrase = $GET['passphrase'];
// Put your alert message here:
$message = $GET['msg'];
$body['aps'] = array(
'alert' => $message,
'sound' => 'default',
'badge' => 5
);

Resources