Swift - register and re-register push notifications - ios

Im trying to find a way to de-authorise users for push notifications when they log out from an app Ive found this function UIApplication.shared.unregisterForRemoteNotifications() which aparently works however I never see notifications being disabled, I also read in the documentation that it should not be used often or something to that effect, I basically want to have a toggle button in my app where the user clicks it one way and gets the standard enable notifications popup and another way to disable notifications on the fly, Im not a native swift developer so any pointers welcome
Also is it possible to attach a callback to this to know if it executes successfully, Im trying the following but get the error Argument passed to call that takes no arguments
UIApplication.shared.unregisterForRemoteNotifications() { (result, error) in
if let error = error {
call.error("Error", error)
} else if let result = result {
call.success([
"deregister": true
])
}
}
Edit: I found this which says its not possible to toggle on and off Change push notifications programmatically in Swift
With that in mind does this mean that the standard for devices is that:
1) when a user log out of their account they can still receive notifications.
2) When a user creates a new account on the same app it uses the same token and so receives notifications from the old account ?
3) when a user sells their phone and another guy/gal downloads the same app that they will receive notifications from that other users account (in terms of 3rd party push service one signal, aparently you dont need to refresh the player id)

Related

Migrating Parse Push to AWS

I am having an issue with Parse Push on AWS. We have the adapter configured per these specifications and can seem to broadcast to one specific user (don't know how or why that user) using the curl method, but I am confused how (or if) I can use this to send user to user push notifications. For example, "X liked Y's Z" Where X is the liker, Y is the liked and Z is the object being liked.
in parse you have multiple options to send push notifications.
Push notifications can be sent to one or more users by providing a query with all the installations that you like to send the push to. You can also send push notifications for specific channel that the user subscribed to, this is very good for marketing or maybe if your app have different type of users (for example: sellers, buyers etc.)
The reason that a push is being sent to installations and not to users is because that one users can have multiple installations (e.g. iphone,ipad,other device etc.)
like i said there are multiple options to send push but i recommend to send a push using one of the following approaches:
From cloud code - you can create cloud code function that will be triggered by the client and this cloud code function will first create a query of all the installations that you need to send the push to and will execute the function that will actually send the push. This cloud code function can receive multiple parameters that can contain any data that needs to be processed before you sending the push, such data can be array of users, channel name and more.
the following cloud code snippets show how to send a push for all users who successfully subscribed and have device token:
Parse.Cloud.afterSave("SendPush", function(request) {
var query = new Parse.Query(Parse.Installation);
query.exists("deviceToken");
var payload = {
alert: "after save push"
};
Parse.Push.send({
data: payload,
where: query
}, {
useMasterKey: true
})
.then(function() {
response.success("Push Sent!");
}, function(error) {
response.error("Error while trying to send push " + error.message);
});
});
and then from your iOS SDK you call this cloud code function in the following way:
NSDictionary * parameters = # {}; // put parameters if required
[PFCloud callFunctionInBackground: #"SendPush"
withParameters: parameters block: ^ (id _Nullable object, NSError * _Nullable error) {
// callback result
}
];
From iOS SDK - if you don't want to send your push from cloud code you can do it directly from your iOS. I think it's better to do it in cloud code because in cloud code you write ones and then you can trigger this function from any SDK and also from the REST API.
In Parse docs you can find a lot of examples on how to send push from iOS SDK all the examples can be found here:
http://parseplatform.github.io/docs/ios/guide/#push-notifications
but like i said the best is to do it with cloud code.
Answer is similar if you're using AWS services without Parse. A better architecture is where the mobile device invokes business logic in the cloud (i.e., in an AWS Lambda function) and that code sends the push notifications. This allows you to build a more secure solution because you can control content and control who can send to whom (i.e., you must be on someone's friend list to send) within your business logic. If you open permissions to publish directly from the device, then you make system vulnerable to attacks where someone uses the app's credentials and publishes harmful content (potentially to all your app's users).
Example of sending push notification from an AWS Lambda function...
Can you send SNS push notification from lambda function in Amazon AWS?

Twilio iOS Video Call: Getting "User is unavailable" error message when user rejects the call

