how to detect whether user had installed this app before - ios

I am trying to check whether user has installed this app on his iOS device before or not.
For example I install app X , then Uninstall it, and again Install it.
I want that app X be able to detect that the device had installed this app before and this is a re-installation.
Update
By thanks to all friends that shared solutions like keychain, vendor Id and etc. The main subject that I should notice (as mentioned in comments) is that; Is there a solution that works even after system restore or system factory reset? According to #Andrea's answer using receipts may work but what about the cases that we want to publish the app in enterprises account? Or what if user uses a jailbreak device and install the app with and IPA? Some times because of security problems we want to detect that whether this app is installed before or not? So how we can detect it?

Maybe trying to check the app receipt you can infer the original purchase date (even if the app is free it comes with a receipt), but this could be difficult.
If you want to do that you can can add a flag to the keychain. Keychain values persist after an uninstall, but not after a system restore.
Of course this can work only in future releases.

As the OP mentions in one comment Apple does not allow access to the device UDID so we need a different approach to uniquely identify the user.
In order to get an identifier that uniquely identifies the user you could use:
[[UIDevice currentDevice] identifierForVendor]
But be careful, according to Apple documentation:
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.
A possible solution to this is to store the identifier in NSUserDefaults and also in the server and have a logic that at startup checks if there is a change in the identifier. In that case you could update the identifier locally and in the server to provide continuity for your analytics, for example.
For example to check for a change in the identifier:
NSString *previousUUID = [[NSUserDefaults standardUserDefaults] stringForKey:DEVICE_UUID];
NSString *currentUUID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
BOOL UUIDChanged = ![previousUUID isEqualToString:currentUUID];
// Handle this situation in your backend to offer continuity in your analytics
I have three apps in the App Store that use this and were approved by Apple without problems.

iOS is built to reserve a portion of disk to each application installed, when you uninstall application the space is erased so there isn't a "cookie" that describes when app has been installed.
You can reach your goal in two ways: through the keychain, for instance you save a value with specific key and you check every installation that key or through a simple backend call that send you the date o whatever you want. I think the first solution is better.

I would define a method to uniquely identify a device. Whenever an install is issued on a device, I would send a request to a server, where device keys are stored. If the key is not already present in the database, then I would store it, otherwise the install has been already issued.

You can save something to keychain and then try to read it.

You can use APNS. Apple push notification service.
Device token never will change whatever device reset.
So, you can use Push notification.
Push notification(device token) is unique for each device and always will be same.
When app will install save device token on your server database so, whenever app will again install on same device you can check device token from server database.

Related

iOS DeviceCheck API - Will the token remain same if user uninstall the app

We want to prevent user from creating multiple profiles on same device.
For this we first tried IDFA but IDFA can be reset anytime from Settings.
Then we found DeviceCheck that states:
identifying Access per-device, per-developer data that your associated
server can use in its business logic
According to this we get to set two bits per device and a token for server to server verification. Now the question is:
If user uninstalls the app and installs again. will the token remain same?
How would we detect user isn't creating multiple Profiles on same device?
Device Check is the best solution for what you are trying to achieve. The advertising ID can be turned off and reset, and the [[UIDevice currentDevice] uniqueIdentifier] will be reset once the user uninstalls all app from a given developer.
Device Check is the solution Apple has proposed to check whether a device has redeemed an offer, created a previous profile, or simply to check whether the device is an authentic Apple device.
It requires the use of a server to communicate with Apple servers to validate a client generated token. You get two bits you can set. Those two bits are connected to your developer profile, not two bits per app.
keychain is the place where you can store users data securely. Storing data in keychain has one more advantage — in a case when the user decides to remove the app from the device and then he decides to install it again, the data is still saved.
You can also do this by storing a value in the Keychain. It will persist even if the app is deleted and thus you can tell if the app is a new install or a reinstall. So if a value is there in your keychain it is a reinstall otherwise its a fresh install.

does app give different device token on re-installing again

