Hello,
I have added a notification service extension and content extension to an existing app. The service extension downloads a video file, using the url passed in an APNS push notification. It is then attached to the notification. The content extension passes the attachment url to AVPlayer, so the video is played inside the notification if the user decides to view it. So far, so good.
Now I would like to save the downloaded video files for viewing in the main app, inside a table view. For this, I created an app group, enabled the app group capability for both the main target and the content service extension, and selected the app group within the capability, again for both. Then, instead of saving the file to the temp directory in the service extension, I moved the downloaded file to the app group shared container:
let groupDirectoryUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.net.mydomain.myapp")!
let groupPathUrl = groupDirectoryUrl.appendingPathComponent("Library/Caches/myapp") // added this later to see if it would work from within the Caches directory
let groupPath = groupPathUrl.path
// Code snipped, creating myapp folder if it does not exist
do {
try FileManager.default.moveItem(at: location, to: groupFileUrl) // location is the url of the downloaded file
self.tmpLogger.addLogEntry(severity: 5, "<File copied to>: \(groupFileUrl)") // This is so I can view log entries from within my app
if (FileManager.default.fileExists(atPath: groupFileUrl.path)) { // Temporary code to double check the file's existence
self.tmpLogger.addLogEntry(severity: 5, "<File now exists>: " + groupFileUrl.path)
}
} catch let error {
bestAttemptContent.title = "\(bestAttemptContent.title) <FILE MOVE ERR>" // So the error will be visible in the notification, for debug
bestAttemptContent.body = "\(bestAttemptContent.body) \(error.localizedDescription)"
self.tmpLogger.addLogEntry(severity: 1, "<File move error>: \(error.localizedDescription)")
}
No problem here, moving the file works. But here's the thing, it is not visible from the main app. In the table view controller:
let documentDirectoryUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.net.mydomain.myapp")!
let fileNameOnly = NSString(string: mediaEntry.fileName!).lastPathComponent //mediaEntry is CoreData, containing the url of the saved file. CoreData works
let storagePathUrl = documentDirectoryUrl.appendingPathComponent("Library/Caches/myapp")
let fileName = storagePathUrl.absoluteString.appending(fileNameOnly)
let url = URL(string: fileName)!
MyLogger().addLogEntry(severity: 5, "Filename: " + url.path)
if (FileManager.default.fileExists(atPath: url.path)) {
// This part of the code is never reached, the file never exists
I have updated the table view code to re-download the video file if it does not exist in the shared container, and store it in the same location. So as it stands now, from the main app, when a video event is selected, the video is downloaded and saved to the shared container, and can then be viewed. This will persist, so it can be viewed many times, but will be downloaded only once.
I've put in some code to display the contents from within the notification content extension. The files that are downloaded in the main app are not visible in the extension. So, although there's no errors when accessing the shared container, the two programs cannot see eachother's data.
I know there is at least one app extension that is not allowed to access shared data, but didn't find any information that this is the case for the notification service. Any thoughts?