How to display only once same push notifications? - ios

I'm using push notifications on my app, and i didn't find a way to display only once notifications that have same content.
Is that possible ?
My code :
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UIAlertViewDelegate, GGLInstanceIDDelegate, GCMReceiverDelegate {
var window: UIWindow?
var gcmSenderID: String?
var registrationOptions = [String: AnyObject]()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
var configureError:NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
gcmSenderID = GGLContext.sharedInstance().configuration.gcmSenderID
UIApplication.sharedApplication().registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: [category]))
UIApplication.sharedApplication().registerForRemoteNotifications()
let gcmConfig = GCMConfig.defaultConfig()
gcmConfig.receiverDelegate = self
GCMService.sharedInstance().startWithConfig(gcmConfig)
return true
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let instanceIDConfig = GGLInstanceIDConfig.defaultConfig()
instanceIDConfig.delegate = self
GGLInstanceID.sharedInstance().startWithConfig(instanceIDConfig)
registrationOptions = [kGGLInstanceIDRegisterAPNSOption:deviceToken,
kGGLInstanceIDAPNSServerTypeSandboxOption:true]
GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID,
scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler)
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print(error.localizedDescription)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
GCMService.sharedInstance().appDidReceiveMessage(userInfo)
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
GCMService.sharedInstance().disconnect()
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
GCMService.sharedInstance().connectWithHandler({(error:NSError?) -> Void in
if let error = error {
print("Could not connect to GCM: \(error.localizedDescription)")
} else {
print("Connected to GCM")
}
})
}
func onTokenRefresh() {
GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID, scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler)
}
func registrationHandler(registrationToken: String!, error: NSError!) {
if(registrationToken != nil) {
print(registrationToken)
}else{
print("Registration to GCM failed with error: \(error.localizedDescription)")
}
}
}
I'm using Google Cloud Messaging for push notification into my app
Thank's in advance

Related

didRegisterForRemoteNotificationsWithDeviceToken not called with simple iOS app

