I am using Azure Notification Hub to send remote notifications, at the moment only to iOS.
I initially realised that my device was receiving 5 notifications of the same notification event. I checked and debugged my code and it indeed correctly checks if the provided token to register is not already registered.
I then checked my database and realised that I do not have duplicates, but 5 different device tokens for the one device and user account. They each had been generated every-time I uninstall and then re-install the app on my device.
Given that, I would think that when an app is uninstalled, the token generated before is made invalid by Apples systems? I assumed this because upon re-installation, a new token is generated, different to the previous one. Why would the older tokens remain valid; whats the use case for such.
It seems other people are having this issue for iOS development, including Android too.
Using VendorId to identify a device is proving pointless, as some are finding out, that it also changes upon fresh installation. When I uninstall the app and reinstall I get a new vendorId plus a new notification token, leaving the previous ones still valid, opening up the ability to receive multiple of one instance of a notification (since the back end cannot match the new two values to anything existing in the database).
Any advice on this please? I am absolutely lost on this?
Update: I certainly need a user to have more than one device token at a time, in case they are logged in on multiple devices.
You are basically going to have to identify a device yourself, by saving an ID, using UUID, into Keychain. Keychain because the data persists over multiple installs.
Below is a quick rushed implementation using Locksmith:
import UIKit
import Locksmith
class Keychain
{
private static let AccountName = "MyAppName";
private static let CustomDeviceIdKey = "CustomDeviceIdKey";
private static func AccountData() -> Dictionary<String, Any>?
{
return Locksmith.loadDataForUserAccount(userAccount: AccountName)
}
private static func GenerateCustomDeviceId() -> Bool
{
do{
try Locksmith.saveData(data: [CustomDeviceIdKey: UUID().uuidString], forUserAccount: AccountName)
return true
}catch{
print("Failed to save custom device id: \(error.localizedDescription)")
return false
}
}
static func CustomDeviceId() -> String
{
let data = AccountData()
if let result = data?[CustomDeviceIdKey] as? String{
return result
}else{
if GenerateCustomDeviceId(){
return CustomDeviceId()
}
return ""
}
}
}
And then later you just go:
func SomeMethodThatNeedsDeviceId(){
var customDeviceIdThatPersistsOverInstalls = Keychain.CustomDeviceId()
}
And that is what you use in place of VendorId