Where is record device token? - ios

I am trying to send Push Notification to all my test flight users. However, i don't know how i have to proceed. I followed the raywenderlich tutorial (here)
in the php file :
// Put your device token here (without spaces):
$deviceToken = 'e606c132727582dab8b280a01cb3c6498141f1e8b4ce61f66b47xxxxxxxxxxxx';
// Put your private key's passphrase here:
$passphrase = 'xxxxxxxx';
// Put your alert message here:
$message = 'My first push notification!';
you need to put the device token. Then how i can get all device token register to put in this file ?
I would like try this :
$deviceToken = getAllToken()
with getAllToken() return an array with all deviceToken registered with testFlight
I hope it's clear :)
Thanks !

Test flight won't help you in this. You need to record the deviceToken obtained through "didRegisterForRemoteNotification" and send it to the server. Here is an example in Swift (don't forget to remove some specific characters in the device token lik I've done).
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
// This method will be called everytime you open the app
NSLog("Device token:\(deviceToken)")
filteredDeviceToken=deviceToken.description.filter { $0 != Character(" ") } .filter { $0 != Character("<") }.filter { $0 != Character(">") }
sendToServer(filteredDeviceToken);
}
Of course, it's the "sendToServer" that will gives this information to your backend, and this is dependent of you.
You can also use existing services, like pushBot, parse, and others to take care of this for you: just add their lib and then you can send a push to all registered device

Related

Users can't open CKShare record when they accepted the record and application starts

Working my way thru implementing the CKShare functionality of CloudKit.
I Haven manged to get to the part to share a record (via email for example) and also can confirm the user received the invite. The problem is that when user accepts the record then the app pops up but nothing happens. In order to assist here are some key Elements of the app, and please tell me if i am wrong.
1) The application does not require user to login using their Apple ID
2) I am testing the application via a direct built on two different phones (with seperate Apple IDs) when i Connect the phones to the computer with a Cable (aka not using TestFlight yet).
3) I have checked in the CloudkitDashboard and i can see the record that hah been shared and also see that the recored hah been shared, but instead of seeing the user email I sent the invite I see my email and the fact that the record hah been "accepted"
4) I Haven added the CKSharingSupported key in the Info.plist file.
5) The code in the AppDelegate.swift file am using to accept the CKShare is below. I world like to raw your attention to the fact that the string "User Accepted the Share" never gets printed, which makes me think that this part of the code never runs.
func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) {
print("User Accepted the Share")
let acceptShareOperation: CKAcceptSharesOperation = CKAcceptSharesOperation(shareMetadatas: [cloudKitShareMetadata])
acceptShareOperation.qualityOfService = .userInteractive
acceptShareOperation.perShareCompletionBlock = {meta, share,
error in
print("The Record Share was Accepted")
}
acceptShareOperation.acceptSharesCompletionBlock = {
error in
/// Send your user to where they need to go in your app
let viewController: SNPDetailsViewController = self.window?.rootViewController as! SNPDetailsViewController
viewController.fetchShare(cloudKitShareMetadata)
}
CKContainer(identifier:
cloudKitShareMetadata.containerIdentifier).add(acceptShareOperation)
}
Any insight to guide me where I am wrong, will be much appreciated.
Thank you for your time!
Please see this answer for more context: CloudKit CKShare URL Goes Nowhere
But make sure that:
You specify a fallback URL for your CloudKit Container that redirects to your application.
Inside your app in Xcode, you set up a URL scheme so that custom URLs like yourapp:// open your application and the query parameter from the fallback URL gets passed into userDidAcceptCloudKitShareWith.
After weeks of trial and error, research and LUCK I managed to find out the problem. All tutorials and online solutions relate to the below code in the AppDelegate.swift, to accept a CKShare record:
func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) {
let acceptShareOperation: CKAcceptSharesOperation = CKAcceptSharesOperation(shareMetadatas: [cloudKitShareMetadata])
acceptShareOperation.qualityOfService = .userInteractive
acceptShareOperation.perShareCompletionBlock = {meta, share,
error in
DispatchQueue.main.async() {
print("The Record Share was Accepted")
}
}
acceptShareOperation.acceptSharesCompletionBlock = {
error in
guard (error == nil) else{
print("Error \(error?.localizedDescription ?? "")")
return
}
let viewController: SNPDetailsViewController = self.window?.rootViewController as! SNPDetailsViewController
viewController.fetchShare(cloudKitShareMetadata)
}
CKContainer(identifier:
cloudKitShareMetadata.containerIdentifier).add(acceptShareOperation)
}
The solution in my case was to add it in the SceneDelegate.swift in the following function:
func windowScene(_ windowScene: UIWindowScene, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) {
(add above code)
}
Hope this helps others!

How to send push notification when content on a website changes

