I am developing a program where I need to store a unique device_id since I cant get a unique identifier (like MAC Address) for every device, because it is deprecated by Apple.
What I want to do is, store a file in a specific directory of iOS where even the user deletes my iOS app this file wont be deleted. I am saying this because I used NSUserDefaults but the data stored from it get deleted if the user deletes its application.
*P.S Or if there is an alternative way to identify every device with its unique_id, suggestions are welcomed!*
You should use KeyChain to save info that should not be deleted together with app.
https://developer.apple.com/library/ios/documentation/Security/Reference/keychainservices/Reference/reference.html
UPDATE
This SO thread could be useful for you Saving/Reading to/from KeyChain
I need to store a unique device_id since I cant get a unique
identifier
It is not 100% correct. You can use
[ UIDevice currentDevice ].identifierForVendor
From Apple's docs :
The value of this property is the same for apps that come from the
same vendor running on the same device. A different value is returned
for apps on the same device that come from different vendors, and for
apps on different devices regardless of vendor.
Normally, the vendor is determined by data provided by the App Store.
I the app was not installed from the app store (such as enterprise
apps and apps still in development), then a vendor identifier is
calculated based on the app’s bundle ID. The bundle ID is assumed to
be in reverse-DNS format.
On iOS 6, the first two components of the bundle ID are used to
generate the vendor ID. if the bundle ID only has a single component,
then the entire bundle ID is used. On IOS 7, all components of the
bundle except for the last component are used to generate the vendor
ID. If the bundle ID only has a single component, then the entire
bundle ID is used.
Related
My goal is to obtain the identifierForVendor for a specific app that is on the App Store and that I have NOT developed nor have access to. Lets say this app's bundle id is com.example.app
And just to preface, I was able to grab the identifierForVendor of com.example.app by sniffing the network requests. However, this is not an efficient or scalable way to get it for multiple devices. So, I am looking into other methods.
I have tried to get the identifierForVendor of com.example.app by creating a custom iOS app on Xcode with the bundle id com.example.test
I was hoping the identifierForVendor would be the same considering their documentation notes that apps with the same bundle id will have the same identifierForVendor, but it was not. It seems that the identifierForVendor is also based on the developer profile or something.
Is there anyway for me to get this identifierForVendor value of an external app?
The short answer is that you cannot.
Apple does not provide any details on how this identifier is computed.
The identifier is unique for apps with the same initial bundle id components for a given developer on each device.
For example, apps with bundle ids com.example.app1 and com.example.app2, both from developer1 would have the same identifierForVendor on a given device.
An app with the bundle id com.example.app3 on the same device but from a different developer would have a different identifierForVendor; that is the for vendor bit.
Even if you use the same bundle ID prefix you won't get the same identifier as an app from another developer.
You should also note:
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.
In my iOS app, I have to restrict the user to use iOS app per device. To do this I found a solution that we can use the identifierForVendor method of UUID (Universally Unique Identifier) which will generate a unique ID to uniquely identify an app on a device. (Here, I am not using UDID (Unique Device Identifier) because Apple rejects apps if the app uses UDID).
So my question as is there any possibilities that the two devices will have the same UUID. any idea?
EDIT 1:
I have one more doubt as if I installed the same app on different two devices and save its UUID string into the device KeyChain. Both devices have same iCloud account. Now while doing iCloud sync for this two devices, is one my device KeyChain will gets overwritten?
EDIT 2:
I have found answer for EDIT 1 as 'Yes, through iCloud Keychain, the keychain would be synced to another one of my devices, and I’d get the same device identifier from here and from below answer too'
For the item to be synced with iCloud keychain, I’d need to explicitly set the kSecAttrSynchronizable attribute. Using the SecItem API, we can set this attribute while adding a keychain item.
Is there any tutorial how to add item in Keychain (Without third party libraries)?
No, Two device does not have the same UUID. I am 100% Sure about it. So go with identifierForVendor method.
But, The UUID may be changed when you reinstall the the application in your device (If there is not other application for the same vendor).
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. The value can also change when installing test builds using Xcode or when installing an app on a device using ad-hoc distribution. Therefore, if your app stores the value of this property anywhere, you should gracefully handle situations where the identifier changes.
EDIT
YOUR QUESTION
I have one more doubt as if I installed the same app on different two devices and save its UUID string into the device KeyChain. Both devices have same iCloud account. Now while doing iCloud sync for this two devices, is one my device KeyChain will gets overwritten?
ANSWER
YES. Your keychain will gets overwritten. So you have same UUID for both 2 devices.
I thought is NO!
The value of this property is the same for apps that come from the same vendor running on the same device. A different value is returned for apps on the same device that come from different vendors, and for apps on different devices regardless of vendor.
Normally, the vendor is determined by data provided by the App Store. If the app was not installed from the app store (such as enterprise apps and apps still in development), then a vendor identifier is calculated based on the app’s bundle ID. The bundle ID is assumed to be in reverse-DNS format.
I want the device id of user mobile bcz I want to store it in database while submitting the form,so that whenever user uninstall the app and again reinstall the same at that time he will get all record which is submitted previously so he need not to submit the data again.I used library but it will return the same id for all device.please help.Thanks in advance.
Official Documentation answer
#property(nonatomic, readonly, retain) NSUUID *identifierForVendor
NSString *identifier = [[UIDevice currentDevice].identifierForVendor UUIDString];
The value of this property is the same for apps that come from the same vendor running on the same device. A different value is returned for apps on the same device that come from different vendors, and for apps on different devices regardless of vendor.
Normally, the vendor is determined by data provided by the App Store. If the app was not installed from the app store (such as enterprise apps and apps still in development), then a vendor identifier is calculated based on the app’s bundle ID. The bundle ID is assumed to be in reverse-DNS format.
On iOS 6, the first two components of the bundle ID are used to generate the vendor ID. if the bundle ID only has a single component, then the entire bundle ID is used.
On IOS 7, all components of the bundle except for the last component are used to generate the vendor ID. If the bundle ID only has a single component, then the entire bundle ID is used.
If the value is nil, wait and get the value again later. This happens, for example, after the device has been restarted but before the user has unlocked the device.
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. The value can also change when installing test builds using Xcode or when installing an app on a device using ad-hoc distribution. Therefore, if your app stores the value of this property anywhere, you should gracefully handle situations where the identifier changes.
you can use unique device id FOR IOS6+
NSString *identifier = [[UIDevice currentDevice].identifierForVendor UUIDString];
I've worked for a while now on my (existing) app to add support iCloud synchronization. In total, I have 3 Versions of the app:
a) regular iPhone version
b) lite (free) iPhone version
c) iPad version
I want to use iCloud to make the core data storage sync between all 3 versions/devices. I've got the implementation, and the development versions I put on my devices worked great.
Yesterday I decided to submit the iPhone versions, but they got rejected:
Invalid Code Signing Entitlements - The signature for your app bundle contains entitlement values that are not supported. For the com.apple.developer.ubiquity-container-identifiers entitlement, the first value in the array must consist of the prefix provided by Apple in the provisioning profile followed by a bundle identifier suffix. The bundle identifier must match the bundle identifier for one of your apps or another app that you are permitted to use as the iCloud container identifier.
Specifically, value "[teamid].com.[myself].[somename]" for key "com.apple.developer.ubiquity-container-identifiers" in [my app] is not supported.
I really have no clue about how those identifiers should look like. On this page: https://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/iCloud/iCloud.html#//apple_ref/doc/uid/TP40007072-CH5-SW1 they say something about containers of my other apps ... do I have to add 3 containers for the 3 versions of my app? So far I configured under project/targets/summary/entitlements:
[x] iCloud Key-Value Store: com.[myself].[somename]
iCloud Containers: com.[myself].[somename]
for all 3 versions (same identifiers). What do I have to configure exactly, so that all 3 versions will sync their core data storage database through iCloud?
According to iCloud Design Guide: iCloud Fundamentals, all your apps sharing your iCloud container, can do so using a single iCloud container (if that is what you wish). The catch here is that the primary (first) container ID must be the Bundle ID of your current app being developed, or a Bundle ID of any of your previously submitted apps (that share the same Team ID).
I'll bring an example,
Let us assume that your app regular iPhone app (a) has a Bundle ID com.yourteam.iphoneapp and it was the one that you submitted first and is available on the App Store. Then you have to provide that same ID as the primary iCloud container ID for all other versions as well.
Here's a relevant section out of the document mentioned above:
In the Xcode target editor’s Summary tab, you can request access to as
many ubiquity containers as you need for your app. For example, say
you provide a free and paid version of your app. You’d want users, who
upgrade, to retain access to their iCloud documents. Or, perhaps you
provide two apps that interoperate and need access to each other’s
files. In both of these examples, you obtain the needed access by
specifying a common ubiquity container and then requesting access to
it from each app.
Pick one of your iCloud-enabled apps to serve as the primary app for the common ubiquity container. The app you pick can be the current
one you are developing, or another app of yours submitted for
distribution in the App Store and whose entitlements use the same team
ID.
You have probably resolved this issue by now, but the answer is that you just use the same ubiquity container identifier in all apps. You only need one, and it is not dependent on the app name: notice Apple told you to use "[teamid].com.[myself].[somename]" not "[teamid].com.[myself].[appname]". Use "some name" that is consistent between the apps, not the "app name".
You need to create 3 separathe iCloud enabled provisional profiles. Devices that are running the same version of your app can share data on the same iCloud container. But if you wish to have any devices running any one of those three versions of your apps to share data then you need to add those identifiers in the Entitlements section of each version.
There is good tutorial on iCloud from http://www.raywenderlich.com/6015/beginning-icloud-in-ios-5-tutorial-part-1
Edited:
I added an sample picture for your case. Also, the text below is extracted from the tutorial on that website:
Here we use a new method you haven’t seen yet called URLForUbiquityContainerIdentifier. This method allows you to pass in a container identifier (like you set up earlier in the iCloud Containers section) and it will return to you a URL to use to access files in iCloud storage.
You need to call this on startup for each container you want to access to give your app permission to access the URL. If you pass in nil to the method (like we do here), it automatically returns the first iCloud Container set up for the project. Since we only have one container, this makes it nice and easy.
I've uploaded several .app's the the iTunes store, where the "executable" file (ie. filename.app) is the same.
What are the repercussion's of this on an actual device, when an actual person downloads both onto their iPad/Phone/Touch , and possibly is running both?
The best answer would be that it is inconsequential since the bundleID's store the .app in different respective folders, but I do need further insight.
The name you give the app is irrelevant. All that matters is the bundle ID. These must be unique. From the iTunesConnect Developer's Guide:
An identifier used by iOS and Mac OS X
to recognize any future updates to
your app. Your Bundle ID must be
registered with Apple and unique to
your app. Bundle IDs are app-type
specific (either iOS or Mac OS X). The
same Bundle ID cannot be used for both
iOS and Mac OS X apps.
Think about the consequences of the alternative. If I name my app MyApp and you name your app MyApp, then a user who bought both would be in trouble. The bundle ID is the unique identifier for each app. The name of the app is unique for convenience and to avoid confusion when purchasing an app, but the bundle identifier is unique to keep products from overwriting one another.