I am implementing twilio's video call in my iOS application. The problem is that I am looking for a way to know when the counterpart application is dead to send him a VoIP Push notification.
The solution I was trying to implement was that, when the call returns "User is unavailable" error then i would tell my backend to send VoIP notification to the counterpart, the problem with this solution is that I found a twilio's bug where sometimes if the user rejects the call twilio's SDK returns a wrong error message saying "User is unavailable" instead an error with "User rejects the call" message. So I can't know if the user was really unavailable (to send the VoiP notification) or if the user just rejected the call
How to reproduce the error?
1. Connect two clients with fixed identity id. For example "identity1" and "identity2"
2. Make a call from "identity1" to "identity2" and rejects it from "identity2". You will receive the correct error message "User rejects the call"
3. Close the app in "identity2" WITHOUT CALLING UNLISTEN, just kill the app.
4. Then start the app again in "identity2" (change the token if you want but let the same identity id).
5. Make a call from "identity1" to "identity2" and rejects it from "identity2". You will receive the wrong error message "User is unavailable" instead "User rejects the call".
Thats the problem is like twilio would not remove the old client's instance if we don't call unlisten. And if I can't difference when user is unavailable or when just rejects the call then I can't send the VoIP push when is really needed.
In order to receive incoming call, you have to call listen API on each launch of the app. It seems you might be killing the app after listen but after relaunch listen was not called on client. So when the remote party makes an outbound call, it is getting TWCErrorCodeConversationParticipantNotAvailable.
Once conversation client starts listening for incoming calls, remote party should receive TWCErrorCodeConversationRejected on reject.
In other words, if A calls B, and B is not listening (i.e. not called listen on client), A will receive “user is unavailable".
The example in Swift:
/* Create an AccessManager - this provides a single place to update your Twilio
Access Token when using multiple Twilio SDKs */
var accessManager = TwilioAccessManager(token:self.accessToken, delegate:self)
// Create a Conversations Client and listen for IncomingInvites
var client = TwilioConversationsClient(accessManager: accessManager, delegate: self)
client!.listen()
// MARK: TwilioConversationsClientDelegate
// Selectively handle IncomingInvites based on the originator
func conversationsClient(conversationsClient: TwilioConversationsClient,
didReceiveInvite invite: TWCIncomingInvite) {
if (invite.from == "ringo") {
invite.reject()
} else {
/* See the "Specify Local Media Constraints when Creating a
Conversation" guide for instructions on constructing LocalMedia */
invite.acceptWithLocalMedia(self.localMedia!) { conversation, error in
self.conversation = conversation
self.conversation!.delegate = self
}
}
}
Please let me know if this helps at all!

How do I use Parse.com's push notification feature for a change in PFObjects?

Can I use Parse.com’s push notification feature to send an array of PFObjects to the user when either a new one is added, or an existing one is deleted?? If so, how should I go about it? I’m writing an app for iOS. Any help would be much appreciated.
Edit:
After doing a bit of searching, I see I have to use the cloud code aftersave() method, and then send a push notification through JavaScript.
If anyone could provide examples of how to go about it, that would be great. In the meantime I'm going through the docs. Thanks again all.
The Parse Documentation really contains everything you need to get started. Writing the code that sends the actual notification is only a small part of the whole process that is required to send push notifications. Here are the steps required:
Create an SSL Certificate: create the cert via Apple Developer Center then export it with Keychain Application
Create Provisioning Profile: also done via Apple Dev Center.
Configure Parse App: Change Parse settings, then upload the cert you created in step 1.
Configure App in Xcode: Change app to use provisioning profile you created in step 2.
Add Code to Prompt user for Notifications: write the code in your app that asks a user if they want to receive Push notifications, then store their device ID in Parse Installation class.
Send the Notification: as mentioned earlier this is the easiest step of all. It can be done via the Parse Dashboard (Click on Push notifications when looking at the Data Browser), via the Parse API or via Cloud-code. I did it via Cloud-Code and it looks like this:
// Find the Installation (i.e. iOS Device) that belongs to my user*
var query = new Parse.Query(Parse.Installation);
query.equalTo('user', user);
Parse.Push.send({
where: query, // Set our Installation query
data: {
alert: "This is the notification message",
badge: "Increment"
}
}).then( function(){
console.log("Push notification successfully sent!");
});
*I added a field in my installation class that captures a user. That way I know which device belongs to which user and can send targeted Push Notifications.
Prepare for Release: When you release your app, you will need to do some additional configuration to get everything ready to release.
Again, I recommend the Parse Docs. They are comprehensive and very helpful. Let me know if you have any additional questions. Hope this helps!
** BTW: If you don't have any experience with cloud-code, then you can complete steps 1-5, then manually send the notifications via the Parse Dashboard.

NSUbiquityIdentityDidChangeNotification doesn't work?

