iPhone handling dynamic URLs - iphone

My iPhone app consumes a Java web service in order to get data. At my company we have 3 environments - development, testing, production. Each environment's URL, that points to the web service, is different. Thus, each time we promote the project to the next environment I must change the hard-coded URL in the iPhone code to match that of the targeted environment. Has anyone devised a strategy to handle this either on the iPhone itself or in the service layer?

Try storing the variable part of the URL in your app's info.plist file. You can change that w/o rebuilding.
If more config changes are needed, VCS branching may be what you need.

You might consider the following approach:
When you start up your app, or rather when you have established that a network connection is possible, you send your device id to the server.
The server checks your device id against a list and tells your app whether the user talking to the server is allowed to see development and testing content.
If your device is allowed to, you provide an interface for the user to change whether they want to see development, testing or production content. Store that in NSUserDefaults
Depending on user choice, the corresponding url is used to talk to your server. To be sure, you can include your device id check here, too.
This approach has the benefit that you can allow clients to see testing content... without ever having to update or change their app. And you can revoke that permission anytime.

Related

Remote Wipe out an iOS Application

I have developed an iPad application and I have distributed that application to my clients. Now my clients ask what will happen if their iPad lost or stolen. My iPad application has very sensitive data. So they need to wipe out remotely if iPad is stolen or lost.
I found two solutions.
One is configure 'Find My iPad' in each iPad with same apple account.
Second one is configuring MDM server with push notifications.
If I'm going to configure MDM server I need to contact third party vendor who supports push notifications service of apple or I need to buy Lion Server and configure profile Manager.
Can some one tell me what is the best solution to implement and pros and cons of these two options.
Push notifications won't help you here - they only will pop up a message to the user, you cannot influence the app from them.
Possible solutions:
Protect your app with username / password: Each user should choose a username and password, store those in the keychain and check on app start. Of course you should also encrypt all data with the password when storing it to the device.
Like said above, implement a server request which gets the unique id of the installed app (of course you'd have to create one first on first app startup), returns whether the app is reported as stolen and then either do nothing or delete all data. I'd be careful about deleting though in case there was an error somewhere in your implementation and you wipe out a 'normal' application's data. Also in this case I'd encrypt any sensitive data that is stored to the device. This solution also won't work when the app is offline, of course.
Just make a web service and get response from server, and after getting response , run your application otherwise kill.
if(stolen)
exit(0);
else
run

App with different functionality based on the user's country

I need to develop an application that will behave differently depending on the user's country. Let's say, if the user is in France, some functionality would be available. But, if the user were from India, he would be able to acces a different set of functionality.
If it were only language based restrictions, I could switch functionality using NSLocale class methods. But my functionality is really dependent on the user's country because of licensing and legal reasons.
What are the best practices for dealing with this situation?
For each market where you have specific requirements due to market-specific licensing or legal issues, you can create a separate app in iTunes Connect and make it available for download only in the relevant market. And if you need to, this also allows you to provide a market-specific EULA. It's a big maintenance burden, but it would ensure that only users in a given market can access the app.
Note that in XCode you can fairly easily build, deploy and publish multiple versions of your project built from different configurations (XCode calls this "Targets"), so you could still achieve this in a single codebase by simply adding some preprocessor definitions in the relevant target definitions and putting #ifdef in your code where you want differentiated logic.
A 3rd party app has no access whatsoever to any information about the user of the device or access to the iTunes account. There is no way to know the user's true country. At any given time, the device may not even be associated with any one person. An iPod touch, for example, may have no user logged into any iTunes account. The same device can ultimately be logged into one of several different accounts.
All you have access to is the user's current GPS location (if the user allows your app to access that information) or their current locale.
Basically, there is no way to do what you need. Of course you could prompt the user but obviously there is no way to verify this information.

User Experience Flow on iOS

Under iOS there are several built in hooks for launching service-specific apps based on a passed URL for example handling http:// (to Safari), handling addresses (to google maps) and phone numbers (to the built in phone app). Several apps make it a standard practice of implementing the rarely used ability (for most apps) to register your own service prefix. Two handy apps that come to mind that implement this are facebook:// and skype:// and it is a handy way to add quasi-integration with their app into yours. Skype even does this on most desktop os's so you can literally run the command line skype://555-1234. You can also check for these registered service prefixes and expose useful menu choices in your apps but I digress.
As with all of these service handlers built in or not, the problem under iOS is that you lose the user and the flow of their experience ends with the phone app (for example). Yes you can embed web views to handle some cases but things like the phone app still win out.
I propose that it would be great that if iOS apps were handed a trailing URL as part of their arguments (even if they accept and might handle say two args already) that by convention when our app is exited we launch the trailing URL we may have been optionally handed. If fully supported in some manner this would allow for multi-app integration and an extended user experience flow-wise. I'm imagining being able for example to launch a phone call and have the user return to my app when it is finished by launching my app again using the URL I passed it such as "myapp://return-context-values". Obviously this could be taken further.
Does such a mechanism already exist in some way? If not I'd like to hear your thoughts on the idea.
Check out x-callback-url.com, it proposes precisely what you're suggesting.
And yes, I think it would be great. You're much more likely to pass a request to me if you know you'll get the focus back, and vice versa.

How do I upload files using http/ftp to iphone/ipad? (Eg. ifile, goodreader)

Is there any good advice on uploading files to the device? I've seen many apps create a http server on 80 or 8080 to upload files. Does that mean I have to implement a server too?
Are there any 3rd-party libraries? (Preferably open-source and non-GPL)
EDIT: I am going to upgrade files in the app for specific devices in a corporate environment, so the ipad pulling files from a central server is also an alternative. But I would have to send messages to these ipads to tell them to fetch those files.
But I would have to send messages to
these ipads to tell them to fetch
those files.
Push Notification Programming Guide
Or mail with custom URL scheme for launching your application.
iOS Application Programming Guide - Implementing Custom URL Schemes
I assume what you want is a kind of automatic update. An app do something by order from server without user's manual operation.
I don't know enterprise-license specific feature of iOS. But I believe there's no such enterprise-specific APIs. And as I know, automatic update is almost impossible. Because,
There is no system-level support for automatic update. (yet?)
So messaging and fetching feature should be implemented in app.
But no app is guaranteed to run in background for long time.
And also user can turn off any app at any time.
There is no way to send message to an app which is not running.
Even you can send, there is no way to address each client form the server.
If your app is running, sending message or commanding them to fetch or do anything is just a simple work. The problem is there is no regular way to force them always keep alive. Even under situations like OS reboot or abnormal termination.
However there is an alternative. Just registering app as VOIP app like Skype. OS does not keep the app running too, but will monitor specific socket port, and will wake your app when the socket receives some message. For more details, see here: http://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/BackgroundExecution/BackgroundExecution.html#//apple_ref/doc/uid/TP40007072-CH5-SW15
In AppStore, an app using VOIP for other purpose like automatic update will not be passed, but you have no need to concern about it.
And other way to send message to device without running app is push notification. This is a feature supported in system-level. But this is not designed to commanding app. This is designed to send textual message. So If your app is not running, the message will be displayed to user. However, you can guide the user to start the app by sending push notification.
As a final option, you can request some feature to Apple for enterprise environment. If your company is big enough to get an enterprise license, Apple will consider your feature request seriously.
If you decided to use VOIP method, I'm sorry I can't help you any more. I have no experience of implementing this kind of app. But it should not so hard.
However hard part is server. It definitely require custom server program which keeps TCP/IP connection. Regular HTTP server cannot be used. Because HTTP itself is designed as not to keep TCP/IP connection. You have to build this kind of server yourself from scratch. You'll have to handle lower level TCP/IP transmissions.
There are a few solutions(both of free/commercial) for this kind of server, but none of are popular because this kind of server regularly needs full customization. So there's nothing to re-use or share.
However I believe this is most suitable implementation for your app.
If you can satisfy automatic update only when the app is running, you can archive it by polling server status from the client periodically.
This is easy to implement because you can use regular HTTP servers for this. Client connect and download recent updates from central server periodically. If there is a new update, just fetch and do what you want. And the app is launched, just check the update at first. Prevent all operation until update applied.
This is regular way. Most of applications are built with this method. In this case, you have no need to implement server or hard thing.
However applying speed of update is depend on polling period.
(Edit)
I couldn't care about private APIs. Because your app is not for AppStore, so you can use private API's freely. (This is different thing with jail-breaking. There are so many hidden features by excluded from documentation) I don't know about private APIs, but it's possible there is some API which enable the support for keep-alive of the app.
However, this reverse engineering work is so painful unless you're born to hack.
You may try to use the following open-source in your project:
http://code.google.com/p/cocoahttpserver/
https://github.com/robin/cocoa-web-resource/wiki
Apple has some sample code on their website that details exactly what you're looking for:
http://developer.apple.com/library/mac/samplecode/CocoaHTTPServer/CocoaHTTPServer.zip
So you have a couple options:
You could distribute your app wirelessly within your organization and push new content out as app updates. Apple provides this option to their Enterprise Developers.
Wireless App Distribution
iPhone enables enterprises to securely host and wirelessly distribute in-house apps to employees over Wi-Fi and 3G. Apps can be updated without requiring users to connect to their computers. In-house apps can be hosted on any web server accessible to users. Users simply tap on a URL to install apps wirelessly without needing to connect to their computers.
The alternative is you configure the app to fetch the updated data. You describe adding an HTTP server to the iOS device, but there's no way the server can receive data when the app isn't running. Given your needs, it would probably work better to embed a web client in your app instead.
If I was in your shoes (and option #1 didn't work), I'd use ASIHTTPRequest to check with a server at launch/daily. If there are new updates, the app could then either prompt the user that there are new data files to download, or it could just silently download them in a background thread.
UPDATED: Perhaps I should have been more explicit about how to do #2. You can configure the download so it isn't interrupted when the user quits the app (you don't need to do a Voip hack). Check out the Completing a Finite Length Task in the Background section in the iOS Programming Guide.
There are http server sample codes from Apple and open source community such as cocoahttpserver TouchHTTPD.
You can upload file to the http server on iphone.
Here's a blog and screen-shots about running cocoahttpserver and upload file to iphone.
The Python CGIHTTPServer allows you to create a server in 0 lines of code:
jcomeau#intrepid:~/rentacoder/bin2txt$ python -m CGIHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
Actually implementing a script to parse the input and save the file would take a little more effort.
[later]
OK, so forget about that, Apple doesn't allow it. See Local server on iPad for the iPad at least.

How to make a secure login using UDID or device token?

So I'm making an app where I want the users to be able add, edit and rate content, but I do not want to force them to register. Instead I was planning on just using their device id or device token to identify them. I'm planning on making both an iPhone and Android version, so I'm looking for a general solution, but the iPhone version has higher priority, so an iPhone specific solution would also be welcome.
The problem is that I don't want just anyone to be able to use my web service by sending a phony device id or someone else's device id.
How would the client prove to the server that it is providing the correct device id?
In theory, you cannot. A device ID is not particularly secret, and in most cases, it can be easily spoofed. As for Android, there's no reliable device ID on that OS at all - see the gory details here: Is there a unique Android device ID?
All you can rely upon is security by obscurity - hoping that no one will be determined enough to reverse-engineer the code and analyse the authentication protocol. And not disclosing the code is not an option - you are distributing the app after all.
That said, one not-particularly-secure auth method would be - send the device ID and a hash of device ID concatenated with a secret, hard-coded in the client code string (the shared secret). The service would contain a copy of the secret, recalculate the hash (using the device ID provided) and match the hashes. Not breakable by protocol analysis, only by digging in the code for the secret. Vulnerable to replay attacks though. Feel free to obfuscate the secret in the code - e. g. combine it together from parts stored in separate places right before use.
For a stronger solution, authenticate users, not devices. This is up to your customers, and depends on the nature of the business.
I am no Android expert but the IMEI code I think is unique for the device. I dont know though how you can read it and transmit it.