Let me explain for beginners that when developing for iOS to install on a device, most of the time you build an application in development mode, i.e. only for myself.
But at some point it is required to begin to give out to the customer the result of the work to “look”.
To do this, use a special type of assembly AdHoc Distribution. You need to go to Apple and create a distribution provisioning profile. After that, collect the application, signing it with this profile. The profile contains all the identifiers of the devices to which this application is planned to be installed at this stage. As a result, when building for AdHoc, Xcode creates a file with the .ipa extension, which can already be installed on all devices specified in the profile. For example through iTunes.
The question arises how best to transfer the resulting assembly to your client. Yes, you can simply send the file by mail for example, or put it on a file sharing service and let the poor fellow install it himself through iTunes on his device. But if you value the time of your client or you are too lazy to explain how to do it, well, or you are just a nice and pleasant person, then you should think about whether there is another, more convenient way.
On one of these methods, with the automation of the issuance of Xcode read under the cut!
')
On this path, there have long been enough laborers who, it must be admitted, are not quite good at coping with this task. One of the well-deserved services is for example TestFlight. The bottom line is that they enable your client (or beta testers) to install your application through their service. To do this, all beta testers must install their application on their devices. And later, when they receive by mail a notification about the release of the next build of yours, they launch this application, find your update there and install it for themselves through their interface.
But this scheme, I would say, is not perfect.
Firstly, this implies that you will still have to explain to the customer how to register with TestFlight, how to install their application to themselves (it is not in the AppStore, the installation takes place from their website).
Also in this case, we do not simplify our lives on our side - each time you first need to build the next AdHoc build in Xcode, then in its Organizer window select the AdHoc distribution option, specify the correct profile and save the .ipa file to disk. Then go to the site TestFlight, and fill in this .ipa, write a comment, do not forget to set permissions for those to whom this build is intended. Very, very many gestures.
In addition, often the service is not available, or simply the download speed is such that the installation process of the application falls down on timeout.
It is especially not pleasant to hear from the customer that for some reason your application is not installed, when you know for sure that this is not the case, and you checked the download from TestFlight yourself.
As a result, for me the last straw was the fact that they do not yet support the installation on iOS7, under which we are developing our last project.
And then we came to a decision that was easier for both parties.
Now all the above procedure is reduced to two steps. I, as before, choose in Xcode archive build (as usually build under AdHoc). Then I write to the customer that the application is updated. Everything.
Now the customer simply comes from his device to a specific address on the Internet (the address does not change and he can save it to your bookmarks). A pop-up window appears - if you want to install the application, of course it wants, the application is being installed. Everyone is happy.
And that's what you need to do to come to this nirvana.
The magic of installing applications through a mobile browser.
First, a little about the magic that allows you to install applications by URL.
This is a long time ago existing opportunity, and all these services, ala TestFlight, are actually based on it.
There is a protocol
called itms-services:, with the help of which, on iOS in particular, applications are installed from a browser. The protocol implies that a .plist file with a certain structure will be loaded, including, among other things, a link to the .ipa file. As a result, it is processed by iOS as an application installation request.
Those. we first need to create some simple (or not so much as you want) HTML page. Near to put our magic .plist file and .ipa build.
Here I mean that Amazon S3 storage is used for such storage. Creating your account on
Amazon Web Services is easy and I will not describe it here. Storage and distribution of such scanty volumes will come to you in some pennies that I am lazy to count here, this is not about that now.
So create our files, this is how our HTML may look. Let's call it, say index.html. The main
thing is that it contains links on
itms-services: protocol
<html> <head> <title>My Ad-Hoc Distribution Site</title> <style> li{font-size:60pt margin:20px 0} </style> <meta name="viewport" content="width=device-width" /> <meta name="apple-mobile-web-app-capable" content="yes" /> </head> <body> <ul> <li><a href="itms-services://?action=download-manifest&url=http://mybucketname.s3.amazonaws.com/MyApp1.plist"> MyApp1</a></li> <li><a href="itms-services://?action=download-manifest&url=http://mybucketname.s3.amazonaws.com/MyApp2.plist"> MyApp2</a></li> </ul> </body> </html>
As you can see, the list is implemented here, because we do not want to be limited to just one application, we will have several of them. And each of them is set for a separate link.
In the address
itms-services: // ... itself, you only need to change
mybucketname and the name of the .plist file. Those. replace them accordingly with the name of your bucket on Amazon S3, where you put all this, and the name of your .plist (the file name has no meaning and may not coincide with the name of the application).
The .plist itself looks like this:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>items</key> <array> <dict> <key>assets</key> <array> <dict> <key>kind</key> <string>software-package</string> <key>url</key> <string>http://mybucketname.s3.amazonaws.com/MyApp1.ipa</string> </dict> </array> <key>metadata</key> <dict> <key>bundle-identifier</key> <string>com.mycoolcompanyname.myapp1</string> <key>bundle-version</key> <string>1.0</string> <key>kind</key> <string>software</string> <key>title</key> <string>MyApp1</string> </dict> </dict> </array> </dict> </plist>
Understandably, here, too, you need to replace the name
mybucketname in the
software-package key string. And specify your .ipa file name instead of MyApp1.ipa. And do not forget to change the key string
bundle-identifier . Instead of
com.mycoolcompanyname.myapp1, enter your bundle id that you used when building this application in Xcode.
Well, specify the desired application name in the
title key.
Fine! Already, you can now build the application under AdHoc distribution and handles it on S3 in this bucket. After that it can be installed via the link
mybucketname.s3.amazonaws.com/index.html by opening it in a mobile browser.
By the way, I recommend the CyberDuck application for manual uploading on S3. He himself stopped on it, as the most convenient version for MacOs.
One important detail, do not forget to set access rights to the .ipa file to public-read. In CyberDuck, this is done by right-clicking on the file> Info and adding an Everybody group with Read rights.
But this option is also not for the lazy, so go ahead.
Automation in Xcode. We write a post-actions script.
So that absolutely nothing had to be done, we will write a small script.
In Xcode, it is possible to cram your scripts at almost all stages when building an application.
We, in this case, are only interested in the assembly to the archive (this is how we always build the application for AdHoc Distribution).
Therefore, we add a post-action at the final stage for this scheme.
Go to Xcode, open the schema editing dialog. Next will be a few explanatory screenshots. They are made in the beta version of Xcode 5, but Xcode 4.6 this feature is also present, and the interface in this part is almost the same.
So click on the name of your target in the place where it is indicated in the upper left of the main Xcode window. In the dialog that appears, select the item Edit Scheme ...
In the schematic editing dialog, we find the Arhive scheme and click the small triangle next to its name, several sub-items will unfold. The last one will be the Post-actions we need.

