VoIP ringtone not working - ios

I'm using iOS version 9 and swift as well. I Can receive a call while the app is is active but when the app is closed or in the background, I have an issue, It only gets a notification, not a full ringtone (I'm using SinchService) but it's not working. I've added the VoIP certificate and it's valid
code
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
sinch?.push().application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
sinch?.push().application(application, didReceiveRemoteNotification: userInfo)
}
func startManager() {
let config = SinchService.config(withApplicationKey: VoiceManager.SinchKey, applicationSecret: VoiceManager.SinchSecret, environmentHost: VoiceManager.SinchHost).pushNotifications(with: SINAPSEnvironment.development)
let sinch = SinchService.service(with: config)
sinch?.delegate = self
sinch?.callClient().delegate = self
let push = Sinch.managedPush(with: SINAPSEnvironment.development)
push?.delegate = self
push?.setDesiredPushTypeAutomatically()
let appDelegate: AppDelegate = (UIApplication.shared.delegate as! AppDelegate)
appDelegate.sinch = sinch
appDelegate.push = push
}
// MARK: - SINCallClientDelegate
func client(_ client: SINCallClient!, didReceiveIncomingCall call: SINCall!) {
//show calling view
let controller = UIViewController.currentViewController()
VoiceCallingViewController.show(call: call, viewController: controller)
}
func client(_ client: SINCallClient!, localNotificationForIncomingCall call: SINCall!) -> SINLocalNotification! {
let notification = SINLocalNotification()
notification.alertAction! = LanguageManager.localizedString(key: "answer")
notification.alertBody = "\(LanguageManager.localizedString(key: "incomming-call")) \(call.remoteUserId)"
return notification
}

you are not setting any sound in you localnotification method. add sound to notification

Related

IOS Swift Pushkit: didUpdatePushCredentials not called

I am trying to develop a VoIP app using Twilio Client iOS SDK. My app receives incoming calls when its not in background. For background mode I am trying to use PushKit Framework as Apple suggests. But my app is not getting registered for PushKit. The method didUpdatePushCredentials is not getting called.
This is my app delegate and settings:
import UIKit
import PushKit;
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var voipRegistry: PKPushRegistry!;
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
if UIApplication.instancesRespondToSelector(#selector(UIApplication.registerUserNotificationSettings(_:))) {
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [UIUserNotificationType.Alert, UIUserNotificationType.Badge, UIUserNotificationType.Sound], categories: nil))
}
let preferences = NSUserDefaults.standardUserDefaults()
let usrIdKey = "usrId"
let tokenKey = "token"
if preferences.objectForKey(usrIdKey) == nil || preferences.objectForKey(tokenKey) == nil{
// Doesn't exist
} else {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
var nav1 = UINavigationController()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewControllerObj = storyboard.instantiateViewControllerWithIdentifier("NumberScreenViewController") as? NumberScreenViewController
nav1.viewControllers = [viewControllerObj!]
self.window!.rootViewController = nav1
self.window?.makeKeyAndVisible()
}
phone.login{
device in
}
var state:String
switch application.applicationState {
case .Active:
state = "Active"
case .Background:
state = "Background"
case .Inactive:
state = "Active"
}
NSLog("App launched with state \(state)")
return true
}
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state informationO 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.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
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.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
//output to see when we terminate the app
NSLog("app terminated")
}
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
NSLog("Registering for VOIP notifications.")
//register for voip notifications
voipRegistry = PKPushRegistry(queue: dispatch_get_main_queue())
voipRegistry.desiredPushTypes = Set([PKPushTypeVoIP])
voipRegistry.delegate = self;
}
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification)
{
if ( application.applicationState == UIApplicationState.Active)
{
print("Active")
// App is foreground and notification is recieved,
// Show a alert.
}
else if( application.applicationState == UIApplicationState.Background)
{
print("Background")
// App is in background and notification is received,
// You can fetch required data here don't do anything with UI.
self.redirectToPage(notification.userInfo)
}
else if( application.applicationState == UIApplicationState.Inactive)
{
print("Inactive")
// App came in foreground by used clicking on notification,
// Use userinfo for redirecting to specific view controller.
self.redirectToPage(notification.userInfo)
}
}
func redirectToPage(userInfo:[NSObject : AnyObject]!)
{
var viewControllerToBrRedirectedTo:DialScreenViewController = DialScreenViewController(nibName: "DialScreenViewController", bundle: nil)
if userInfo != nil
{
if let pageType = userInfo["TYPE"]
{
if pageType as! String == "Page1"
{
// viewControllerToBrRedirectedTo = UIViewController() // creater specific view controller
}
}
}
if self.window != nil && self.window?.rootViewController != nil
{
let rootVC = self.window?.rootViewController!
if rootVC is UINavigationController
{
(rootVC as! UINavigationController).pushViewController(viewControllerToBrRedirectedTo, animated: true)
}
else
{
rootVC?.presentViewController(viewControllerToBrRedirectedTo, animated: true, completion: { () -> Void in
})
}
}
}
}
extension AppDelegate: PKPushRegistryDelegate {
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
//print out the VoIP token. We will use this to test the nofications.
NSLog("voip token: \(credentials.token)")
}
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
let payloadDict = payload.dictionaryPayload["aps"] as? Dictionary<String, String>
let message = payloadDict?["alert"]
//present a local notifcation to visually see when we are recieving a VoIP Notification
if UIApplication.sharedApplication().applicationState == UIApplicationState.Background {
let localNotification = UILocalNotification();
localNotification.alertBody = message
localNotification.applicationIconBadgeNumber = 1;
localNotification.soundName = UILocalNotificationDefaultSoundName;
UIApplication.sharedApplication().presentLocalNotificationNow(localNotification);
}
else {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let alert = UIAlertView(title: "VoIP Notification", message: message, delegate: nil, cancelButtonTitle: "Ok");
alert.show()
})
}
NSLog("incoming voip notfication: \(payload.dictionaryPayload)")
}
func pushRegistry(registry: PKPushRegistry!, didInvalidatePushTokenForType type: String!) {
NSLog("token invalidated")
}
}
I have same problem. However it was recovered after rebooting the phone.
Go through https://www.raywenderlich.com/123862/push-notifications-tutorial
Download
import UIKit
import PushKit
class AppDelegate: UIResponder, UIApplicationDelegate,PKPushRegistryDelegate{
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let types: UIRemoteNotificationType = [.Alert, .Badge, .Sound]
application.registerForRemoteNotificationTypes(types)
self. PushKitRegistration()
return true
}
//MARK: - PushKitRegistration
func PushKitRegistration()
{
let mainQueue = dispatch_get_main_queue()
// Create a push registry object
if #available(iOS 8.0, *) {
let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)
// Set the registry's delegate to self
voipRegistry.delegate = self
// Set the push type to VoIP
voipRegistry.desiredPushTypes = [PKPushTypeVoIP]
} else {
// Fallback on earlier versions
}
}
#available(iOS 8.0, *)
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
// Register VoIP push token (a property of PKPushCredentials) with server
let hexString : String = UnsafeBufferPointer<UInt8>(start: UnsafePointer(credentials.token.bytes),
count: credentials.token.length).map { String(format: "%02x", $0) }.joinWithSeparator("")
print(hexString)
}
#available(iOS 8.0, *)
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
// Process the received push
}
}
Life cycle of app - when app is in terminated and push kit payload comes