I'm creating a cloudkit app, and have been trying multiple ways to get the NSUbiquityIdentityDidChangeNotification, but I never am able to get this notification.
I've tried both of these code versions under the delegate didFinish and the viewDidLoad methods. And I tried calling it from another notification - UIApplicationDidBecomeActiveNotification. I also put import Foundation at top of files.
Here's the basic code I've tried:
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "handleIdentityChanged:",
name: NSUbiquityIdentityDidChangeNotification,
object: nil)
// And this one I tried too from another post here on SO:
var localeChangeObserver = NSNotificationCenter.defaultCenter().addObserverForName(NSUbiquityIdentityDidChangeNotification, object: nil, queue: NSOperationQueue.mainQueue()) { _ in
println("The user’s iCloud login changed: should refresh all user data.")
}
Does anyone know how to get this notification to work for only a cloudkit app in swift? I really just want to detect the iCloud status change and then initiate fetching the userID if there's been a change.
Not that I need to access the ubiquityIdentityToken, but I was wondering why not store the token and every-time the app starts compare the current token with the one in local storage to see if it's a different account or nil? Therefore, why is getting the notification necessary?
Also, the code for getting the token only seems to work if I turn on "iCloud Documents", which I don't need. Does anyone know the implications of having that turned on for a social app that doesn't need it? And is there another way to get the token without enabling iCloud Documents?
This is the code I used to get token and placed in the delegate didFinish method, but only works if iCloud documents is turned on:
var token = NSFileManager.defaultManager().ubiquityIdentityToken
println("token is \(token!)")
On iOS, when I sign out of iCloud, my app is killed. So there seems not really to be a need to receive a NSUbiquityIdentityDidChangeNotification. Like you have said, it seems to be sufficient to compare the current token to the saved token.
On the Apple TV though, my app was not killed when I logged out of iCloud. Here I had noticed the notification was not fired, like you described. Since the app is not killed, a notification would be in order. (Did Apple forget to kill apps on Apple TV when iCloud account is changed?)
With Apple TV there is no iCloud documents container available (unless I explicitly share one from an iOS app). I found that on the dev center website, for the app identifier, iCloud was shown as "Configurable" and not "Enabled" if no document container was selected. I wonder if this has an effect on receiving notifications.
Both on the Apple TV and iOS, I can also confirm that the iCloud token is nil when not using documents (here: key-value-store only). Now that makes it difficult for Apple TV apps (because the app is not killed on iCloud account change, like on iOS) to detect account changes.
I have just noticed that my Apple TV app does received several NSUbiquitousKeyValueStoreDidChangeExternallyNotification when I log into another iCloud account, to reflect the changes. I guess this is as good as it gets. These notifications come with the NSUbiquitousKeyValueStoreChangeReasonKey key in userInfo, and a value of NSUbiquitousKeyValueStoreAccountChange indicates the account has changed.
Sorry for not being able to provide a direct solution, maybe it helped to share my experience.
To be notified in iOS when a user logs in or out of iCloud while using your app, use CKAccountChangedNotification instead of NSUbiquityIdentityChanged notification.
(Longer explanation: https://stackoverflow.com/a/38689094/54423.)

IBM Worklight - Cannot register to event source callback with an existing alias. The alias is already in use for event source

I am using IBM Worklight 6.0.0 and testing on iOS 7 device.
I have the following js error:
Cannot register to event source callback with an existing alias: 'myPush'. The alias is already in use for event source 'PushEventSource'.
On device, when I login, logout then login again. (error appear the second time)
On the client side, my code is:
if (WL.Client.Push){
WL.Client.Push.onReadyToSubscribe = function(){
WL.Logger.debug("onReadyToSubscribe");
WL.Client.Push.registerEventSourceCallback(
"myPush",
"PushAdapter",
"PushEventSource",
pushNotificationReceived);
if (isPushSubscribed() == false) {
doSubscribe();
}
};
}
Is there something wrong with my code?
Is it because I should call "WL.Client.Push.registerEventSourceCallback" only once?
Any other solution?
You are not allowed to register an alias more than once as the error message shows. The error isn't that harmful, since regardless of the error message you can still receive push notifications (you may want to test this to be sure).
If you want to avoid the error message you have two options:
Ensure that the call to WL.Client.Push.registerEventSourceCallback
is called only once per app session, regardless of whether or not
the user has logged out.
Make a call to WL.Client.Push.unsubscribe when the user logs out to
clear the binding from the alias to the event source.
I'd suggest going with option 1. Push notification is tied to the device, not the user. Unless you plan on changing the event source alias for different users, there is no point in unsubscribing.

Resources