In the box in this window, select the name of your target. This means that all variables in the script, such as $ {PRODUCT_NAME}, for example, will take the corresponding ones.
Here we use this skipt:
SIGNING_IDENTITY="iPhone Distribution: MyCoolCompanyName (G4DHGXDY2)" PROVISIONING_PROFILE="${HOME}/Library/MobileDevice/Provisioning Profiles/20DB9849-4CFE-4005-81F6-1A594119839B.mobileprovision" LOG="/tmp/post-build-upload-to-s3.log" DATE=$( /bin/date +"%Y-%m-%d" ) ARCHIVE=$( /bin/ls -t "${HOME}/Library/Developer/Xcode/Archives/${DATE}" | /usr/bin/grep xcarchive | /usr/bin/sed -n 1p ) DSYM="${HOME}/Library/Developer/Xcode/Archives/${DATE}/${ARCHIVE}/dSYMs/${PRODUCT_NAME}.app.dSYM" APP="${HOME}/Library/Developer/Xcode/Archives/${DATE}/${ARCHIVE}/Products/Applications/${PRODUCT_NAME}.app" /usr/bin/open -a /Applications/Utilities/Console.app $LOG echo -n "Creating .ipa for ${PRODUCT_NAME}... " > $LOG /bin/rm "/tmp/${PRODUCT_NAME}.ipa" /usr/bin/xcrun -sdk iphoneos PackageApplication "${APP}" -o "/tmp/${PRODUCT_NAME}.ipa" --sign "${SIGNING_IDENTITY}" --embed "${PROVISIONING_PROFILE}" >> $LOG echo "Created .ipa for ${PRODUCT_NAME}" >> $LOG echo -n "Uploading to S3... " >> $LOG /opt/local/bin/s3cmd put --acl-public --force --guess-mime-type /tmp/${PRODUCT_NAME}.ipa "s3://mybucketname/MyApp.ipa" >> $LOG echo "Done." >> $LOG /usr/bin/open "https://basecamp.com/path-to-your-project-to-let-people-know-of-new-build"
So, in the opened window we see / bin / sh in the first input line. We leave there this value.
In the empty field below copy-paste this script.
Now we have to edit a couple of values in it for your configuration. Namely, you need to set the correct value in the SIGNING_IDENTITY variable and set the correct link to your current provisioning profile in the PROVISIONING_PROFILE variable.
I do it like this. Save here - click OK at the bottom, go to the project's Build Settings and find the Code Signing Identity section there.
It has all the necessary values. But “helpful” Xcode shows them in a human-readable form and also does not allow them to be allocated right there.
Right click on the name of your signing identity (something like iPhone Distribution: ...). A pop-up will open, in which the Other option will be at the bottom ... We select it and here it is our entire set of parameters in text form and even carefully selected.
In previous versions of Xcode, it looked like this:
iPhone Distribution: MyCoolCompanyName (G4DHGXDY2) 20DB9849-4CFE-4005-81F6-1A594119839B
Accordingly, the first line fits into the SIGNING_IDENTITY variable in the script.
And the second is the code of your profile - just replace with it the highlighted part in the address for the variable PROVISIONING_PROFILE, as shown below.
PROVISIONING_PROFILE = "$ {HOME} / Library / MobileDevice / Provisioning Profiles /
20DB9849-4CFE-4005-81F6-1A594119839B .mobileprovision"
In the new Xcode 5 - these two values are separated into separate entries in the Code Signing Identity section. Therefore, the same action must be done twice. First copy the identity name, then the code for the provisioning profile.
As you can see, the script performs two simple steps. First, the resulting .app file turns the file into .ipa. Then this .ipa fills in on S3. In the process of the script, a .log file is also created where everything that happens is written. This .log file is placed in a temporary folder (the same place as .ipa) and opened by the Console system utility so that we can see the progress of the script.
There is only one secret left - how does the fill on S3 work?
We flood assembly on Amazon S3 by means of a script
Actually, not really, let's not mess with manual fill on S3, this is troublesome, we will use the finished utility for this (
S3cmd ).
We are on a Mac, so we put it through
MacPorts . Who does not know, this is a tool that allows you to put on the poppy all sorts of not inherent Linux Linux delights. If you do not have MacPorts installed, we put one of the links for your MacOS version (
Mountain Lion ,
Lion or
Snow Leopard ).
Next we install the s3cmd utility itself. With MacPorts, this is easy to do.
In the terminal we type:
sudo port install s3cmd
You will be prompted to enter a password, enter the administrator password, and the installation will begin. It takes about a minute.
Everything, the utility is installed, now let's tell her our S3 password (when you register at
Amazon Web Services ) you will be given a key and a secret code (do not ask what is the difference between these two concepts, but you need both).
So we type in the terminal:
s3cmd --configure
and we will be asked to answer a few questions regarding our desired configuration, including asking to enter the key and secret code.
For example, it looks like this:
Enter new values or accept defaults in brackets with Enter. Refer to user manual for detailed description of all options. Access key and Secret key are your identifiers for Amazon S3 Access Key: XXXXX XXX Secret Key: YYYY YYY Encryption password is used to protect your files from reading by unauthorized persons while in transfer to S3 Encryption password: Path to GPG program: When using secure HTTPS protocol all communication with Amazon S3 servers is protected from 3rd party eavesdropping. This method is slower than plain HTTP and can't be used if you're behind a proxy Use HTTPS protocol [No]: No On some networks all internet access must go through a HTTP proxy. Try setting it here if you can't conect to S3 directly HTTP Proxy server name: New settings: Access Key: XXXXX XXX Secret Key: YYYY YYY Encryption password: Path to GPG program: None Use HTTPS protocol: False HTTP Proxy server name: HTTP Proxy server port: 0 Test access with supplied credentials? [Y/n] Y Please wait... Success. Your access key and secret key worked fine :-) Now verifying that encryption works... Not configured. Never mind. Save settings? [y/N] y Configuration saved to '/Users/st/.s3cfg'
Well, that's all, now in the script you only need to correct the name of your S3 bucket and the name of the application in the line:
/ opt / local / bin / s3cmd put --acl-public --force --guess-mime-type /tmp/${PRODUCT_NAME}.ipa "s3: //
mybucketname /
MyApp .ipa" >> $ LOG
After that - you can simply run the build under archive (Xcode> Product> Archive) and everything should work. Your application will be flooded at the specified address.