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).
Related
I'm working on a Xamarion iOS app. I want to display a local notification when an event occurs in my app, Like Outlook does when an email is received.
I'm using the following code, after having received the right to send notification from the user, of course:
var content = new UNMutableNotificationContent();
if (!string.IsNullOrWhiteSpace(value: mySoundFile))
{
content.Sound = UNNotificationSound.GetCriticalSound(mySoundFile);
}
if (!string.IsNullOrEmpty(myChannelDescription))
{
content.ThreadIdentifier = myChannelDescription;
}
content.Title = "MyTitle";
content.Body = "MyText";
var trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(0.1, false);
var request = UNNotificationRequest.FromIdentifier(notification.Id.ToString(), content, trigger);
var center = UNUserNotificationCenter.Current;
center.AddNotificationRequest(request, null);
But the notification is not displayed.
Any help appreciated.
The reason for not displaying the notification could be several things. Try the following solutions:
Make sure that the application has the required rights to send notifications and that the user has enabled them.
Check if the sound file is valid and located in the application package. It may also be necessary to add it to the Info.plist file.
Check if the thread identifier is valid and not repeatable.
Check if the trigger time is valid. Setting 0.1 seconds is very short and may not be enough to display the notification.
If the above solutions do not work, it is worth using debugging tools to more closely examine why the notification is not displayed.
On iOS, you must request permission to use notifications before attempting to schedule them. Just like this, you can try to check if the following code is added to your project:
UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert, (approved, err) =>
{
...
});
You can change your AddNotificationRequest as follows to see if there is an error in the notification:
center.AddNotificationRequest(request, (err) =>
{
if (err != null)
{
throw new Exception($"Failed to schedule notification: {err}");
}
});
For more details, you can refer to the following documents to check some permission issues:
Enhanced User Notifications in Xamarin.iOS | Microsoft
Asking permission to use notifications | Apple Developer
UpDate: If your app is in the foreground. You could try implementing the delegate userNotificationCenter(_:willPresent:withCompletionHandler:) which will be called when a notification arrives while the app is in the foreground. Refer to the following code:
UNUserNotificationCenter.Current.Delegate = new TestDelegate();
public class TestDelegate: UNUserNotificationCenterDelegate
{
public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
completionHandler(UNNotificationPresentationOptions.Alert);
}
}
I have started a new project to try out Twilio programable chat but I'm not able to get the push notifications to work.
I am using Firebase to handle the push notifications and notifications directly from Firebase are working fine.
Now here's how I've configured everything:
I am using a Twilio function for my chat to work. I've created an FCM push credential on Twilio dashboard and when asked for the FCM SECRET I've added the Server key that was inside the Cloud Messaging Settings on Firebase console.
I have updated the push notification configuration to enable notifications on a new message on the dashboard like this:
On the app I do have push notifications working, because I am able to receive notifications directly from Firebase.
I've registered for remote notifications on didFinishLaunchingWithOptions like this:
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { _, _ in }
application.registerForRemoteNotifications()
On AppDelegate I'm actually receiving the device token, storing it for later and setting it on my chat client
static var token: Data?
func application(_: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
AppDelegate.token = deviceToken
}
After that, when I'm creating my chat client, I set the device token and the callback's result is successful
func signIn(identity: String) {
self.identity = identity
tokenService.retrieveToken(identity: identity) { result in
if case let .success(token) = result {
TwilioChatClient.chatClient(withToken: token, properties: nil, delegate: self) { _, client in
self.client = client
if let pushToken = AppDelegate.token {
client?.register(withNotificationToken: pushToken) { result in
print(result.isSuccessful()) // this prints true
}
}
}
}
}
}
After all this setup I'm still not able to receive push notifications, so I'm not sure if I'm doing something wrong or if I'm missing something
I have had similar issue. My problem was that I was not able to receive push notifications on iOS 13.
For me the solution was to update the Twilio SDK within iOS Project.
Right now it is v.4.0.0
I have written an iOS app that refreshes its data model when a push notification is received whilst the app is in the foreground, once the data is retrieved from the server I send that information to the watch kit app using:
// This code resides in ErrorsViewController.swift
func updateWatchContext() {
do {
let messages = convertParseObjectsToJSON(tasks)
try session?.updateApplicationContext(["messages" : messages])
} catch let error as NSError {
NSLog("Updating the context failed: " + error.localizedDescription)
}
}
func convertParseObjectsToJSON(data:[PFObject])->[[String : AnyObject]]
{
var data = [[String:AnyObject]]()
for var i = 0; i < tasks.count; i++
{
let object = tasks[i]
data.append([
"createDate" : object["createDate"],
"errorMessage" : object["errorCode"]
])
}
return data
}
This works fine when the application is in the foreground, the data model gets updated on the watch as expected. However in the scenario that the phone is running in the background, how can I make a background fetch, parse the data and send it to the watchkit app without waking the iPhone, using watch connectivity?
I was thinking about trying to add the code in AppDelegate, but I don't believe that will work. I'd like to note that I do not want to make any network requests directly from the watch itself due to the limited CPU power; it would be un-necessary to handle the data parsing there.
Hi I want to fetch some data using Alamofire and a NSTimer
The app works fine on foreground, the timer is set to call the GetEstado function each 30 seconds but when the app enters background the timer is paused and if my server updates something it does not actually updates on the app
Here's my code
func GetEstado(){
Alamofire.request(.POST, "https://myurl/getestado.php", parameters: ["id": id])
.responseString { rta in
if let dataFromString = rta.result.value!.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
let json = JSON(data: dataFromString)
for (key,subJson):(String, JSON) in json {
if(key=="e"){
if(subJson.stringValue=="1"){
self.Timer.invalidate()
print("ACTUALIZACION")
let notification = UILocalNotification()
notification.fireDate = NSDate(timeIntervalSinceNow: 5)
notification.alertBody = "UPDATED"
notification.soundName = UILocalNotificationDefaultSoundName
UIApplication.sharedApplication().scheduleLocalNotification(notification)
self.performSegueWithIdentifier("UPDATED", sender: self)
}
else{
print("UPS")
}
}
}
}
}
}
Thanks
I think #Paulw11 answer your question in his comment, you can't use NSTimer in background, Apple has a known list of the task that can be produced in background, you can read more here.
But let think for a moment what you're trying to achieve, let suppose you can do it using NSTimer, then you have your app in background consuming memory and battery in your device constantly to try to get the updates from your server, this is not recommended at all.
It's for this that Apple/Google introduced Apple Push Notifications (Google: Android Push Notifications) to handle that the server notifies the app when it's in background or inactive regarding any task that is programmed in the server, lets say a new mail, a new message in the case of messaging apps, etc.
Then, the option you have is use the service proposed by Apple, you can read more in the following docs:
Notifications
Apple Push Notification Service
I hope this help you.
I am having troubles increasing the badge number using the Parse iOS Framework.
When I call this code, the other user gets the Push notification, but his badge number is not increasing on the icon.
let push = PFPush()
let data = ["badge": "Increment"]
push.setData(data)
push.setChannel("channel_\(userId)")
push.setMessage(message)
var err: NSError?
do {
try push.sendPush()
} catch var error as NSError {
err = error
} catch {
fatalError()
}
Thanks!
Try with this in swift for increase
let currentCountStr = UIApplication.sharedApplication().applicationIconBadgeNumber.description
let currentCount = Int(currentCountStr)
if(currentCount > 0) {
UIApplication.sharedApplication().applicationIconBadgeNumber = currentCount! + 1
} else {
UIApplication.sharedApplication().applicationIconBadgeNumber = 1
}
You should check your database and/or code if you successfully updated 'Installation' table. The way it works is, that they store badge number in that table (perhaps refresh after each application is awaken) so later server can send incremented number inside notification payload.
Parse had a blog entry on this : http://blog.parse.com/announcements/badge-management-for-ios/
Just to add note how it works in more generic environment :
You should send actual new badge number from the server, it is not just incremented for you.
There is good deal of information on another question :
Increment the Push notification Badge iPhone