The core of the app I am building is that it sends a push notification to the user twice a week with a number from a website, at a specific time twice a week (example of the Swift code I'm using for this below).
I did some research about background execution, but I think I will not be able to use it because it's so limited (only for location, limited time, etc.).
Using a server is another option. I do not intend to make money with this app so it has to be a free option. That's why I was looking into Firebase.
I'm learning Swift now, it's the first programming language I'm learning.
Does anyone have an opinion on how to go about doing this?
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = URL(string: "https://store.nike.com/be/nl_nl/pd/air-vapormax-flyknit-hardloopschoen-heren/pid-11384993/pgid-12169774")!
let request = NSMutableURLRequest(url: url)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
var message = ""
if error != nil {
print(error)
} else {
if let unwrappedData = data {
let dataString = NSString(data: unwrappedData, encoding: String.Encoding.utf8.rawValue)
var stringSeperator = "exp-pdp-local-price js-pdpLocalPrice"
if let contentArray = dataString?.components(separatedBy: stringSeperator) {
if contentArray.count > 0 {
stringSeperator = "€"
let newContentArray = contentArray[1].components(separatedBy: stringSeperator)
if newContentArray.count > 0 {
message = newContentArray[0]
print(message)
}
}
}
}
}
if message == "" {
message = "The jackpot couldn't be found. Please try again."
}
DispatchQueue.main.sync(execute: {
//De text in het label van de weer app = message
//Gebruik 'self.' om naar de viewcontroller te verwijzen, want hier zit je in een closure en niet in de viewcontroller zelf.
})
}
task.resume()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Push notifications are not complicated.
Basically you have to register your device to APNS ( Apple push notification system ), once registered device, APNS will return you a token (each token is device unique). When u get the token from APNS you have to send the token to the server which will provide your devices with push notifications. Once the server app receives a token from device, you can save it in database.
For example :
username1 mobile_token1, mobile_token2.
Now, you can get tokens from database for specific username and send push notifications from the server to the devices.
When you send push notifications from server to devices, you have to send the token and data content to APNS, APNS then will send notification to specific device.
So the answer for your question is, if you want to send push notifications you have to send them from backend to devices, the moment you will send push notifications is when the web content changes, you get the tokens from the database, and send notifications to APNS.
The logic is same when you use firebase instead APNS.
Here is a nice tutorial for client side
https://www.raywenderlich.com/156966/push-notifications-tutorial-getting-started
It seems you don't need a push notification (also called remote notification) but a local one (see apple documentation).
You can configure when during week you want this local notification to be fired.
Edit: I did not catch that content of notifications depends on your previous piece of code.
So you can still use a local notification. It will be triggered by what is called a background fetch.
See this tutorial for example (search 'Background fetch' on the page).

How to get One Signal user's unique player id in iOS?

