I am working on an App Clip and I would like to receive push notifications from my server. In my regular app, this functionality works fine. However, in the App Clip, I am unable to receive the device token. I suspect there might be something wrong with my implementation.
I have the following code in my AppDelegate:
class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
print("Device Token: \(token)")
Task{
await NotificationManager.shared.sendTokenToServer(token: token)
}
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Failed to register for notifications: \(error)")
}
}
I have enabled push notifications in the App Clip target, and when I launch the App Clip, I do receive a prompt asking for permission to allow notifications. However, even after granting permission, I am still not able to receive the device token.
Additionally, here is the code for my NotificationManager class:
class NotificationManager: NSObject, ObservableObject, UNUserNotificationCenterDelegate {
@Published var token: String?
static let shared = NotificationManager()
override init() {
super.init()
UNUserNotificationCenter.current().delegate = self
}
func requestAuthorization() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
if granted {
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
}
func sendTokenToServer(token: String) async {
let url = URL(string: "\(APIConfig.baseURL)/api/device-token")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
do {
let deviceToken = await FirebaseTokenManager.shared.getToken()
if let deviceToken = deviceToken {
request.setValue("\(deviceToken)", forHTTPHeaderField: "Authorization")
}
let bodyData: [String: Any] = [
"os": "ios", // Stel hier het juiste besturingssysteem in (ios of android)
"bundle_id": Bundle.main.bundleIdentifier ?? "", // Voeg hier de bundle ID van je iOS-app toe
"device_token": token
]
request.httpBody = try JSONSerialization.data(withJSONObject: bodyData)
let (data, response) = try await URLSession.shared.data(for: request)
if let httpResponse = response as? HTTPURLResponse {
print("HTTP status code: \(httpResponse.statusCode)")
if (200...299).contains(httpResponse.statusCode) {
// Succesvolle response
let decoder = JSONDecoder()
let apiResponse = try decoder.decode(APICallResponse.self, from: data)
print("Success: \(apiResponse.message)")
} else {
// Foutieve response
let decoder = JSONDecoder()
let errorResponse = try decoder.decode(ErrorResponse.self, from: data)
print("Error: \(errorResponse.message)")
}
}
} catch {
print("Error: \(error)")
}
}
}
In this code, I'm checking the notification settings using UNUserNotificationCenter.current().getNotificationSettings, and if the authorization status is .ephemeral or .authorized, I call notificationManager.requestAuthorization() to request notification permission.
.onAppear {
activityManager.startCameraActivity(eventName: authenticationViewModel.event?.name ?? "", photosLeft: authenticationViewModel.photosLeft , photosTotal: authenticationViewModel.photoLimit)
let center = UNUserNotificationCenter.current()
center.getNotificationSettings { (settings) in
if settings.authorizationStatus == .ephemeral {
notificationManager.requestAuthorization()
}
if settings.authorizationStatus == .authorized {
notificationManager.requestAuthorization()
}
}
}
Please note that I am unable to enable background modes for the App Clip because that option is not available. Could this be the cause of the issue? Is there any alternative approach I can take to receive the device token in the App Clip?