I have to implement a UDID-like string for my application.
Therefore I used identifierForVendor to make a unique ID for my app and saved it to keychain with SSKeychain, in case it is changed each time the user reinstalls my application.
For each time I have to use the identifier, I will check in keychain whether if it's existed or I create and save one:
-(NSString *)getUniqueDeviceIdentifierAsString
{
NSString *strApplicationUUID = [SSKeychain passwordForService:self.appName account:#"myapp"];
if (strApplicationUUID == nil)
{
strApplicationUUID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
[SSKeychain setPassword:strApplicationUUID forService:self.appName account:#"myapp"];
}
return strApplicationUUID;
}
I'm just afraid that the ID will be synced across user's devices then it couldn't be "UDID-like" anymore.
I wonder if this is a good practice for my app?
Related
This question already has answers here:
iOS unique user identifier [duplicate]
(7 answers)
Closed 5 years ago.
Is there a way to identify a device even after having uninstalled an app and reinstalling again? I found topics where it's possible to get a UUID but it seems that after uninstalling the app the value of the UUID changes
The value in this property remains the same while the app (or another
app from the same vendor) is installed on the iOS device. The value
changes when the user deletes all of that vendor’s apps from the
device and subsequently reinstalls one or more of them.
I installed an App called Jodel, you don't have to create an Account to use the app and After uninstalling it, delete iCloud data, logging out from iCloud... an reinstalling it I was still logged in in the App. I assume they use a unique device identifier? Do you have an idea how such mechanism could be implemented?
You can use Keychain Service to store data still after uninstalling app from device.
for more reference about keychain service check this
https://developer.apple.com/documentation/security/keychain_services
Yes, It's Possible
#import "UICKeyChainStore.h"
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self getDeviceIdFromKeychain];
}
- (void)getDeviceIdFromKeychain
{
NSString *deviceID = [UICKeyChainStore stringForKey:#"KEY TO SAVE TO Keychain" service:nil];
// if vandorid from keychain is not nil
if (deviceID)
{
[[NSUserDefaults standardUserDefaults] setObject:deviceID forKey:#"deviceID"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
// else it goes for new vendorid and then stored it to keychan
else if (deviceID == (id)[NSNull null] || deviceID.length == 0 )
{
deviceID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
[UICKeyChainStore setString:deviceID forKey:#"KEY TO SAVE TO Keychain" service:nil];
[[NSUserDefaults standardUserDefaults] setObject:deviceID forKey:#"deviceID"];
[[NSUserDefaults standardUserDefaults] synchronize];
// NSLog(#"VendorID Local - %#",deviceID);
}
}
ViewContoller.m
- (void)viewDidLoad
{
NSString *strDeviceId = [[NSUserDefaults standardUserDefaults]objectForKey:#"deviceID"];
}
I wanted to know that How to generate Unique ID of device for iPhone/iPad using Objective-c
so that once application is installed on device , so we should track that deviceID
I have searched to retrieve IMEI of iPhone/iPad , but it is not allowed in objective-c.
Then I searched to generate UDID of iPhone/iPad but it is generating for different ID each time I launched it on simulator .
Yes, UDID is deprecated; we are not allowed to get UDID due to user privacy purposes. Apple does not allow to get any identifiers that uniquely identifies a device, such as IMEI, MAC address, UDID etc.
UUID is the best way to go as of now. But that would be unique for each vendor. You are not assured that it will be unique each time you get the UUID string. Best bet is to store the UUID string to phone's Keychain and retrieve it when needed, with a catch. When you factory-reset your phone, the keychain items would be erased. This limitation should be kept in mind.
UPDATE - IN IOS 10.3 BETA'S:
It seems that Apple has made some changes to how Keychain works in iOS 10.3+. Keychain items stored in the Keychain will be deleted when the all the apps from the specific vendor are uninstalled. According to Apple, the residence of sensitive information of an app even after the app is gone from the device may lead to security risks, so they decided to forbid this kind of behavior.
Developers relying on Keychain storage even after an uninstall for their apps can make use of this WORKAROUND to continue with the intended functionality. According to this workaround, any app can access the information stored in that specific Keychain Access Group, so it is recommended that adding an extra layer of encryption to your data will protect it with even more security, although keychain encrypts items by default.
UPDATE - IOS 10.3.3 (STABLE):
It seems that the keychain items deletion was a BUG in early betas of iOS 10.3.3 and was fixed later in the stable release. This might have been caused during betas since strange things can happen during that phase. It should be no problem to use Keychain hereafter.
You can use UUID (Universal User Identification). Following link contains apple documentation
https://developer.apple.com/reference/uikit/uidevice/1620059-identifierforvendor
https://developer.apple.com/library/content/releasenotes/General/WhatsNewIniOS/Articles/iOS7.html#//apple_ref/doc/uid/TP40013162-SW1
you can use this code for UUID:
//Objective-C
NSString * string = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
//Swift
let deviceID = UIDevice.currentDevice().identifierForVendor?.UUIDString
//Swift 3
let deviceID = UIDevice.current.identifierForVendor?.uuidString
Use the below code to get UDID for iOS device
Use KeychainItemWrapper Class download from URL
KeychainItemWrap
NSString *uuid;
KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:#"AC_APP_UUID" accessGroup:nil];
NSString *keychainUUID = [keychain objectForKey:(__bridge id)(kSecAttrAccount)];
NSString *appVersion = [NSString stringWithFormat:#"%#",#"1.0"];
[keychain setObject:appVersion forKey:(__bridge id)(kSecAttrDescription)];
if (keychainUUID==nil||[keychainUUID isKindOfClass:[NSNull class]]||keychainUUID.length==0) {
uuid = [[NSUUID UUID] UUIDString];
[keychain setObject:uuid forKey:(__bridge id)(kSecAttrAccount)];
}else{
uuid = [keychain objectForKey:(__bridge id)(kSecAttrAccount)];
}
Anyone coming here post 2017, Apple has implemented DeviceCheck for this purposes.
https://developer.apple.com/documentation/devicecheck#overview
You can use DeviceCheck to see if this particular device has installed or used your particular app. It doesn't give you a unique id to the phone, but it does allow you to see if a user has burned through a promotion or not.
You cannot take IMEI and phone number of user mobile, Apple is restricted to get these uniqueID's.
You have to store UDID in keychain. for this you have to download keychainwrapper class and store the UDID generated by above code:
UIDevice *device = [[UIDevice alloc]init];
NSString *idForVend = [NSString stringWithFormat:#"%#", [device identifierForVendor]];
NSLog(#"Identifier For Vendor : %#",idForVend);
follow this link it will solve your problem for sure: https://stackoverflow.com/questions/16459879/how-to-store-a-string-in-keychain-ios , iOS?
If you use this If you delete app And install again it will remain same DeviceID.
#import <AdSupport/AdSupport.h>
NSString* sClientID = [[[ASIdentifierManager sharedManager]advertisingIdentifier] UUIDString];
The Best UUID because:
it will never change (*even if the app will be deleted)
Apple approve it.
Solution is :
You can do it with DeviceToken . DeviceToken are uniq for all mobile.
Code is here :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[UIApplication sharedApplication] respondsToSelector:#selector(registerUserNotificationSettings:)])
{
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
else
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
}
return yes;
}
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
NSString *AppDeviceToken=[[NSString alloc] initWithFormat:#"%#",deviceToken];
//NSLog(#"My token is: %#", self.AppDeviceToken);
AppDeviceToken = [self.AppDeviceToken stringByReplacingOccurrencesOfString:#" " withString:#""];
AppDeviceToken = [self.AppDeviceToken stringByReplacingOccurrencesOfString:#"<" withString:#""];
AppDeviceToken = [self.AppDeviceToken stringByReplacingOccurrencesOfString:#">" withString:#""];
NSLog(#"%#'s Device Token is : %#",[[UIDevice currentDevice] name],AppDeviceToken);
}
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
NSLog(#"Failed to get token, error: %#", error);
}
Device token are uniq for all device.
Say I have an app - 'MyApp' - is there a way to consistently get a device identifier string within 'MyApp'?
i.e. Any time a user uses 'MyApp' on a particular device, I could call the API and get back the same string all the time?
identifierForVendor will change between installs, best to use CFUUIDCreate.
if ([[NSUserDefaults standardUserDefaults] valueForKey:#"UUID"] == nil) {
CFUUIDRef uuid = CFUUIDCreate(NULL);
NSString *uniqueIdentifier = ( NSString*)CFBridgingRelease(CFUUIDCreateString(NULL, uuid));
CFRelease(uuid);
[[NSUserDefaults standardUserDefaults] setObject:uniqueIdentifier forKey:#"UUID"];
}
The above will survive app re-installs.
Apple may reject your app for sending personally identifiable information. Use an advertising ID instead:
#import <AdSupport/AdSupport.h>
// Advertising ID
ASIdentifierManager *adManager = [ASIdentifierManager sharedManager];
NSUUID *uuid = [adManager advertisingIdentifier];
NSString *stringRepresentation = uuid.UUIDString;
Just make sure you abide by Apple's guidelines for UDID usage, including restrictions for users that have checked 'Restrict Ad Tracking' in Settings.
Apple doesn't allowed to add application to the app store that used the [UIDevice uniqueIdentifier] because the property become private in iOS SDK 6.0
What are the Alternatives?
you can use/create "your own" UDID:
+(NSString *)getUUID
{
CFUUIDRef newUniqueId = CFUUIDCreate(kCFAllocatorDefault);
NSString * uuidString = (__bridge_transfer NSString*)CFUUIDCreateString(kCFAllocatorDefault, newUniqueId);
CFRelease(newUniqueId);
return uuidString;
}
You should keep in mind that this method will produce a different id on every call so you should persist it some how, thus it is not an identical alternative to the UDID, but for most uses it is even better like that.
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
- (NSString*)deviceId {
NSString *udidString;
if (SYSTEM_VERSION_LESS_THAN(#"6.0")) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
udidString = [defaults objectForKey:#"udidKey"];
if (!udidString) {
CFUUIDRef identifierObject = CFUUIDCreate(kCFAllocatorDefault);
// Convert the CFUUID to a string
udidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, identifierObject);
[defaults setObject:udidString forKey:#"udidKey"];
[defaults synchronize];
CFRelease((CFTypeRef) identifierObject);
}
} else {
udidString = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
}
return udidString;
}
if gets warning on the line: udidString = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; it means the Xcode SDK is less than 6.0
(Xcode 4.3 contains iOS SDK 5.1, Xcode 4.5 contains iOS SDK 6.0)
to update Xcode iOS SDK:
simply download the newest Xcode available on App Store (Apple doesn't give an option to download only the SDK).
if want to keep current Xcode version just:
download the newest Xcode version.
copy iOS SDK Library from :
newestXcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/
to
oldXcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/
Reopen old Xcode and thats it!
I am developing an application with external databases. For this motive, I have to save an uuid the only identifier for every user who registers. This way, it will differ if the user is a new user or is a user already registered in the application.
I create a new uuid with this:
NSUUID *uuid = [NSUUID UUID];
And i save that at external databases with the username. How do I obtain this information when the user enter again to the application? Have I to save it in some place of the device?
For one, you could could use NSUserDefaults
To cache uuid:
[[NSUserDefaults standardUserDefaults] setObject:uuid forKey:#"userIDKey"];
To retrieve uuid:
NSString *uuid = [[NSUserDefaults standardUserDefaults] objectForKey:#"userIDKey"];
Note that using the NSUUID class restricts you to an iOS target of iOS 6.0+. There are other ways to generate a UUID < iOS 6.0, e.g.
+ (NSString*)stringWithUUID {
CFUUIDRef uuidObj = CFUUIDCreate(nil);
NSString *uuidString = (__bridge_transfer NSString*)CFUUIDCreateString(nil, uuidObj);
CFRelease(uuidObj);
return uuidString;
}