HOW TO: Extreme iPhone Distribution Automation

Discussion in 'iOS Programming' started by lindahl22, Dec 29, 2010.

  1. lindahl22, Dec 29, 2010
    Last edited: Jan 1, 2011

    lindahl22 macrumors member

    Joined:
    Feb 22, 2008
    #1
    How to automate the process of distributing an application for over the air download.

    The steps are:

    Build and Archive, and Save to Disk
    Upload to Website, replacing old Version
    Update iPhone Website with date

    You could even set it up so that when you send a certain email it will build it so you can write code on the go (using Dropbox and Droptext) and then install on your phone and see the differences.


    **Website File Layout**

    - name.com/index.php *(iPhone Site, optional but recommended)*
    - name.com/application/index.php *(Basic Auto Link Creating Site)*
    - name.com/application/application.ipa *(only file that needs to be updated)*
    - name.com/application/application.plist
    - name.com/application/application57.png
    - name.com/application/application512.png
    - name.com/application/Application_Distribution_Profile.mobileprovision




    **Solution using Automator:**

    **First Action: Run Shell Script** to Build & Archive and save to a .ipa file. It may take a while to figure out how to modify this to fit your situation as it did with me


    Code:
        PROJDIR="/Users/username/Xcode/applicationfolder"
        PROJECT_NAME="application"
        APPLICATION_NAME="Application"
        TARGET_SDK="iphonesimulator4.0"
        PROJECT_BUILDDIR="${PROJDIR}/build/Distribution-iphoneos"
        TARGET_TEST_NAME="application"
        BUILD_HISTORY_DIR="${PROJDIR}/distribution/" #where you want the .ipa to go
        DEVELOPER_NAME="First Last (TMTE9G3NGS)"
        PROVISONING_PROFILE="/Users/username/Xcode/Application_Distribution_Profile.mobileprovision"
         
        # compile project
        echo Building Project
        cd "${PROJDIR}"
        xcodebuild -target "${PROJECT_NAME}" -sdk "${TARGET_SDK}" -configuration Distribution
        
        #Check if build succeeded
        if [ $? != 0 ]
        then
          exit 1
        fi
        
        /usr/bin/xcrun -sdk iphoneos PackageApplication -v "${PROJECT_BUILDDIR}/${PROJECT_NAME}.app" -o "${BUILD_HISTORY_DIR}/${APPLICATION_NAME}.ipa" --sign "${DEVELOPER_NAME}" --embed "${PROVISONING_PROFILE}"
    **Action Two: Get Finder Item**

    The application .ipa file that was just saved.


    **Action Three: Upload to FTP Server**

    http://automatorworld.com/archives/upload-to-ftp/ Use that script to upload the file to where you want it. In my case name.com/application/application.ipa



    **Now for the website end of the things.**

    If you want to have a basic way for users to download the file just put the index.php file (created below), the Application.plist file (created below), the .ipa file and the 57 pixel and 512 pixel image in a folder.

    I have gone one step further and created an iPhone HTML site that you can go to that also shows when the file was last updated. You can create that site using this template: http://snipt.org/vmup/ I had to use the basic site to copy the url that it created for the links to the ipa and mobileprovision. Here is a snippet that I have for the link with an auto updating Last Updated date. For the last updated text to work I had to change the file to a .php

    Code:
        <li><a href="URL FROM BASIC SITE HERE"><span class="menuname">Install Application Name</span><span class="itemarrow"></span></a></li>
        
        <sup>
            Last Updated: <?= date("m/d/Y H:i",filemtime("applicationfolder/application.ipa")) ?>  (TIME ZONE HERE)
        <sup>
    


    Basic Auto link creating application index file:

    PHP:
        <?php  $ipas glob('*.ipa'); $provisioningProfiles glob('*.mobileprovision'); $plists glob('*.plist');  $sr stristr$_SERVER['SCRIPT_URI'], '.php' ) === false ?  $_SERVER['SCRIPT_URI'] : dirname($_SERVER['SCRIPT_URI']) . '/'$provisioningProfile $sr $provisioningProfiles[0]; $ipa $sr $ipas[0]; $itmsUrl urlencode$sr 'index.php?plist=' str_replace'.plist'''$plists[0] ) );   if ($_GET['plist']) { $plist file_get_contentsdirname(__FILE__)  . DIRECTORY_SEPARATOR  preg_replace'/![A-Za-z0-9-_]/i'''$_GET['plist']) . '.plist' ); $plist str_replace('_URL_'$ipa$plist); header('content-type: application/xml'); echo $plist; die(); }   ?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Install iOS App</title> <style type="text/css">  li { padding: 1em; }  </style> </head> <body> <ul> <li><a href="<? echo $provisioningProfile?>">Install Team Provisioning File</a></li> <li><a href="itms-services://?action=download-manifest&url=<? echo $itmsUrl?>"> Install Application</a></li> </ul> </body> </html>
    Application plist file:

    Code:
        <?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>IPA FILE LINK HERE</string>
        				</dict>
        				<dict>
        					<key>kind</key>
        					<string>full-size-image</string>
        					<key>needs-shine</key>
        					<true/>
        					<key>url</key>
        					<string>URL FOR 512 PIXEL IMAGE HERE</string>
        				</dict>
        				<dict>
        					<key>kind</key>
        					<string>display-image</string>
        					<key>needs-shine</key>
        					<true/>
        					<key>url</key>
        					<string>URL FOR 57 PIXEL IMAGE HERE</string>
        				</dict>
        			</array>
        			<key>metadata</key>
        			<dict>
        				<key>bundle-identifier</key>
        				<string>COM.COMPANY.APPLICATION</string>
        				<key>bundle-version</key>
        				<string>VERSION NUMBER HERE (YOU DON'T REALLY NEED TO UPDATE IT UNLESS YOU WANT TO)</string>
        				<key>kind</key>
        				<string>software</string>
        				<key>title</key>
        				<string>APPLICATION NAME HERE</string>
        			</dict>
        		</dict>
        	</array>
        </dict>
        </plist>
    
     
  2. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #2
    Where does iTunes Connect fit into your puzzle?
     
  3. ulbador macrumors 68000

    ulbador

    Joined:
    Feb 11, 2010
    #3
    Without server side scripting, Javascript will do this very very easily...

    Code:
    <script type="text/javascript">
    document.write(document.lastModified);
    </script>
    
    Of course, every browser may treat that differently.. Much easier with PHP/Perl/JSP/ASP/etc on the server side.
     
  4. lindahl22, Dec 29, 2010
    Last edited by a moderator: Dec 30, 2010

    lindahl22 thread starter macrumors member

    Joined:
    Feb 22, 2008
    #4
    It does not. This is Ad Hoc Distribution. For beta testers and myself. Users install the app via a website not the app store. (app can only be installed on devices that have the team provisioning profile, and to have that they need to be added by their UDID.)

    Awesome! This will help me out a ton. Currently I just have text in the HTML file when I put this in it's place how do I link it to the correct file?

    The modified date needs to be for the linked .ipa file not the index.HTML file

    How do I do it on the server side using the easiest method? Do I need to change to a index.php :( ?
     
  5. ulbador macrumors 68000

    ulbador

    Joined:
    Feb 11, 2010
    #5
    I have no idea how to automate Automator to do text entry and stuff.

    It's pretty easy stuff if you can run something server side. You wouldn't even have to change anything, just upload the file, and the index script would pick up the change and display the new file. Of course, this would take some scripting knowledge on your part.
     
  6. lindahl22 thread starter macrumors member

    Joined:
    Feb 22, 2008
    #6
    What would the script look like if the file was in the same folder as the index.HTML file and it was labeled app.ipa
     
  7. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #7
    Sorry. Must've missed that in the OP. ;)
     
  8. ulbador macrumors 68000

    ulbador

    Joined:
    Feb 11, 2010
    #8
    Something like:

    Code:
    <a href='app.ipa'>Download App</a> Last Updated: <?= date("m/d/Y H:i:s",filemtime("app.ipa”)); ?>
    
    Of course the file would PROBABLY have to be named index.php then and PHP support would have to be enabled on the server.
     
  9. lindahl22, Dec 30, 2010
    Last edited: Dec 30, 2010

    lindahl22 thread starter macrumors member

    Joined:
    Feb 22, 2008
    #9
    Here is the index.html file that I am using: http://snipt.org/vmup/

    Okay so I changed it from index.html to index.php (still has same code that was probably html) and I added the line and it returns this error:
    Parse error: syntax error, unexpected T_STRING

    I also don't need it to link to the file just show when the file was last updated.
     
  10. ulbador macrumors 68000

    ulbador

    Joined:
    Feb 11, 2010
    #10
    It looks like some "smart" quotes got applied, probably when I copied and pasted:

    Code:
    <?= date("m/d/Y H:i:s",filemtime("app.ipa")) ?>
    
    Just drop that whereever you want to display the last file modification time. Those are all just regular old ", not the smart quotes that sometimes happen.
     
  11. lindahl22 thread starter macrumors member

    Joined:
    Feb 22, 2008
    #11
    AWESOME!! It works! Thanks so much! :D
     
  12. lindahl22 thread starter macrumors member

    Joined:
    Feb 22, 2008
    #12
    Now for the hardest part, how can I build and archive, and save the application to disk?

    Here is an article that attempts to explain how to do this. However after trying to run this code:

    Code:
    PROJDIR="/Users/lindahl22/Dropbox/Xcode/Book/App (rewrite)"
    PROJECT_NAME=app
    TARGET_SDK="iphonesimulator4.0"
    PROJECT_BUILDDIR="${PROJDIR}/build/Release-iphoneos"
    TARGET_TEST_NAME="App"
    BUILD_HISTORY_DIR="/Users/lindahl22/Dropbox/Xcode/Book/App (rewrite)/distribution"
    DEVELOPER_NAME="lindahl22"
    PROVISONING_PROFILE= "/Users/lindahl22/Dropbox/Xcode/App_Distribution_Profile.mobileprovision"
     
    # compile project
    echo Building Project
    cd "${PROJDIR}"
    xcodebuild -target "${PROJECT_NAME}" -sdk "${TARGET_SDK}" -configuration Release
    
    #Check if build succeeded
    if [ $? != 0 ]
    then
      exit 1
    fi
    
    /usr/bin/xcrun -sdk iphoneos PackageApplication -v "${PROJECT_BUILDDIR}/${APPLICATION_NAME}.app" -o "${BUILD_HISTORY_DIR}/${APPLICATION_NAME}.ipa" --sign "${DEVELOPER_NAME}" --embed "${PROVISONING_PROFILE}"
    I run this code through the "Run Shell Script" action in automator, with the shell being /bin/bash and passing inputs as arguments I get the following error:
    However everyone has read permissions, changing everyone to read/write doesn't help. Got any advice? Thanks!
     
  13. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #13
    There is an extra space after the = and before the ". Remove it or the shell will interpret the line as an attempt to run the command /blahblah/App_Distribution_Profile.mobileprovision with an env-var of PROVISONING_PROFILE assigned the value "".

    The original script it was taken from also (mistakenly) contains extra spaces around one of its ='s.
    http://blog.octo.com/wp-content/uploads/2010/11/build.txt
     
  14. lindahl22 thread starter macrumors member

    Joined:
    Feb 22, 2008
    #14
    Nice thanks, however now I have another error :(

    warning: compiler 'com.apple.compilers.gcc.4_0' is based on missing compiler 'com.apple.compilers.gcc.4_0'
     
  15. lindahl22 thread starter macrumors member

    Joined:
    Feb 22, 2008
    #15
    Do you know if I can just drop this code into automator as a shell action? I am getting an error.
     
  16. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #16
    The code as posted has bugs, so I don't see how.

    Or are you asking "If I fix this code, can I drop it into Automator as a shell action?" To which I'd have to say "Post the code".


    Post the error, and identify the program where the error appears. We can't see your screen, so the content and the context of this error are unknowable unless you tell us.
     
  17. Luke Redpath macrumors 6502a

    Joined:
    Nov 9, 2007
    Location:
    Colchester, UK
    #17
    Perhaps something like testflightapp.com would be of some use to you when it exits private beta (soon). I don't work for them but I have been using the beta and it's very nice

    In the meantime, if you are familiar with Ruby and Rake, you could use my betabuilder gem, which handles the process of building and creating an IPA and then distributing using one of the built in distribution strategies or one of your own. It currently supports web based deployment using SCP (with an HTML index page and manifest plist) or to TestFlight using their upload API.

    It means I can deploy a new beta of my app from the terminal with a single command (or via Xcode using a Run Script build phase).

    It's still a work in progress but its open source and available on Github:
    https://github.com/lukeredpath/betabuilder
     
  18. lindahl22, Dec 31, 2010
    Last edited: Jan 1, 2011

    lindahl22 thread starter macrumors member

    Joined:
    Feb 22, 2008
    #18
    fixed it... posting result soon
     
  19. lindahl22 thread starter macrumors member

    Joined:
    Feb 22, 2008
    #19
    Yes I am aware of that solution. I prefer mine better. I currently am deploying beta apps to testers via a website. I just want to automate this process so I can edit code on the go from my iPhone, send an email to my machine to run the Automator action to update the sites app file so I can download the changed app on my phone. The only thing I need is the build and archive and save process to be able to be done in Automator.
     
  20. nomar383 macrumors 65816

    nomar383

    Joined:
    Jan 29, 2008
    Location:
    Rexburg, ID
    #20
    This. Looks. Awesome.

    I've been using Hockey and have grown tired of building the IPA/manifest and then uploading it manually with Cyberduck. Five minutes of my time is too much!

    I'll try your solution tonight :)
     

Share This Page