Register for voip notifications outside of app delegate

My app requires onboarding and I want to wait until the user reach the AskForVOIPNotificationsViewController before I ask for permission to present push/voip notifications. The code below kind of works, the problem is that pushRegistry in AppDelegate does not realise it has permission and didUpdatePushCredentials in AppDelegate does not get called. The code is never run and the server never gets the device token. However if I close the app and relaunch, didUpdatePushCredentials is called, the server gets the token and the user is able to receive notifications.
How can I make sure didUpdatePushCredentials/PKPushRegistry is called from AskForVOIPNotificationsViewController so that the user is able to receive voip notifications immediately without relaunching the app?
I implemented my code according to a similar question, but I am unable to get it to work with PushKit.
Any help is VERY much appreciated - thank you !
In AskForVOIPNotificationsViewController
func registerForNotifications() {
let notificationSettings: UIUserNotificationSettings! = UIApplication.sharedApplication().currentUserNotificationSettings()
if !notificationSettings.types.contains([.Badge, .Sound, .Alert]) {
let notificationTypes: UIUserNotificationType = [.Badge, .Sound, .Alert]
let notificationSettings = UIUserNotificationSettings(forTypes: notificationTypes, categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(notificationSettings)
}
}
In App delegate
import UIKit
import PushKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, PKPushRegistryDelegate {
var voipRegistry:PKPushRegistry!
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
registerForVoIPPushes()
return true
}
func registerForVoIPPushes() {
voipRegistry = PKPushRegistry(queue: dispatch_get_main_queue())
voipRegistry.delegate = self
voipRegistry.desiredPushTypes = Set([PKPushTypeVoIP])
print("VOIP Push registered")
}
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
let voipToken: String! = credentials.token.description
print("\n\n##### didUpdatePushCredentials: \n\n", voipToken)
**// update server with device token HERE**
}
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
print("\n\n## DID RECEIVE NOTIFICATION ## \n\n")
let data = payload.dictionaryPayload
let aps = data["aps"] as! [String: AnyObject]
let alert = aps["alert"] as! [String: AnyObject]
let localNotification = UILocalNotification()
//setup the notification
localNotification.alertBody = alert["body"] as? String
localNotification.alertTitle = alert["title"] as? String
localNotification.soundName = "Simple_ring_tone_29s.aiff"
localNotification.alertAction = alert["action-loc-key"] as? String
UIApplication.sharedApplication().applicationIconBadgeNumber = 1
//show the notification
UIApplication.sharedApplication().presentLocalNotificationNow(localNotification)
}
This worked for me, I hope that also work for you.
Still it is not good idea to do, this stuff has to be in appdelegate.
Please download code.
//
// ViewController.swift
// PushDemo
//
// Created by Hasya.Panchasra on 01/07/16.
// Copyright © 2016 bv. All rights reserved.
//
import UIKit
import PushKit
class ViewController: UIViewController,PKPushRegistryDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.PushKitRegistration()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: - PushKitRegistration
func PushKitRegistration()
{
let mainQueue = dispatch_get_main_queue()
// Create a push registry object
if #available(iOS 8.0, *) {
let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)
// Set the registry's delegate to self
voipRegistry.delegate = self
// Set the push type to VoIP
voipRegistry.desiredPushTypes = [PKPushTypeVoIP]
} else {
// Fallback on earlier versions
}
}
#available(iOS 8.0, *)
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
// Register VoIP push token (a property of PKPushCredentials) with server
let hexString : String = UnsafeBufferPointer<UInt8>(start: UnsafePointer(credentials.token.bytes),
count: credentials.token.length).map { String(format: "%02x", $0) }.joinWithSeparator("")
print(hexString)
}
#available(iOS 8.0, *)
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
// Process the received push
}
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let types: UIRemoteNotificationType = [.Alert, .Badge, .Sound]
application.registerForRemoteNotificationTypes(types)
return true
}
From the code you've posted, it seems the only place you call registerForVoIPPushes(), is in application(_:didFinishLaunchingWithOptions:)
Since registerForVoIPPushes() sets the voip registry delegate, you should probably also call it when the user gives permission for notifications.
According to this tutorial, registerUserNotificationSettings(userNotificationSettings) has a delegate callback application(_:didRegisterWithNotificationSettings:) you can use for this purpose:
func application(application: UIApplication, didRegisterUserNotifications notificationSettings: UIUserNotificationSettings)
{
// Check whether notifications are permitted
if notificationSettings != .None
{
print("Permission for notifications granted.")
registerForVoIPPushes()
}
}

