I use this code:
let userInfo = notification.request.content.userInfo
let position = userInfo["TITLE"] as? NSString
completionHandler([.alert, .badge, .sound])
This code play default sound, but i want change it to system files mysound.mp3
How i can ?
To play a custom sound when notification received you will have to add sound key to your notification payload and sound file into xcode project.
Add files to the Xcode project root. Make sure Add to targets is selected when adding files so that they are automatically add to the bundle resources. Sound must be less than 30 seconds.
See below exapmple.
{
aps =
{
alert = "notification message";
sound = "example.wav";
};
}
Related
I saw UNNotificationAttachment does provide support on both image and audio.
Based on https://developer.apple.com/documentation/usernotifications/unnotificationattachment
Create a UNNotificationAttachment object when you want to include
audio, image, or video content together in an alert-based
notification.
Hence, I try to create 2 local notification (not push notification), which triggered by time. 1 notification has an image, another notification has an audio file (m4a)
However, I notice the image attachment does work well. It is showing as thumbnail on right.
But, there is nothing shown for the audio file attachment. I expect there will be an audio play button on right.
Here's how they look like
Am I doing something incorrect? Or, my expectation is wrong for the local notification's UNNotificationAttachment?
Here's my code which is using UNNotificationAttachment
if let attachment = litePlainNote.attachmentables.first {
source = attachment.url
identifier = "\(timestamp)-\(attachment.name)"
} else if let recording = litePlainNote.recordingables.first {
source = recording.url
identifier = "\(timestamp)-\(recording.name)"
}
if let source = source, let identifier = identifier {
let destination = UserDataDirectory.notification.url.appendingPathComponent(identifier)
do {
try FileManager.default.copyItem(at: source, to: destination)
let notificationAttachment = try UNNotificationAttachment(identifier: identifier, url: destination)
content.attachments.append(notificationAttachment)
} catch {
error_log(error)
}
}
May I know are you able to make audio file (m4a) workable with UNNotificationAttachment (Local notification)?
I moved step by step for getting rich push notifications. Here they are :
Created Notification service extension with plist :
NotificationService didRecieve :
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: #escaping (UNNotificationContent) -> Void) {
func failEarly() {
contentHandler(request.content)
}
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
// Get the custom data from the notification payload
if let data = request.content.userInfo as? [String: AnyObject] {
// Grab the attachment
// let notificationData = data["data"] as? [String: String]
if let urlString = data["attachment-url"], let fileUrl = URL(string: urlString as! String) {
// Download the attachment
URLSession.shared.downloadTask(with: fileUrl) { (location, response, error) in
if let location = location {
// Move temporary file to remove .tmp extension
let tmpDirectory = NSTemporaryDirectory()
let tmpFile = "file://".appending(tmpDirectory).appending(fileUrl.lastPathComponent)
let tmpUrl = URL(string: tmpFile)!
try! FileManager.default.moveItem(at: location, to: tmpUrl)
// Add the attachment to the notification content
if let attachment = try? UNNotificationAttachment(identifier: "video", url: tmpUrl, options:nil) {
self.bestAttemptContent?.attachments = [attachment]
}else if let attachment = try? UNNotificationAttachment(identifier: "image", url: tmpUrl, options:nil) {
self.bestAttemptContent?.attachments = [attachment]
}else if let attachment = try? UNNotificationAttachment(identifier: "audio", url: tmpUrl, options:nil) {
self.bestAttemptContent?.attachments = [attachment]
}else if let attachment = try? UNNotificationAttachment(identifier: "image.gif", url: tmpUrl, options: nil) {
self.bestAttemptContent?.attachments = [attachment]
}
}
// Serve the notification content
self.contentHandler!(self.bestAttemptContent!)
}.resume()
}
}
}
Configured AppId and provision profile for extension.
Rich notification is coming correctly :
But here are the issues I am facing :
didRecieve is not getting called. For that I attached the serviceExtension process to the app target and ran the app.
Note : Extension is getting called as soon as notification arrives but didRecieve is not called :
On opening the push notification (which has video attachment), nothing happens. Ideally it should get played.
If I have to open the video and play it, do I have to explicitly do something or extension will take care of that ?
Payload :
aps = {
alert = "This is what your message will look like! Type in your message in the text area and get a preview right here";
badge = 1;
"mutable-content" = 1;
sound = default;
};
"attachment-url" = "https://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4";
deeplinkurl = "";
"message_id" = 1609;
}
I did try going through following posts but that didn't help :
iOS10 UNNotificationServiceExtension not called
NotificationServiceExtension not called
UNNotificationServiceExtension not working on iPhone 5 (iOS 10)
Good news! Your service extension is indeed being called - the image on your notification is evidence of that. What is probably happening here is that you are unable to debug the extension using the workflow you are used to with applications.
Debugging notification extensions is not like debugging an app. Extensions are plug-ins to an iOS process outside your application. Just setting a breakpoint is not a reliable way to debug them. Instead:
Debugging A Notification Service Extension
Launch the app from Xcode or the device
In Xcode, select Attach To Process or PID By Name... from the Debug menu
Enter the name of your notification extension
Trigger a notification (by sending a push, etc.).
When the notification is delivered the service extension should launch in to the debugger. Service extensions are only relevant to remote (push) notifications, so you will need a device to troubleshoot them.
Debugging A Notification Content Extension
There are at least two ways. The steps shown above for a service extension also work for a content extension. The second method is more familiar but less reliable.
Select the extension scheme in Xcode using the toolbar
In the Product menu, select Edit Scheme...
Set the Executable to the parent application.
Set a breakpoint inside the content extension.
Now build and run your extension. It will launch the parent application.
Trigger a notification that will cause the content extension to load.
It's worth noting that adding logging using the logging framework can be very useful for debugging and troubleshooting as well.
Why The Video May Not Be Playing
iOS limits the size of content that can be presented in notifications. This is described in the documentation for UNNotificationAttachment. For video it is generally 50Mb. Make sure your video is as small as you can make it in terms of bytes, and of course provide a video that is sized appropriately for the device it will be played on. Do not try to play a 1080p video in a notification that is 400 points wide!
In practice it is almost always better to use HLS instead of downloading video, and present it in a content extension.
Another thing in your code that may be problematic is the identifiers you are assigning to your attachments. Identifiers should be unique. Typically this would be a reverse-domain notation string like your bundle ID followed by a UUID string. You could also use the original URL of the content followed by a UUID string. If you provide an empty string iOS will create a unique identifier for you.
With the user notifications framework having non-unique identifiers (for notifications, attachments, etc.) tends to cause difficult to track down issues inside the framework. For example, this can cause an attached watchOS device to crash.
If you want to implement "auto play" for your video - it is not clear from your question wether that is what you are describing - you will need to implement your own player functionality in a content extension.
If you are going to do that, again, HLS is the preferred way to display video in a notification. It usually uses less RAM, offers a better user experience and tends to be more stable.
Since UILocalNotification is deprecated in iOS 10 so I have updated my local notification flow using the UNUserNotification framework.
The app plays custom sound using AVPlayer when the app is in the foreground and it works fine. But in background mode when local notification is triggered, instead of custom sound, a default notification sound is being played.
However, things were working fine in iOS9, using "didReceiveLocalNotification" method app can play custom sound even in background mode.
Update 1:
I'm setting local notification as follows:
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationStringForKey("reminder!", arguments: nil)
content.body = NSString.localizedUserNotificationStringForKey("Reminder body.", arguments: nil)
if let audioUrl == nil {
content.sound = UNNotificationSound.defaultSound()
} else {
let alertSound = NSURL(fileURLWithPath: self.selectedAudioFilePath)
content.sound = UNNotificationSound(named: alertSound.lastPathComponent!)
}
content.userInfo = infoDic as [NSObject : AnyObject]
content.badge = 1
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 60, repeats: false)
let identifier = "Reminder-\(date)"
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
let center = UNUserNotificationCenter.currentNotificationCenter()
center.addNotificationRequest(request, withCompletionHandler: { (error) in
if error != nil {
print("local notification created successfully.")
}
})
I have already gone through many SO Questions but didn't get the solution.
Any help will be greatly appreciated!
In Swift 4.2 and Xcode 10.1
For local notifications to play sound
let content = UNMutableNotificationContent()
content.title = "Notification Tutorial"
content.subtitle = "from ioscreator.com"
content.body = " Notification triggered"
//Default sound
content.sound = UNNotificationSound.default
//Play custom sound
content.sound = UNNotificationSound(named:UNNotificationSoundName(rawValue: "123.mp3"))
"123.mp3" file needs to be in your Bundle.
Found out that alertSound doesn't have the correct file path hence the content.sound sets nothing. I was saving the recorded file in documents directory and the file path retrieve for real device is different as compared to the simulator.
Setting a sound file which is placed in project bundle did the trick
content.sound = UNNotificationSound(named: "out.caf")
In your push notification package you need to include the custom sound you want to play in the background. This sound needs to be included in your application too.
For example, here is how I create a custom notification package in PHP for iOS. Notice in my notification object I have a sound object.
array("to" => $sDeviceID,
"data" => array($sMessageType => $sMessage,
"customtitle" => $sMessageTitle,
"custombody" => $sMessage,
"customimage" => "$mIcon") ,
"notification" => array("title" => "sMessageTitle",
"text" => $sMessage,
"icon" => "$mIcon",
"sound" => "mySound.mp3"));
Here is how to create a notification using the UserNotifications framework with a custom sound.
If notification is your UNNotificationContent and the name of your custom media file that is in your bundle is a.mp4, just use the following code:
notification.sound = UNNotificationSound(named: "a.mp4")
So, you don't need to use didRecieveLocalNotification.
I understand that
let notificationContent = UNMutableNotificationContent()
...
notificationContent.sound = UNNotificationSound(named: "out.mp3")
is working fine, but:
1) the sound file should not be longer than 30 sec (which is ok, I think)
2) the sound file has to be part of the Bundle.mail files. If it is stored somewhere else the notification will not have access to it, when in background. It works fine in foreground. Apple does not provide permission to access other folders as far as I know.
3) there are restrictions on the sound format. Please refer to Apple guides
4) I'm not sure if sound files in Bundle.main can be changed
programmatically. For example: I wrote a routine which extracts 30 sec of a song stored in apple music and chosen by the user... everything works fine, if the info is stored in a different directory, but only in foreground... once locked or in background there is no access to it. I'm not able to change/overwrite a file in Bundle.main. If that would be possible the problem would be solved ... but I think that would be a security issue. I conclude that alert sounds and music are working fine as long as the above is met.
let notificationContent1 = UNMutableNotificationContent()
notificationContent1.title = "Good morning! Would you like to listen to a morning meditation to start the day fresh ? Or maybe a cool relaxing soundscape? Open the app and browse our collection which is updated daily."
notificationContent1.subtitle = ""
notificationContent1.body = ""
notificationContent1.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: "AlarmSound.wav"))
var dateComponents1 = DateComponents()
dateComponents1.hour = 08
dateComponents1.minute = 00
let trigger1 = UNCalendarNotificationTrigger(dateMatching: dateComponents1, repeats: true)
let request1 = UNNotificationRequest(
identifier: UUID().uuidString,
content: notificationContent1,
trigger: trigger1
)
let notificationContent2 = UNMutableNotificationContent()
notificationContent2.title = "Good evening! Hope you had a great day. Would you like to meditate on a particular topic ? Or just some relaxing sleep sounds ? Open the app and pick what you want so you can go to sleep relaxed."
notificationContent2.subtitle = ""
notificationContent2.body = ""
notificationContent2.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: "AlarmSound.wav"))
var dateComponents2 = DateComponents()
dateComponents2.hour = 20
dateComponents2.minute = 00
let trigger2 = UNCalendarNotificationTrigger(dateMatching: dateComponents2, repeats: true)
let request2 = UNNotificationRequest(
identifier: UUID().uuidString,
content: notificationContent2,
trigger: trigger2
)
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().add(request1, withCompletionHandler: nil)
UNUserNotificationCenter.current().add(request2, withCompletionHandler: nil)
iOS 10 introduced push notification framework updates,
UserNotificationsUI.framework
As written on apple docs, it lets us customize the appearance of local and remote notifications when they appear on the user’s device.
So if anyone have idea how to display image in push notification when on lock screen. same like andorid push notification are doing.
Thanks,
If you want to customize the appearance of local and remote notifications, perform the following steps:
Create a UNNotificationCategory and add to the UNUserNotificationCenter category:
let newCategory = UNNotificationCategory(identifier: "newCategory",
actions: [ action ],
minimalActions: [ action ],
intentIdentifiers: [],
options: [])
let center = UNUserNotificationCenter.current()
center.setNotificationCategories([newCategory])
Create a UNNotificationContentExtension:
then use code or storyboard to customize your UIViewController.
Add category to UNNotificationContentExtension's plist:
4.Push Notification
Local Notification
Create a UNMutableNotificationContent and set the categoryIdentifier to "newCategory" which includes UNUserNotificationCenter's categories and UNNotificationContentExtension's plist:
let content = UNMutableNotificationContent()
content.title = ...
content.body = ...
content.categoryIdentifier = "newCategory"
let request = UNNotificationRequest.init(identifier: "newNotificationRequest", content: content, trigger: nil)
let center = UNUserNotificationCenter.current()
center.add(request)
Remote Notification
Set "mutable-content : 1" and "category : newCategory". Note that the category value is set to "newCategory" which matches what you previously added to UNUserNotificationCenter and UNNotificationContentExtensions plist.
Example:
{
"aps" : {
"alert" : {
"title" : "title",
"body" : "Your message Here"
},
"mutable-content" : "1",
"category" : "newCategory"
},
"otherCustomURL" : "http://www.xxx.jpg"
}
Note: you need a device or simulator which supports 3DTouch, otherwise you can't show a custom UNNotificationContentExtension viewcontroller.(In iOS10 Beta1, it`s not work. But now this work without 3d touch)
And ... if you just want to show an image on a push notification displayed on the lock screen, you need to add UNNotificationAttachment:
let content = UNMutableNotificationContent()
content.title = ...
content.body = ...
content.categoryIdentifier = "newCategory"
let fileURL: URL = ... // your disk file url, support image, audio, movie
let attachement = try? UNNotificationAttachment(identifier: "attachment", url: fileURL, options: nil)
content.attachments = [attachement!]
let request = UNNotificationRequest.init(identifier: "newNotificationRequest", content: content, trigger: nil)
let center = UNUserNotificationCenter.current()
center.add(request)
For more detail feature,Demo
Actually if you are setting up a local notification and you're just interested in having an image show up in the notification itself, you don't have to bother with NotificationsUI.framework or UNNotificationContentExtensions at all. That is only useful if you want a custom UI when the user 3D touches or expands the notification.
To add an image that is already on the device (either shipped with the app, or generated/stored by the app at some point before the notification is created), then you only need to add a UNNotificationAttachment with a file URL where the path ends in .png (or .jpg will likely work too?). Something like this:
UNMutableNotificationContent *content = [UNMutableNotificationContent new];
content.title = #"Title";
content.body = #"Body";
content.sound = [UNNotificationSound defaultSound];
NSURL *imageURL = [NSURL URLWithString:#"file:/some/path/in/app/image.png"];
NSError *error;
UNNotificationAttachment *icon = [UNNotificationAttachment attachmentWithIdentifier:#"image" URL:imageURL options:nil error:&error];
if (error)
{
NSLog(#"error while storing image attachment in notification: %#", error);
}
if (icon)
{
content.attachments = #[icon];
}
Then when the notification appears, the image will show up on the right-hand side of the notification banner like it does for Messages notifications. And you don't have to jump through all of the hoops of setting up a content extension with a categoryIdentifier, etc.
EDIT: Updated to add that this is only a valid solution for local notifications.
You have to do some work on creating push notification and also when you are handling.
When you creating payload you need to add extra attribute attachment, something like below:
{
aps : {
alert: { },
mutable-content:1
}
my-attachment = "url to resource"
}
When you receive notification system will call didReceive method of service extension, override notification extension didReceive method like this
public func didReceive(_ request:UNNotificationRequest, withContentHandler contentHandler:(UNNotificatinContent) -> Void) {
let fileUrl = //
let attachment = UNNotificationAttachment(identifier : "image", url: fileUrl, options: nil)
let content = request.content.mutableCopy as! UNMutableNotificationContent
content.attachment = [attachment]
contentHandler(content)
}
Here is WWDC video talk on this topic.
Implement your notification's custom view using a UIViewController that conforms to UNNotificationContentExtension.
See https://developer.apple.com/reference/usernotificationsui/unnotificationcontentextension
I'm trying to create a notification with an action on the Apple Watch. However the documentation is not really saying what is native and what should be made.
Currently I'm creating a UILocalNotification on the iPhone. However what I'm wondering is that the action button will be mirrored on the Apple Watch.
The code I'm using to create the notification on the iPhone is:
let incrementAction = UIMutableUserNotificationAction()
incrementAction.identifier = "OPEN_ACTION"
incrementAction.title = "Open"
incrementAction.activationMode = UIUserNotificationActivationMode.Background
incrementAction.authenticationRequired = false
incrementAction.destructive = false
let counterCategory = UIMutableUserNotificationCategory()
counterCategory.identifier = "SLAGBOOM_CATEGORY"
counterCategory.setActions([incrementAction],
forContext: UIUserNotificationActionContext.Default)
counterCategory.setActions([incrementAction],
forContext: UIUserNotificationActionContext.Minimal)
let types = UIUserNotificationType.Alert
let settings = UIUserNotificationSettings(forTypes: types, categories: NSSet(object: counterCategory) as? Set<UIUserNotificationCategory>)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
let notification:UILocalNotification = UILocalNotification()
notification.alertBody = message
notification.category = "SLAGBOOM_CATEGORY"
UIApplication.sharedApplication().scheduleLocalNotification(notification)
Am I supposed to do anything to make sure the button will work on the Apple Watch? Or do I need to create a watchkit app only for a notification?
You get default notifications for free but the users only option is to dismiss it.
If you want something custom then you want to create your own watch target and build out the different notification views in the watch targets storyboard
Here's the page on Apple's Watch Programming Kit the explains the different custom notifications you can make