Generating unique id for iphone - ios

Hi I am developing small iphone application in which I want to generate unique id for my device. I am using following thing :
-(NSString*)uniqueIDForDevice
{
NSString* uniqueIdentifier = nil;
if( [UIDevice instancesRespondToSelector:#selector(identifierForVendor)] ) { // >=iOS 7
uniqueIdentifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
} else { //<=iOS6, Use UDID of Device
CFUUIDRef uuid = CFUUIDCreate(NULL);
//uniqueIdentifier = ( NSString*)CFUUIDCreateString(NULL, uuid);- for non- ARC
uniqueIdentifier = ( NSString*)CFBridgingRelease(CFUUIDCreateString(NULL, uuid));// for ARC
CFRelease(uuid);
}
return uniqueIdentifier;
}
So i tested this code locally. Mean Every time when I uninstall and install it again it will create same unique code for me. But when I push it to app store that time for every installation on same device it is generating different code. I want to generate same code for each installation on same device. Is there any method to do this. Need some help.
I want to generate a unique identifier for device which will be same for my device even I install and uninstall application many times. I am using OIS 7.0 version.
Thank you.

The identifierForVendor changes only after a system restore, you can check some of my test here:iOS 7 access UUID value in an enterprise application (not for AppStore).
In case of iOS version lower than ios6 you can save the id in the keychain, it will persist even after app uninstall

Related

Get UDID in iOS 8 +

I need to get the UDID of my iPhone to use in my iOS app.
Some info about my app:
My app is not for the public and will never make it to the store, so I can use any 3rd party libraries. It will only be used by some employees at work.
My device will always be plugged into a Mac, while my app is running.
The way I see it, there are only 2 ways this can be accomplished.
Use a third party library to get the UDID inside of my iOS app.
Since the iPhone will always be plugged into a Mac while my app is running, how about getting the UDID via the Mac and transferring it in some way to my app in the iPhone.
Any ideas would be appreciated. Thanks.
Edit: Question is, do you know any 3rd party libraries or a better way to get my app to automatically get the iPhone's UDID while running?
Edit 2: I know this can be done using only my phone because of this web app: http://get.udid.io/
How does this work?
If you're trying to read the UDID to automate something on the Mac, then you can use something like system_profiler SPUSBDataType to get the UDID, for my phone the entry:
Product ID: 0x12a8
Vendor ID: 0x05ac (Apple Inc.)
Version: 7.01
Serial Number: 7bed*********************************33
Speed: Up to 480 Mb/sec
Manufacturer: Apple Inc.
Location ID: 0x1d110000 / 6
Current Available (mA): 500
Current Required (mA): 500
Extra Operating Current (mA): 1600
The line Serial Number is the UDID (I've starred it out as I'm stupidly paranoid).
Note, that without the UDID you could never have got the app onto the phone in the first place.
You could run a small daemon process on the mac, reading this information and creating a bonjour service that provides the information to requestors - it's a SMOP.
It's very simple. Go to Xcode Window and select Devices or you can find it in Organizer.
http://www.raywenderlich.com/2915/ios-code-signing-under-the-hood/organizerudid
From a quick look online, it looks like you can use a private framework called libMobileGestalt.dylib.
After linking the library and importing the header, you should be able to do something like this (reference):
CFStringRef value = MGCopyAnswer(kMGUniqueDeviceID);
NSLog(#"Value: %#", value);
CFRelease(value);
On my Mac, I can find that particular dylib here:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib/libMobileGestalt.dylib
Use this code in ios 9
NSUUID *tempUUID = [[UIDevice currentDevice] identifierForVendor];
NSString *stringForUDID = [tempUUID UUIDString];
NSCharacterSet *notAllowedChars = [[NSCharacterSet characterSetWithCharactersInString:#"1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"] invertedSet];
NSString *resultString = [[stringForUDID componentsSeparatedByCharactersInSet:notAllowedChars] componentsJoinedByString:#""];
NSLog(#"Final string %#", resultString);
Here is the github project which seems correct for your requirement
Here is the code that works
#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
#import <liblockdown.h>
#include <stdio.h>
...
LockdownConnectionRef connection = lockdown_connect();
CFStringRef udid = (CFStringRef)lockdown_copy_value(connection, NULL, kLockdownUniqueDeviceIDKey);
CFShow(udid);
lockdown_disconnect(connection);
Use this: [[[UIDevice currentDevice] identifierForVendor] UUIDString];

Can one determine the iOS SDK version used to build a binary, programmatically, at run time?

Ah, iOS 8 - lots of unexpected changes from iOS 7 to account for!
tl;dr: Is there a way to programmatically determine the iOS SDK version used to build an app, at run-time (not with a preprocessor macro)?
I'm struggling with some window frame calculations for a library I maintain (distributed as a pre-built static library), as iOS 8 has changed the way the screen coordinate system works.
Two initial observations, running code for iOS 7 with no changes for iOS 8:
When built with the iOS 7 SDK, and run on iOS 8, everything works as prior, no changes necessary.
When built with the iOS 8 SDK, and run on iOS 8, it's broken: some changes in frame calculation are needed to get correct positioning.
So, we change the code, with conditionals on [[UIDevice currentDevice] systemVersion], to work correctly with the new coordinate system. Now:
When built with the iOS 7 SDK, and run on iOS 7, everything works.
When built with the iOS 8 SDK, and run on iOS 8, everything works.
BUT:
When built with the iOS 7 SDK, and run on iOS 8, the calculations are off - remember, when built with the iOS 7 SDK, everything worked fine prior to the iOS 8-specific code changes. So, the changes made actually broke stuff.
Now, normally, I could happily solve this with some macro conditionals on the SDK version (#ifdef __IPHONE_8_0, etc). But I'm distributing a pre-built static library, built with the iOS 7 SDK, so the code within those conditionals would never make it in. Here's why that's a problem:
If the static library is built with the iOS 7 SDK, but linked into an app built with the iOS 8 SDK, it's the same as if the static library were built with the iOS 8 SDK (because the linking happens at the final app compilation stage, of course). That means I need to have those iOS 8 changes in there, when the app is built with the iOS 8 SDK -- but I can't use a macro conditional to determine whether to use them, as the C preprocessor did its thing during the static library build under iOS 7.
So, my question is this: does anyone know how I might be able to determine whether the app build was made with the iOS 8 SDK, at runtime, from within the pre-compiled static library?
I did try checking for an iOS 8-only SDK feature (-[UIScreen nativeBounds], for example), but that doesn't fly -- the symbol's available regardless of SDK version.
Anyone have any ideas?
Empirical, undocumented observations follow:
Apple records the SDK you built against in the Info.plist under the keys DTSDKBuild and DTSDKName, amongst others. Of those DTSDKName seems to be accessible at runtime and ends with the SDK number. So, getting a:
- (NSString *)buildVersion
{
// form character set of digits and punctuation
NSMutableCharacterSet *characterSet =
[[NSCharacterSet decimalDigitCharacterSet] mutableCopy];
[characterSet formUnionWithCharacterSet:
[NSCharacterSet punctuationCharacterSet]];
// get only those things in characterSet from the SDK name
NSString *SDKName = [[NSBundle mainBundle] infoDictionary][#"DTSDKName"];
NSArray *components =
[[SDKName componentsSeparatedByCharactersInSet:
[characterSet invertedSet]]
filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:#"length != 0"]];
if([components count]) return components[0];
return nil;
}
BOOL wasBuiltWithiOS8SDK =
[[[NSBundle mainBundle] infoDictionary][#"DTSDKBuild"] compare:#"11D167"]
== NSOrderedDescending;
... with the heavy caveat that I've just reverse engineered that, empirically. So it's technically undocumented API and there's no guarantee whatsoever of robustness in the future.
You could then just use:
BOOL wasBuiltForiOS8 =
[[self buildVersion] compare:#"8.0"] != NSOrderedAscending;
(which has the nice feature that it'll evaluate to YES if the version string isn't found, so technically it doesn't matter if Apple takes away DTSDKBuild in the future, it only matters that they don't retroactively remove it from 7.x or somehow one day use a version string that is alphabetically before 8.0)
Here's a provisional solution - hacky, though; it'd be nice to have something more robust.
- (BOOL)hasiOS8ScreenCoordinateBehaviour {
if ( [[[UIDevice currentDevice] systemVersion] floatValue] < 8.0 ) return NO;
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if ( UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) &&
screenSize.width < screenSize.height ) {
return NO;
}
return YES;
}

Unique Identifier Changing on 64 bit iOS Device

Reviewed lots of questions as there are number of questions with same topic but not find with the same issue so posting.
Issue
Looking to Generate Unique Identifier for iOS Device as if user install app and with reinstall generate same identifier.
Resolved But Not Working With 64 Bit Devices
I Used this code for fetching the unique identifier for iOS device and it works fine all but when i run it on 64 bit iOS device it gives different result on every install. Please review if anyone know about the possible solution.
- (NSString *)GetUUID {
#try {
UIDevice *device = [UIDevice currentDevice];
return [[device identifierForVendor]UUIDString];
}
#catch (NSException *exception) {
return #"00000-00000-0000-00000";
}
}
The identifierForVendor will stay the same as long as app from the same developer(vendor) are installed on the device.
Thus if user uninstalls your app and there are no other app by you on the user device the identifierForVendor will be different when the user re-installs you app.
Apple has made it very clear they don't want developers track devices or installs per device. Thus you can no longer get any unique identifier from the device.
The changing of the identifierForVendor could have to do with some re-installing isseu. I've been tracking identifierForVendor and dit not see this issue.
For storing identifier betweeen reinstalls you may use this code (add SSKeychain to project)
/*
The following method determines the AppName and a uniqueidentifier and store it in the keychain
As a result when the user removes the app, downloads it again his JID and password which are derived from the
uniqueidentifier don't change.
otherwide the identifierForVendor method would return a new value on reinstall
*/
-(NSString *)getUniqueDeviceIdentifierAsString
{
NSString *appName=[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey];
NSString *strApplicationUUID = [SSKeychain passwordForService:appName account:#"incoding"];
if (strApplicationUUID == nil)
{
strApplicationUUID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
[SSKeychain setPassword:strApplicationUUID forService:appName account:#"incoding"];
}
return strApplicationUUID;
}
Use keychain Access to solve getting different vendor ID
Simple iPhone Keychain Access
http://useyourloaf.com/blog/2010/03/29/simple-iphone-keychain-access.html

iOS 7 access UUID value in an enterprise application (not for AppStore)

Apple since iOS7 ha deprecated and unavailable the use of the property -uniqueIdentifier. The other properties -identifierForVendor and -advertisingIdentifier have the big problem that they change the value after uninstalling and reinstalling the app.
I need that value to identify uniquely the device connected to the server.
The app will be distributed only internally using an enterprise account, so no problem for the review process.
Is there a private a method to get it?
[UPDATE WITH SOME TEST]
As David said I used identifier for vendor on iOS7.1 device here are some results from my tests.
After app installation: 28FD42B6-A993-4602-A988-69E375A1F913
After killing the app: 28FD42B6-A993-4602-A988-69E375A1F913
After deleting and reinstalling the app:
28FD42B6-A993-4602-A988-69E375A1F913
After system restore and reinstalling the app:
4948F77F-3D41-4933-B2F0-C4DCB529C7CC
After restore from backup made before system restore:
28FD42B6-A993-4602-A988-69E375A1F913
You should be able to use [UIDevice identifierForVendor] for your purpose. According to the documentation:
The value of this property is the same for apps that come from the same vendor running on the same device.
Based on that I don't think the value should change if you delete and reinstall the application. Some quick testing confirms that it is persistent through delete/install cycles.
EDIT:
It looks like identifierForVendor is only persistent through remove/install on iOS 7, so use uniqueIdentifier on iOS 6 and identifierForVendor on iOS 7 as:
#implementation UIDevice (persistentDeviceIdentifier)
-(NSString*)persistentDeviceIdentifier
{
if([self respondsToSelector:#selector(uniqueIdentifier)])
return [self performSelector:#selector(uniqueIdentifier)];
else
return [[self identifierForVendor] UUIDString];
}
#end

The advertisingIdentifier and identifierForVendor return "00000000-0000-0000-0000-000000000000"

I've implemented this methods to get advertisingIdentifier and identifierForVendor:
- (NSString *) advertisingIdentifier
{
if (!NSClassFromString(#"ASIdentifierManager")) {
return [OpenUDID value];
}
return [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
}
- (NSString *) identifierForVendor
{
if ([[UIDevice currentDevice] respondsToSelector:#selector(identifierForVendor)]) {
return [[[UIDevice currentDevice] identifierForVendor] UUIDString];
}
return #"";
}
- (BOOL)isAdvertisingTrackingEnabled
{
if (NSClassFromString(#"ASIdentifierManager") && ![[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]) {
return NO;
}
return YES;
}
On simulator everything is working as should be and I can get the 2 strings IDs representation.
But when I run from iPhone 3GS with iOS 6.0 (10A403), these 2 methods return "00000000-0000-0000-0000-000000000000" as identifier.
Already done:
Restarted the device
Removed the app and reinstalled
Created and Ad-Hoc build, installed, removed and installed again
Run this code from another app
Tested on iPad 2 with iOS 6.0 (10A403) and everything went ok (I've got the correct identifiers)
It appears to be a bug in iOS. Seeing the same issue on devices that have been upgraded over-the-air, but devices upgraded with Xcode or iTunes work as expected without zeros.
Tried similar steps as you, and the only common theme was over-the-air (bad) versus tethered upgrade (good).
Update: Users that move directly from iOS 5.1 to 6.1 over-the-air experience a different behavior. Every time the app is closed completely and restarted, a new value is being returned by identifierForVendor. This would be expected if the app was being uninstalled and reinstalled, but that's not the case.
Apple confirmed this bug in their system in response to a Technical Support Incident request. They said that identifierForVendor and advertisingIdentifier sometimes
returning all zeros can be seen both in development builds and apps downloaded over the air from the App Store. They have no work around and can't say when the problem will be fixed.
There are some situations where API returns empty response for ID like after device restore.
Suggestion is to postpone ID retreival, so you can call sometginh like this:
-(void)retrieveID
{
if (<check fails>)
[self performSelector:#"retrieveID" withObject:nil afterDelay:1.0];
}
And fetch ID later.

Resources