Can't make push notification Work with Sinch

I'm trying to receive voip(and regular) push notification work on my app for sinch calls.
The code its already receiving calls when the app is in foreground.
And background with local nofitications
And the certificate for push is working sending pushes with pusher app in mac, i follow the tutorials and dont know what i'm missing
My code:
class AppDelegate: UIResponder, UIApplicationDelegate, SINCallClientDelegate, SINCallDelegate, SINMessageClientDelegate, SINClientDelegate, SINManagedPushDelegate {
var msgClient:SINMessageClient!
var window: UIWindow?
var applicationKey:String!
var applicationSecret:String!
var environmentHost:String!
var voipClient:SINClient!
var push:SINManagedPush!
func requestUserNotificationPermission() {
if UIApplication.sharedApplication().respondsToSelector("registerUserNotificationSettings:") {
let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
UIApplication.sharedApplication().registerForRemoteNotifications()
}
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
self.push.application(application, didReceiveRemoteNotification: userInfo)
}
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
self.handleLocalNotification(notification)
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
self.push.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
}
func startSinch() {
if self.voipClient == nil {
self.push.registerUserNotificationSettings()
let userID = "partner-4" //fixed for tests
self.voipClient = Sinch.clientWithApplicationKey(applicationKey, applicationSecret:applicationSecret,environmentHost:environmentHost,userId: userID)
self.voipClient.delegate = self;
//commented to test push but is working
//self.voipClient.setSupportActiveConnectionInBackground(true)
self.voipClient.enableManagedPushNotifications()
self.voipClient.setSupportCalling(true)
self.voipClient.setSupportMessaging(true);
self.voipClient.start()
self.voipClient.startListeningOnActiveConnection()
self.msgClient = self.voipClient.messageClient()
self.msgClient.delegate = self
}
}
func managedPush(managedPush: SINManagedPush!, didReceiveIncomingPushWithPayload payload: [NSObject : AnyObject]!, forType pushType: String!) {
self.handleRemoteNotification(payload)
}
func handleRemoteNotification(userInfo: NSDictionary){
if (self.voipClient == nil) {
self.startSinch()
}
self.voipClient.relayRemotePushNotification(userInfo as [NSObject : AnyObject])
}
func client(client: SINCallClient!, localNotificationForIncomingCall call: SINCall!) -> SINLocalNotification! {
let notification = SINLocalNotification()
notification.alertAction = "test"
notification.alertBody = "test"
notification.soundName = "notification-sound.caf"
return notification
}
func relayLocalNotification(notification: UILocalNotification) -> SINNotificationResult{
return self.voipClient.relayLocalNotification(notification)
}