I remember, the device token never changes upon re-installing for iPhone.
However these days (especially on iOS 9), I noticed that device token is changing if I re-install the app.
Is this setting is done by Apple or I am missing anything?
I have to know this because this is very important for me as I am sending push based for specific users to inform their updates.
Also for no reason there are un-wanted many device tokens.
Note
I am calling below webservice in App Delegate
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
// sending it to online database for my record
}
Yes on iOS9 Apple says that Device Token might change each time your app is installed. So the best way is to reregister the Device token on each launch.
Here is a link to Apples documentation about changing device token
You need to find your own way to track user. Here is issues with your approach and suggested vendor identifier:
Device push token can change at any moment. You can track this change during application launch and ask server to switch tokens, but messages which will be send till this moment on old token will be lost.
identifierForVendor - also very unreliable source of unique identifier, because it will change in a lot of cases.
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.
For single device you can use Keychain as source of persistent identifier storage. You can generate for user new unique identifier (for example with NSUUID) and store it in Keychain (if not exist yet). If access group will be configured for stored item and reused with all your application - you will have access to stored unique identifier from your applications on user device. If properly configured, item in Keychain will be stored in encrypted user device backups and even will be restored on his new device.
Yes, it might be changed when each time app is installed. you need to update the device_token on every launch of app.
rtfm:
"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."
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIDevice_Class/#//apple_ref/occ/instp/UIDevice/identifierForVendor

In my iOS application, the user has to register their `unique device` for full access of the app which remains same even after reinstallation [duplicate]

In my iPhone/iPad app's use case, there is a voting system and one device can send its vote once to the server. Therefore my server needs to identify user's device. I don't want the user to register an account because that makes the app complicate. However, I couldn't find a solution that works.
UDID is deprecated
I presume getting MAC address will get your app rejected by the app review process
I tried creating my own UUID using [[NSUUID UUID] UUIDString] and then storing it using NSUserDefaults, but the settings disappear if the user uninstalls the app
identifierForVendor is also reset when the user uninstalls the app
I considered advertisingIdentifier but because I'm not using it for advertisement, I presume it will also be rejected by the app review process
I'm not asking for a bulletproof solution in every situation. Just a solution that works even if the user uninstalls the app. Because I can generate my own UUID, I guess my question boils down to: How I can save data for the app that survives app uninstallation?
However if any of you have other approach, please feel free to inform me. Thanks.
Save the UUID into the keychain.

What can I use as a permanent alternative to UUID?

Here is my situation and problem. I have an app that is used by a commercial company. They give their workers a phone with our app installed on it, the workers might swap phones (i.e. first come first serve; grab what is available).
The company needs a way to identify each phone in case it stolen and to use for inventory, but from our app. Our solution gives them a way to remote wipe the app should the phone be lost or stolen. Since we cant use the UUID, per Apple, we not sure how to identify the phone for wiping. I know there is a temp way to sue a temp UUID, but that temp UUID has the ability to change or be reset by Apple or another app on the phone. So if that UUID get change out from under us we can't wipe it or identify it as the new change UUID would be passed up.
The other issue with us generating a unique ID of our own when the app is installed is that if some uninstalls our app and reinstalls, for whatever reason, it will create a new unique ID on the backend. Now we have to ID's on the backend for the same phone, so inventory will show one extra phone.
We can't trust the companies to always be sure to wipe out the old ID should they reinstall the app.
Any suggestions?
about the unique identifier, generate a UUID and saved it in Keychain
Apple has OS X Server has a function to manage remote devices, it's very useful for enterprise. such as manage VPN settings, wifi settings,distribute apps, remote wipe if stolen. You should research MDM.
if your iPhone is stolen you can do nothing in your app.
Best idea I know about is to include AdSupport and do this:
NSString *uuid = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSUserDefaults can persist this across app updates. Not sure across uninstalls. For that, you might need user identity and storage off the device.
Following code will help you to get unique alphanumeric value which will be same for apps that come from the same vendor running on the same device
Which means if you 5 Apps. published , all of them will return you a same unique value on a particular device.
[[[UIDevice currentDevice] identifierForVendor] UUIDString]
Please find the Reference at Developer Library
Other solution would be to use OpenUDID.
Third Solution is as below:
When App. Launches for the first time, create your own unique id from "CFUUIDCreate"
Save this with NSUserDefault in Cloud.
So, now if the app is uninstalled it will still have same id for that user when fetched from the Cloud.
In case phone is reset, you will still get the same ID unless and until cloud account is changed.

is there a way to check two device tokens are belongs to same device?

I want to get the device token of the device and want to send it to a server.Sometimes if I uninstall the app and install it again,Then the new device token which I got is different than previous.So,In my server there are two device tokens which are belong to same device.Can we avoid that?(In my service,I want to keep only one device token per one device)
Thank you.
If you doing this for push notification, you can use the feedback service from apple to detect if a device is deleted.
You can store a generated UUID and store it in the keychain like this. If you set it up right, it will persist between app deletes and reinstalls on the same device, but not across multiple devices via a restore from backup (unless you want that).

Resources