I'm considering using the CFUUIDCreate API to build a database in my server to measure what percentage of users of each of my apps are running which version of iOS (to help me make a decision on iOS minimum supported version for future development).
My question is: Should I ask the user for permission to send the (anonymous) UUID / iOS version data pair to my server, or is it OK to do it automatically?
I ask because I could bet on the safe side and ask anyway, but most users would feel intimidated by the technical details and most likely decline. Also, the longer the text in an UIAlertView, the more likely the user won't read it.
Will Apple reject my app if I don't ask? Even if they don't, do you think I should always ask the user for permission to send this anonymous data?
What's everyone's experience implementing this kind of functionality?
OK, this is what I'm going to do, based on Nikolai Ruhe's answer but improving on a pitfall I just discovered.
Suppose user John Doe installed my app on his iPhone running iOS 5.0.
On the first launch, the app sends an anonymous request to my server that effectively increases by one the counter for 'Devices running iOS 5.0'. The app records this event and the iOS version (in User Defaults or Keychain) and does not send any further requests as long as the locally stored OS version string and the current one (returned by the system) are equal.
The next week, John upgrades to iOS 5.1 and launches my app. The app detects the OS version discrepancy and sends a new request to my server.
But if this only adds one device to the 'iOS 5.1' population, John's iPhone is now being counted twice: once as "Devices running 5.0" and once as "Devices running 5.1".
So to fix this, my HTTP request should look like this:
http://myserver.com/my_stats_scripts/index.php?app_id=com.myCompany.myApp&new_os_ver=5.1&old_os_ver=5.0
So my database can increase the number of 5.1 devices and decrease the number of 5.0 devices by one.
Of course, on the first request, the HTTP parameter old_os_ver is set to empty, and the server treats it like a new device.
If I pull this right, I no longer need UUIDs. But I am still sending system info covertly to my server. I think I'll also disclose this on the Terms of Use.
You should definitely ask for permission. The crucial bit here is that your data collecting might be anonymous, yet it can be used it to track individual users.
Web browsers send a user-agent string with every request. The difference is that they do not send a universally trackable id that would never change.
So the problematic piece in your proposal is the UUID. Why not just leaving it out? Your app would send an anonymous request once and locally store the transmitted iOS version. When the user upgrades the OS, you send another request with the new iOS version and an update count.
Using this scheme you would not transmit trackable data and still get a proper usage-by-os statistic.
Related
Assuming you created an app that users have downloaded that is just awful and you neither want to fix it nor have anyone continue to use it so that it won't tarnish your brand, is there a way to end its life on user's iOS devices?
Curious if there is some store setting to force it to work with earlier versions of iOS and invalidates the current app, or code that would force an update that says the app is no longer available.
As many have confirmed, there is no way to remove an application from someone's device. For these cases though, many companies have servers that the application sends a request to on launch, that returns either a need to update the app, a message, or to tell the user the app has been discontinued and that the app cannot be used anymore, stopping them from using the app from there on.
The last use case might be useful to you, but of course this is a proactive solution, not a reactive one.
My project have a case: one account user can only log on to one device ( if user log on to app in device A, user can't log on to app in device B). My Idea is: when user login, I'll get the imei Iphone (like android) and send it with request login to server. But I can't get imei. I try with UUID, but UUID will change when re install app. Keychain does not solve the problem. Please help me.
You have to use Keychain to store Unique Id , this will not change even if user delete app
You can use any wrapper Source code to do this
here is an example
https://github.com/Joe0708/KeychainUUID
At the beginning I'd like to mention that I do not know any method that directly answers your question, especially that Apple does not allow you to read IMEI and other similar stuff due to privacy concerns. This has been answered here.
The workaround might be as follows
Take a look at the UIDevice class, especially at the identifierForVendorProperty which provides you (according to documentation ) with a device specific value.
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.
As far as i know some financial apps are secured this way to permit only one device to access the account. This however requires registering a device each time application is reinstalled.
Alternatively you can use UUID you generate within your app (first run) and then you assign it for the user online. It might take the form similar to two step verification process. Be aware however that with such restrictions user will have to be online all the time to use your app.
Scenario:
I "control" two different apps, App A and App B, both which the user has installed
App A is running
App A needs to obtain a string that was set by App B when App B last ran.
After obtaining the string, App A will still be running
User should not receive any feedback this communication is happening. E.g. no "switching animations" between A or B, no pop-ups, etc.
Constraints:
Apps are released under different vendors
Apps are already in the app store; updated versions will have this communication ability.
It is acceptable for the data stored in App B to be accessible to other apps on the device.
It is not acceptable for the data stored in App B to be visible to general third parties (e.g. if an external server is used, there needs to be some sort of secured scheme)
The data read should be able to occur immediately upon App A being opened after install. For instance, I cannot require the user of App A to enter log in credentials for an external communication service.
Must work on non-jailbroken devices.
This is seeming rather difficult to pull off in iOS7. Help is appreciated.
Tricky work around. Not recommended, but it will get the job done if you can't afford servers.
On the first app create a contact in the user's contacts book. Give it a generic name like "000 - NameOfAppB Data - Don't Delete" (I start with "000" so it goes to the bottom of the users contact book so they never see it, I also add "don't delete" so if the user does somehow find it they don't delete it hahaha) (who looks at contact books anyways). In the contact info under notes add your NSData in string format.
Then when app A is opened search for that contact, read the data, then delete the contact.
Apple does allow you to create and delete users contacts without their permission. (At least in 2011 they did, this may have changed).
This might serve your purpose
https://developer.apple.com/library/ios/documentation/Security/Reference/keychainservices/Reference/reference.html
I am not sure of its limitations though, i have seen implementations where credentials have been shared between apps.
this is my first ios app. am working on a version 1 that i'm planning on giving to few of my customers. customers will get it from app store. in future, if i have new version that i'd like to notify current users, is there anything that I have to put in version 1?
thanks.
Yes, you will need to put something in version 1 in order to do this if you want some kind of notification in the app itself. You can go about it a few different routes depending on how complex you want it to be:
You could add push notifications to your app, so that you can send a push notification to your users letting them know an upgrade is available. You would probably only want to do this if you used the push notifications for other purposes as well, as users probably wouldn't want to allow push notifications for an app to only inform them of app updates.
You could have your app check with your server upon app launch to see if there's an update available. You could simply have a file on your server that the app checks which can contain the version number of the most up to date app you have available. If the server reports a newer version than the version reported by the app, it can display a message, which could also be contained on your server to be configurable. This would be pretty simple to implement, and could possibly contain other configuration information for your app. You could also choose when to show the prompt, in case you don't want to bug users for some updates but do for others. This would be good to do if you might release an update that requires users upgrade in order to continue to have it work with a backend server.
You can also get your app to check directly with Apple to see if a newer version of the app is available on the app store. You should be able to find a resource that will instruct you how to do this. Going this route, as soon as an update is available it will start bugging users to upgrade, so you may not want to do this if you only want to push some updates on your users but not others.
You can do nothing. On iOS 7 by default app updates get automatically installed, and even if they have that disabled, the user can see what app updates are available in their app store app. This is what most apps do, aka they don't bug the user every time an update is available. And if somebody isn't updating their apps anyway, your prompt won't necessarily encourage them to do it either.
It's similar to the message appearing in Chrome when a new version is available - something like "Chrome has just got better".
Presuming that you have a server side counterpart, my approach would be the following:
store the latest version number of your app somewhere on the server (database, configuration file, etc)
implement an API at server side that, upon an app version provided as parameter, returns true if an update is available
in your app, read the current app version (see this SO answer)
call the remote API mentioned in (2), and act accordingly if the return value is true
Note however that appstore notifies the user when an update is available - but that doesn't happen in-app
Incrementing the app version is enough for App Store notification as explained in
iPhone app Update Vs new version
There is a newly introduced issue with iPhone 3.0 SDK and how it deals with the NSURL method for automatically making phone calls. It used to be that you could call a method (NSURL), pass in a string with a URL prefix (tel://, sms, etc...) and the iPhone OS would dispatch the message to the device, such as iTunes, App Store, Phone, SMS, Mail, Safari, etc... The code goes something like this:
[openURL:[NSURL URLWithString:#"tel://8005551212"]];
When the method was called the phone call would be placed automatically. With the iPhone OS 3.0 when the method is called the app pops up a dialogue box asking for confirm the phone call. This breaks several existing apps as well as one that we just pushed into the App Store for review.
Can anyone think of a fix to this issue? I'm currently at a loss for what to do and trying to decide what other ways to handle this new wrench in the works.
I blogged about this and suggested that people contact Apple and make them aware of this issue. I also recommend a fix that a friend and I were thinking about - and that is to use the same "authorization" that location aware apps have; an app knows it's location aware and asks the user if it's okay to use their location.
Again, if anyone has a fix for this issue (and that is within the realm of the iPhone SDK as to not be rejected by Apple) please let me know; I would be greatly appreciative.
Update: Julian Romero Nieto has a good description of the bug and cites the (updated) Apple documentation and shows the issue at hand. You can read his posting to Oper Radar here.
I believe this is included as a security feature - imagine an app that called a 900 number at 3am every day for 10 minutes. If you compare it to the new 'In-App Purchase' API - it's much the same.
The location API comparison is a bad example - getting the users location is a privacy concern, not a financial one.
You can't fix this issue as this is what is intended - anything you do to "fix" the issue will result in an app that won't be approved.
The user experience is considered not to be good when an app can choose to dial a number without the user's consent. It would be possible for software to dial "premium" numbers that cost the user a lot of money without them realising.
This is standard across all mobile software platforms and OS - if it just changed in OS 3.0 then this shows that it must have been an issue that initially Apple thought they could get around. However I think that Mobile Operators will have put pressure on Apple to introduce this as often then end up having to refund the user - but will have already paid out the money to the "premium" number.
I am not sure if "premium" numbers exist in the US as much as they do in Europe and that maybe the reason this is hard to understand.
The RFC for tel:// says to NOT allow autodialing of numbers via the tel: scheme.
So they have to chose between RFC compliance and breaking these few apps.
I hope the chose to ignore the RFC, at least to allow apps to keep dialing if they allow it.
I question whether this is intentional on Apple's part to push users to purchase a new iPhone if they want voice dialing - this problem breaks all of the 3rd party voice dialing apps, making them unsafe and basically useless.
Let's keep up the pressure on Apple to make this a user-configurable setting.
Perhaps you meant newly introduced feature instead of issue?
I don't think you will get Apple to remove the confirmation popup, especially if it is RFC compliance.
Lemmy quote Joel (http://www.joelonsoftware.com/items/2009/06/10c.html) regarding broken apps:
A good platform always has
opportunities for applications that
aren’t just gap-fillers. These are the
kind of application that the vendor is
unlikely ever to consider a core
feature, usually because it’s vertical
— it’s not something everyone is going
to want. There is exactly zero chance
that Apple is ever going to add a
feature to the iPhone for dentists.
Zero.
I would not want some application to make calls, send sms or even connect to internet (living in a country where unlimited mobile data plans are still far in the future) without my consent.
Certainly operator's headache when customers complain about unknown calls on bills.