When a user is in a Facetime call and accepted the SharePlay request, I want to push a specific ViewController
. So I thought it would be same as to get notification when the user tap "accept".
import UIKit
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// to perform action when notification is tapped
UNUserNotificationCenter.current().delegate = self
registerForPushNotifications()
return true
}
func registerForPushNotifications() {
UNUserNotificationCenter.current()
.requestAuthorization(options: [.alert, .sound, .badge]) {
[weak self] granted, error in
print("Permission granted: \(granted)")
guard granted else { return }
self?.getNotificationSettings()
}
}
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { settings in
print("Notification settings: \(settings)")
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
extension AppDelegate : UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let application = UIApplication.shared
if(application.applicationState == .active){
print("user tapped the notification bar when the app is in foreground")
}
if(application.applicationState == .inactive)
{
print("user tapped the notification bar when the app is in background")
}
guard let rootViewController = (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.window?.rootViewController else {
return
}
// Do some work
completionHandler()
}
}
But this was not the case. Nothing were printed out in the logs. Is there another way to know when the app (in the background or terminated) is launched or openend by accepting a SharePlay request ?
So if one accepts the SharePlay request, one will join a session. After that you can switch to a specific ViewController. You can call this function for example in
func sceneWillEnterForeground(_ scene: UIScene) {
if #available(iOS 15, *) {
let _ = CoordinationManager.shared
}
}
and the CoordinationManager could look like this
class CoordinationManager {
static let shared = CoordinationManager()
private var subscriptions = Set<AnyCancellable>()
// Published values that the player, and other UI items, observe
@Published var groupSession: GroupSession<MovieWatchingActivity>?
@Published var enquedMovie: Movies?
private init() {
Task {
// await new sessions to watch movies together
for await groupSession in MovieWatchingActivity.sessions() {
//set the app's active group session
self.groupSession = groupSession
//remove previous subscriptions
subscriptions.removeAll()
//observe changes to the session state
groupSession.$state.sink { [weak self] state in
if case .invalidated = state {
// set the groupSession to nil to publish
// the invalidated session state
self?.groupSession = nil
self?.subscriptions.removeAll()
}
}.store(in: &subscriptions)
// join the session to participate in playback coordination
groupSession.join()
// navigate user to correct view controller to show videos
guard let windowScene = await UIApplication.shared.connectedScenes.first as? UIWindowScene,
let sceneDelegate = await windowScene.delegate as? SceneDelegate,
let navigationController = await sceneDelegate.window?.rootViewController as? UINavigationController else {
return
}
DispatchQueue.main.async {
navigationController.pushViewController(GroupMovieController(), animated: true)
}
// observe when the local user or a remote participant starts an activity
groupSession.$activity.sink { [weak self] activity in
// set the movie to enqueue it in the player
self?.enquedMovie = activity.movie
}.store(in: &subscriptions)
}
}
}
...
}