How to retrieve the OneSignal users' unique player id in iOS?
I only found iOS SDK Setup in OneSignal Official Documentation.
Thanks if any suggestions are given.
You need to use OneSignal's observers such as OSSubscriptionObserver.
// Add OSSubscriptionObserver after UIApplicationDelegate
class AppDelegate: UIResponder, UIApplicationDelegate, OSSubscriptionObserver {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Add your AppDelegate as an subscription observer
OneSignal.add(self as OSSubscriptionObserver)
}
// After you add the observer on didFinishLaunching, this method will be called when the notification subscription property changes.
func onOSSubscriptionChanged(_ stateChanges: OSSubscriptionStateChanges!) {
if !stateChanges.from.subscribed && stateChanges.to.subscribed {
print("Subscribed for OneSignal push notifications!")
}
print("SubscriptionStateChange: \n\(stateChanges)")
//The player id is inside stateChanges. But be careful, this value can be nil if the user has not granted you permission to send notifications.
if let playerId = stateChanges.to.userId {
print("Current playerId \(playerId)")
}
}
}
For a better explanation, here is the documentation for addSubscriptionObserver
I do need to get the Player Id (Or UserId) somewhere inside my code, and i dont want to save it anywhere.
I ended up using this code:
let userId = OneSignal.getPermissionSubscriptionState().subscriptionStatus.userId
let status: OSPermissionSubscriptionState = OneSignal.getPermissionSubscriptionState()
let hasPrompted = status.permissionStatus.hasPrompted
print("hasPrompted = \(hasPrompted)")
let userStatus = status.permissionStatus.status
print("userStatus = \(userStatus)")
let isSubscribed = status.subscriptionStatus.subscribed
print("isSubscribed = \(isSubscribed)")
let userSubscriptionSetting = status.subscriptionStatus.userSubscriptionSetting
print("userSubscriptionSetting = \(userSubscriptionSetting)")
let userID = status.subscriptionStatus.userId // This one
print("userID = \(userID)")
let pushToken = status.subscriptionStatus.pushToken
print("pushToken = \(pushToken)")
This is what worked for me because the other solutions are deprecated:
let userId = OneSignal.getDeviceState().userId
Make sure you import OneSignal:
import OneSignal
On WebViewGold-based apps on iOS (WKWebView / UIWebView) in combination with OneSignal ,you might need a little bit of back-end work to connect it to our OneSignal API: You should save the ?onesignal_push_id=XYZ parameter in a database, and fire the OneSignal API (https://documentation.onesignal.com/docs/onesignal-api) for that specific user as soon as a push notification should be sent. This has to be done by your back-end/webserver. WebViewGold only offers the built-in OneSignal API and the ability to deliver the ?onesignal_push_id=XYZ appendix to your WebView URL call.
So activate the „kPushEnhanceUrl“ option in Config.swift (by switching the value from false to true) to append the individual user ID via ?onesignal_push_id=XYZ to your WebView URL.
If your WebView URL is https://www.example.org, WebViewGold will call https://www.example.org?onesignal_push_id=XYZ instead. Only your FIRST URL request will get that GET variable, so save it in a session or in a cookie to access it on your linked pages. An alternative or additional way would be to retrieve & process the information on any page via JavaScript:
<script>
window.location.href = "getonesignalplayerid://";
alert(onesignalplayerid);
</script>
You can find it inside of standardUserDefaults. You can retrieve it using the following. I believe it is set at the first app launch, however, it might not be set the first time application:didFinishLaunchingWithOptions: is called.
UserDefaults.standard.string(forKey: "GT_PLAYER_ID")
You can see what else is stored in user defaults by looking at the dictionary representation: UserDefaults.standard.dictionaryRepresentation()

How do you unregister for VOIP push notifications with Twilio Swift SDK

I'm using the Twilio iOS Swift Callkit starter code and have successfully got an app + server and running dispensing access tokens, calls being made and received via VOIP push notification.
Now I want to be able to let the user log out. How do I unregister for VOIP push notifications.
I can see that there is this function in my code which looks like the thing to do it, but it looks like something that gets called by something else rather than directly.
func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenForType type: PKPushType) {
NSLog("pushRegistry:didInvalidatePushTokenForType:")
if (type != .voIP) {
return
}
guard let deviceToken = deviceTokenString, let accessToken = fetchAccessToken() else {
return
}
VoiceClient.sharedInstance().unregister(withAccessToken: accessToken, deviceToken: deviceToken) { (error) in
if (error != nil) {
NSLog("An error occurred while unregistering: \(error?.localizedDescription)")
}
else {
NSLog("Successfully unregistered from VoIP push notifications.")
}
}
self.deviceTokenString = nil
}
How do I cause it to be called?
Thanks.
Twilio developer evangelist here.
It looks as though you need to call unregisterWithAccessToken:deviceToken:completion. Much like in registerWithAccessToken:deviceToken:completion, the accessToken is your Twilio Access Token, the deviceToken is the push registry token for the Apple Voip service and the completion will get called when the unregistration is successful.
Let me know if that helps.

Send push notification to a specific test device using OneSignal push notification service

I added push notification support to my iOS app using OneSignal some time before. The app is made in Xcode with Swift.
I want to send a test push notification only to my test device(s). I the documentation I found the following manual: How do I send a notification to a single user?
I managed to create the segment but I don't know where to put this peace of code: OneSignal.sendTag("is_test", "true")
Does anybody know where I have to put this piece of code to make it working as I described above?
I uploaded my code here: https://codeshare.io/DxcNn
Thanks,
David.
Update:
OneSignal now also supports to set a device as test device without doing something in the code. You can also download your own app from App Store and use it as test device. Just select you device from devices list one OneSignal and mark it as test device. You can find your device in the list by model, version and/or time added.
The sendTag method is from the device sdk. In your case iOS.
https://documentation.onesignal.com/docs/ios-native-sdk#section--sendtag-
You should do this anytime after initWithLaunchOptions in the app delegate. Updated code based on comments
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
let oneSignal = OneSignal(launchOptions: launchOptions, appId: "here_is_my_onesignal_app_id") { (message, additionalData, isActive) in
NSLog("OneSignal Notification opened:\nMessage: %#", message)
if additionalData != nil {
NSLog("additionalData: %#", additionalData)
// Check for and read any custom values you added to the notification
// This done with the "Additonal Data" section the dashbaord.
// OR setting the 'data' field on our REST API.
if let customKey = additionalData["customKey"] as! String? {
NSLog("customKey: %#", customKey)
}
}
}
OneSignal.defaultClient().sendTag("is_test", value: "true")
// Override point for customization after application launch.
return true
}

Resources