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
Related
I'm slightly confused about the difference between "normal" push notifications vs. remote notifications, as well as which of them is possible with my free provisioning profile.
I'm able to send push notifications that appear on lock-screen with the following code:
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
...
registerForPushNotifications()
createNotification()
return true
}
func registerForPushNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { [weak self] granted, _ in
print("Permission granted: \(granted)")
guard granted else { return }
}
}
static func createNotification() {
let content = UNMutableNotificationContent()
content.title = "test-title"
// 2. create trigger
var components = DateComponents.init()
components.hour = 14
components.minute = 39
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: false)
content.badge = 1
content.sound = UNNotificationSound.default
// 4. create send request
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
// add request to send center
UNUserNotificationCenter.current().add(request) { error in
if error == nil {
print("Time Interval Notification scheduled!")
}
}
}
However, what I really want is to create a daily notification that is based on some HTTP request.
In other words, I would like to send an HTTP request to some API (say it returns a boolean value) and create a notification based on that value.
I've done some research and I think that remote notifications are capable of doing so.
Unfortunately, when I try to register for remote notifications:
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
I get an error: no valid “aps-environment” entitlement string found for application.
As I've stated - I do not have a paid Apple developer membership.
My questions are:
will remote notifications actually fulfill my needs?
Are remote notifications possible with free provisioning account?
I've found that "normal" push notifications are indeed possible.
Thanks!
It seems you have a misunderstanding about how remote push notifications work. Your server needs to schedule the remote notifications, not your app. You can schedule a daily remote notification on your server, which should suffice your needs, but as I've said, you'll need server-side logic to achieve this.
No - you need a paid developer membership to be able to use remote push notifications. Local notifications require no paid membership, but remote ones do.
I'm pretty sure I already know what the outcome of this attempt is going to be, but before I start going through a lot of effort for nothing, I should probably just ask someone about this. Here's what I want to try:
I'm developing an iOS app in Swift, and I just wrote a PHP script to send a silent push notification to my device. In this silent notification, I'm passing along instructions to have my app delegate open the app using the UIApplication.shared.openURL(url:) method. This PHP script will only be run if a user taps a certain button on an online web page, which can only be accessed when the user is using Safari web browser on his iPhone device with my app already running in the background, so there's no chance that anyone will be able to trigger the PHP script from any other device than an iPhone which already has my app installed and running in the background. If you're wondering why I would use this workaround while I can also just use something as simple as URL schemes or deep linking, well, it's quite simple: first of all, deep linking requires the user to confirm that he wants my app to open before it actually opens. I don't want this, instead, I want my app to open automatically as soon as the button is tapped. Second, after the app is opened through deep linking or universal links, there's this really annoying breadcrumb button in the status bar, which shouldn't be there anymore after my user transitions from the web page to my app. I've tried everything to get rid of the confirmation prompt and breadcrumb button, and this is the last thing I can come up with. Is it possible to trigger the openURL method using a remote notification, even when the app is already open and running in the background?
you can't open / bring to foreground an app without user interaction
You can use silent push notification ( Pushkit ).
It will also work in background and with app terminated mode.
Once you receive silent push notification, you have to schedule local notification with interactive buttons in notification.
As per user tap, your app will be open and with tracking on didFinishLaunchingWithOption you can open specific URL
Note - Without user interaction, you would not be able to open specific URL in safari.
You can refer below code for same.
import UIKit
import PushKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate,PKPushRegistryDelegate {
var window: UIWindow?
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
}
}
Refer some more material for push kit integration.
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.
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
}
I am currently using OneSignal for notification service to my app.I really need a help with accessing notification additionaldata(payload data) from AppDelegate inside didFinishLunchingWithOption where OneSignal API can give me like this.
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var data : [NSObject : AnyObject]!
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let oneSignal = OneSignal(launchOptions: launchOptions, appId: "48755d3d-abc0-4bac-8f71-095729bb3a65") { (message, additionalData, isActive) in
NSLog("OneSignal Notification opened:\nMessage: %#", message)
if additionalData != nil {
NSLog("additionalData: %#", additionalData)
self.data = additionalData
print(self.data)
}
}
oneSignal.enableInAppAlertNotification(true)
return true
}
}
but,I can only get the data if user click notification when appear or open it from notification center.So,if user neglect that notification without tapping when appear or without swiping or tapping from notification center,how do i get the additional data?
Actually,I want to store all payload data every time it comes into my device at realm database and fetch the data from my server according to that payload data.
You should use application(_:didReceiveRemoteNotification:fetchCompletionHandler:).
If you have enabled remote notifications background mode most of your notifications will be delivered even if the app is not running in the foreground. The only caveat being that the app must have been launched (since notifications are being pushed the user has done this) and it mustn't have been force-quit by the user.
More info in Apple's docs about that specific method.
Or in the "Local and Remote Notification Programming Guide's" notification handling chapter
You can extract all the payload in did finishLaunching by following method..
Let data = launchOptions.objectForKey(UIApplicationLaunchOptionsUIApplicationLaunchOptionsRemoteNotificationUIApplicationLaunchOptionsUIApplicationLaunchOptionsRemoteNotificationKey)