I created a simple empty iOS application with XCode 11.5.
With my device iOS 13.5.1, I am tying to implement push notifications but I dont receive the device push token or any error.
What am I doing wrong?
The method didRegisterForRemoteNotificationsWithDeviceToken is never called.
With following code:
import UIKit
import UserNotifications
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
registerForRemoteNotification()
return true
}
func registerForRemoteNotification() {
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
print("Authorization executed")
}
UIApplication.shared.registerForRemoteNotifications()
}
else {
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil))
UIApplication.shared.registerForRemoteNotifications()
}
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
print("Device Token: \(token)")
}
func application(
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Failed to register: \(error)")
}
}
I have following output in the console:
Requesting permission
2020-06-06 12:13:23 +0000
Authorization executed
Requesting permission
2020-06-06 12:13:24 +0000
...
...
...
Screenshot:
Before trying this, make sure you have added this Capabilities...
under 'Capabilities', (next to General),
- Push Notifications option is turned ON`
- and under Background Modes, Remote Notifications is turned ON
For me it took like 6 hours after I recived all tokens that I requested. It really can take a long time sometimes
Import the UserNotifications framework and add the UNUserNotificationCenterDelegate in AppDelegate.swift
Request user permission
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
// Enable or disable features based on authorization.
}
notificationCenter.delegate = self
application.registerForRemoteNotifications()
return true
}
Getting device token
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
{
let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
print(deviceTokenString)
}
In case of error
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("i am not available in simulator \(error)")
}
In case if you need to know the permissions granted
UNUserNotificationCenter.current().getNotificationSettings(){ (settings) in
switch settings.soundSetting{
case .enabled:
print("enabled sound setting")
case .disabled:
print("setting has been disabled")
case .notSupported:
print("something vital went wrong here")
}
}
On Receiving notification following delegate will call:
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
println("Recived: \(userInfo)")
//Parsing userinfo:
var temp : NSDictionary = userInfo
if let info = userInfo["aps"] as? Dictionary<String, AnyObject>
{
var alertMsg = info["alert"] as! String
var alert: UIAlertView!
alert = UIAlertView(title: "", message: alertMsg, delegate: nil, cancelButtonTitle: "OK")
alert.show()
}
}
In your case, I think you need to replace:-
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
with,
let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})

Registering for Push notifications functions don't get called

I'm making this sweet app that requires Push notifications.
However when trying to grab the Push token not all required functions seem to get executed.
The user does get presented with this Alert:
When the user hits OK I step through my code and see that not everything gets executed:
override func viewDidLoad(){
let tapper = UITapGestureRecognizer(target: view, action:#selector(UIView.endEditing))
tapper.cancelsTouchesInView = false
view.addGestureRecognizer(tapper)
print("gets called")
registerForPushNotifications(UIApplication.sharedApplication())
}
func registerForPushNotifications(application: UIApplication) {
print("gets called")
let notificationSettings = UIUserNotificationSettings(
forTypes: [.Badge, .Sound, .Alert], categories: nil)
application.registerUserNotificationSettings(notificationSettings)
}
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
print("doesn't get called")
if notificationSettings.types != .None {
application.registerForRemoteNotifications()
}
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
print("doesn't get called")
let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
var apnsTokenString = ""
for i in 0..<deviceToken.length {
apnsTokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
}
Constant.pushToken = apnsTokenString
print("Device Token:", Constant.pushToken)
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
debugPrint("Error Registering Remote Notification")
}
In my console the following gets printed:
gets called
gets called
Meaning that not all required functions get called. What am I doing wrong?
Assuming all of the code you posted in your question is in your view controller class, the problem is that you need to put the UIApplicationDelegate methods in your actual app delegate class, not the view controller class. Simply move those methods to the proper class and they will work.
Just use this code
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
print("gets called")
let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let characterSet: NSCharacterSet = NSCharacterSet(charactersInString: "<>")
let deviceTokenString: String = (deviceToken.description as NSString)
.stringByTrimmingCharactersInSet(characterSet)
.stringByReplacingOccurrencesOfString( " ", withString: "") as String
print(deviceTokenString)
}

Firebase Notification not working on Testflight

I have created app with notification. When i send notification on developer mode then i get notifications. but when i send on release mod i don't get anything. I read that i should change certificate to product certificat. But it doesn't helped. here is my appdelegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FIRApp.configure()
let notificationTypes : UIUserNotificationType = [.alert, .badge, .sound]
let notificationSettings : UIUserNotificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: nil)
application.registerForRemoteNotifications()
application.registerUserNotificationSettings(notificationSettings)
return true
}
private func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
FIRMessaging.messaging().subscribe(toTopic: "/topics/main")
}
private func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData)
{
FIRInstanceID.instanceID().setAPNSToken(deviceToken as Data, type: FIRInstanceIDAPNSTokenType.prod)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print(userInfo["gcm.message_id"]!)
print(userInfo)
}
func application(_ application: UIApplication, dirtings: UIUserNotificationSettings)
{
UIApplication.shared.registerForRemoteNotifications()
}
func tokenRefreshNotification(notification: NSNotification) {
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
// Connect to FCM since connection may have failed when attempted before having a token.
connectToFcm()
}
func connectToFcm() {
FIRMessaging.messaging().connect { (error) in
if (error != nil) {
print("Unable to connect with FCM. \(error)")
} else {
print("Connected to FCM.")
}
}
}
private func applicationDidEnterBackground(application: UIApplication) {
FIRMessaging.messaging().disconnect()
print("Disconnected from FCM.")
}
Just went through this,
I turned push off and deleted the certs from apple dev center and created them all over again and this made everything work as it should.
I also had this line of code set to,
FIRInstanceID.instanceID().setAPNSToken(deviceToken as Data, type: FIRInstanceIDAPNSTokenType.sandbox)
I will change it to .prod when I push to the app store.
I found solution. problem was with prod certificate. i forget to add prod cetificate to firebase.

iOS GCM notification sending, but not showing

I'm trying to implement GCM in my iOS app. Everything seems to work fine, the app is connecting to GCM and getting a registration ID back. If I send a notification to that regid using Postman it works and I get a success response back from Google. However, whatever I try, the notification isn't actually shown on the device.
The post messsage to the GCM servers I'm using is
{
"to" : "RegID",
"content_available" : true,
"notification" : {
"body" : "Test Body",
"title" : "Test Title"
}
}
which gives me the response:
{
"multicast_id": 6594175386712804014,
"success": 1,
"failure": 0,
"canonical_ids": 0,
"results": [
{
"message_id": "0:1443445858075083%c4cfa24dc4cfa24d"
}
]
}
This makes me believe there is something wrong with the code in my app. Below I've pasted all the relevant code. I've written the code 3 times without success, first following the tutorial and editing it to fit in my app properly, second time I copied the code from the tutorial and the third time I got the example app from the Github repo and copied everything relevant to GCM over.
AppDelegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var connectedToGCM = false
var gcmSenderID: String?
var registrationToken: String?
var registrationOptions = [String: AnyObject]()
let defaults = NSUserDefaults.standardUserDefaults()
let registrationKey = "onRegistrationCompleted"
let messageKey = "onMessageReceived"
let notification = "isNotificationEnabled"
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Google Cloud Messaging
var configureError:NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
gcmSenderID = GGLContext.sharedInstance().configuration.gcmSenderID
var types: UIUserNotificationType = UIUserNotificationType.Badge |
UIUserNotificationType.Alert |
UIUserNotificationType.Sound
var settings: UIUserNotificationSettings =
UIUserNotificationSettings( forTypes: types, categories: nil )
application.registerUserNotificationSettings( settings )
application.registerForRemoteNotifications()
var gcmConfig = GCMConfig.defaultConfig()
GCMService.sharedInstance().startWithConfig(gcmConfig)
return true
}
func applicationDidBecomeActive(application: UIApplication) {
GCMService.sharedInstance().connectWithHandler({
(NSError error) -> Void in
if error != nil {
println("Could not connect to GCM: \(error.localizedDescription)")
} else {
self.connectedToGCM = true
println("Connected to GCM")
// ...
}
})
}
func application( application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken
deviceToken: NSData ) {
println(deviceToken)
// [END receice_apns_token]
// [START get_gcm_reg_token]
// Create a config and set a delegate that implements the GGLInstaceIDDelegate protocol.
var instanceIDConfig = GGLInstanceIDConfig.defaultConfig()
// Start the GGLInstanceID shared instance with that config and request a registration
// token to enable reception of notifications
GGLInstanceID.sharedInstance().startWithConfig(instanceIDConfig)
registrationOptions = [kGGLInstanceIDRegisterAPNSOption:deviceToken,
kGGLInstanceIDAPNSServerTypeSandboxOption:true]
GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID,
scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler)
// [END get_gcm_reg_token]
}
func registrationHandler(registrationToken: String!, error: NSError!) {
if (registrationToken != nil) {
self.registrationToken = registrationToken
println("Registration Token: \(registrationToken)")
let userInfo = ["registrationToken": registrationToken]
NSNotificationCenter.defaultCenter().postNotificationName(
self.registrationKey, object: nil, userInfo: userInfo)
} else {
println("Registration to GCM failed with error: \(error.localizedDescription)")
let userInfo = ["error": error.localizedDescription]
NSNotificationCenter.defaultCenter().postNotificationName(
self.registrationKey, object: nil, userInfo: userInfo)
}
}
func onTokenRefresh() {
// A rotation of the registration tokens is happening, so the app needs to request a new token.
println("The GCM registration token needs to be changed.")
GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID,
scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler)
}
func application( application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
println("Notification received: \(userInfo)")
// This works only if the app started the GCM service
GCMService.sharedInstance().appDidReceiveMessage(userInfo);
// Handle the received message
// Invoke the completion handler passing the appropriate UIBackgroundFetchResult value
// [START_EXCLUDE]
NSNotificationCenter.defaultCenter().postNotificationName(messageKey, object: nil,
userInfo: userInfo)
}
If anyone asked a similar question before let me know, I wasn't able to find one that described my situation properly.
Thanks in advance!
You haven't implemented the appropriate notification callback. You need to implement
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// Do something with userInfo
// call fetchCompletionHandler with the appropriate UIBackgroundFetchResult
}
Silent Push Notifications(i.e. ones with content-available flag set) call the above UIApplicationDelegate method instead of application:didReceiveRemoteNotification:.
Also make sure you've added remote-notification value to the UIBackgroundModes in your Info.plist.

Swift gcm push can't receive notification

I have problem with GCM and ios push notificaion.
App connect to GCM and all that works but when i can't receive notification.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let gcmSenderID = sharedUser.getGcmSenderId()
if gcmSenderID?.characters.count > 0 {
var configureError:NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
if configureError != nil {
print("Error configuring the Google context: \(configureError)")
}
let settings: UIUserNotificationSettings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
}
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
GGLInstanceID.sharedInstance().startWithConfig(GGLInstanceIDConfig.defaultConfig())
registrationOptions = [kGGLInstanceIDRegisterAPNSOption:deviceToken,
kGGLInstanceIDAPNSServerTypeSandboxOption:true]
GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID,
scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler)
}
func registrationHandler(registrationToken: String!, error: NSError!) {
if (registrationToken != nil) {
let params = [
"reg_id": registrationToken,
"dev_id": UIDevice.currentDevice().identifierForVendor!.UUIDString
]
Alamofire.request(.POST, Config().gcmRegUrl, parameters: params, encoding: .JSON)
print("Registred")
} else {
print("Registration to GCM failed with error: \(error.localizedDescription)")
}
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler handler: (UIBackgroundFetchResult) -> Void) {
print("Message")
}
This didReceiveRemoteNotification never fires, and i am sure that server send message.
What can be problem?
Thanks to Arthur Thompson, needed this:
func applicationDidBecomeActive(application: UIApplication) {
GCMService.sharedInstance().connectWithHandler({
(NSError error) -> Void in
if error != nil {
print("Could not connect to GCM: \(error.localizedDescription)")
} else {
print("Connected to GCM")
}
})
}
And i forgot:
GCMService.sharedInstance().startWithConfig(GCMConfig.defaultConfig())
to add on didFinishLaunchingWithOptions.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let gcmSenderID = sharedUser.getGcmSenderId()
if gcmSenderID?.characters.count > 0 {
var configureError:NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
if configureError != nil {
print("Error configuring the Google context: \(configureError)")
}
let settings: UIUserNotificationSettings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
GCMService.sharedInstance().startWithConfig(GCMConfig.defaultConfig())
}
}
Now everything works..

Resources