Background Fetch, UILocalNotification and Apple Watch

I write an iPhone app with Apple Watch. My app should implement the background fetch mode and if there is new data, I send a UILocalNotification and I want my Apple Watch be able to display this notification.
The background fetch part and also the notification works both very well, but the notification is never display in my Apple Watch, even if my iPhone is in sleep mode.
But if I try the same thing but without background fetch, just scheduling a UILocalNotification each minute, all is ok and I can see my notification in my Apple Watch.
So I suppose there is an issue when the notification is sent from the "performFetchWithCompletionHandler" method, however I don't understand why and what I can do to correct this behaviour.
This is my code in my app delegate:
import UIKit
import Alamofire
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let settings = UIUserNotificationSettings.init(forTypes: UIUserNotificationType.Alert, categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
UIApplication.sharedApplication().setMinimumBackgroundFetchInterval(UIApplicationBackgroundFetchIntervalMinimum)
return true
}
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
print("App is registered to receive local notifications")
}
func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
print("########### Received Background Fetch ###########");
if isConnectedToNetwork() {
// Download the Content
let urlString = NSUserDefaults.standardUserDefaults().stringForKey(kServerUrl)
Alamofire.request(.GET, urlString!, parameters: nil)
.responseJSON() { response in
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
self.sendLocalNotification(JSON as! [String : String])
completionHandler(.NewData);
} else {
completionHandler(.NoData)
}
}
} else {
print("No Internet connection: unable to fetch data.")
completionHandler(.NoData)
}
}
private func sendLocalNotification(dictionary: [String: String]) {
let seatInfo = dictionary["seat"]
let seat = "Seat: \(seatInfo)"
let amountInfo = dictionary["amount"]
let amount = "Amount: \(amountInfo)"
let localNotification = UILocalNotification()
localNotification.fireDate = NSDate(timeIntervalSinceNow: 0)
localNotification.alertTitle = "New order"
localNotification.alertBody = seat + "\n" + amount
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
}
}
And here in my NotificationController.swift:
import WatchKit
import Foundation
class NotificationController: WKUserNotificationInterfaceController {
#IBOutlet var alertLabel : WKInterfaceLabel!
#IBOutlet var bodyLabel : WKInterfaceLabel!
override init() {
// Initialize variables here.
super.init()
// Configure interface objects here.
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
}
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
super.didDeactivate()
}
override func didReceiveLocalNotification(localNotification: UILocalNotification, withCompletion completionHandler: ((WKUserNotificationInterfaceType) -> Void)) {
self.alertLabel.setText(localNotification.alertTitle)
self.bodyLabel.setText(localNotification.alertBody)
completionHandler(.Custom)
}
}

IOS Swift: Load new url to a webview after receiving a push notification

I have a Swift 2.0 app with a webview and push notification.
The Webview is working every time the app starts.
After receving a push notifications, i need to call another url.
(to react on the push message)
How can I access the webview element in my appdelegate function didReceiveRemoteNotification ? Is this possible?
My Code so far:
ViewController:
class ViewController: UIViewController,UIWebViewDelegate {
#IBOutlet var containerView: UIView!
#IBOutlet var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
self.webView.delegate = self;
var urlStringHost = "http://www.exampleUrl.com"
let url = NSURL(string: urlStringHost)
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
webView.loadRequest(request)
}
Delegate:
// Push Empfangen
func application(application: UIApplication, didReceiveRemoteNotification userInfo:[NSObject : AnyObject]) {
print("push empfangen")
print(userInfo)
application.applicationIconBadgeNumber = 0
// Load some new url to the existing webview (not working)
//webview?.loadRequest(request)
}
Many Thanks.
By using NSNotificationCenter , you can do it.
First set notification and set selector in your viewcontroller.
func viewDidLoad()
{
super.viewDidLoad()
//add observer for load request in webview when receive remote notification.
NSNotificationCenter.defaultCenter().addObserver(self, selector:"PushReceiver:", name: "PushReceived", object: nil)
}
//When post notification then below method is called.
func PushReceiver(notifi: NSNotification)
{
var dicNotifi: [NSObject : AnyObject] = notifi.userInfo
NSLog("notificiation Info %# \n", dicNotifi)
}
When receive remote notification then post notification in didReceiveRemoteNotification method from AppDelegate Class.
func application(application: UIApplication, didReceiveRemoteNotification userInfo:[NSObject : AnyObject])
{
print("push empfangen")
print(userInfo)
application.applicationIconBadgeNumber = 0
//post notification.
NSNotificationCenter.defaultCenter().postNotificationName("PushReceived", object: nil, userInfo: userInfo)
}

Resources