Distributing iPhone Apps Using OTA Does Not Work

by Stephen Dewitsky posted on February 25 2011 13:02

So the best kept secret of iPhone OS 4.0 is slowly becoming a well known and most useful process. Wireless Distribution or Over the Air (OTA) Distribution model can be officially referenced via Distributing Enterprise Apps for iOS 4 Devices. This new model removes the overhead of educating a client, or application tester, on the nuances of installing an Ad Hoc Distribution. Provisioning files and application build are bundled together in an .ipa, or iPhone Application Archive, which can be installed on device with or without iTunes. Installing through iTunes is as simple as Drag n Drop, then Sync. Installing OTA is as simple as tapping a link from the web browser.

The setup process, however, is still bestowed on the development team. Checkout the guidelines on Apple's reference page: Distributing Enterprise Apps for iOS 4 Devices, or some nicely packaged tutorials; such as Distribute Ad Hoc Applications Over the Air (OTA). I will relinquish the details of how to accomplish the distribution to the reference guide and focus on what to do when the iPhone OTA distribution does not work.

When attempting to configure the iPhone Wireless Distribution I encountered 3 hurdles on my way to success.

  1. Problem: After executing Build and Archive, Organizer does not automatically open

    Solution: Make sure your application identifier matches the id linked to your Ad Hoc provision file

    This may not be a pertinent step to a successful distribution, but I include here because the behavior of XCode was affected. Each Ad Hoc build is configured to use an Ad Hoc provision file which in turn is linked to an Application Identifier configured in the program portal. These identifiers are usually reverse domain in the form of "com.yourcompany.*". When creating a new XCode project, the default application id is something like "com.yourcompany.${PRODUCT_NAME:rfc1034identifier}". Modify the identifier to match the configuration set in your program portal. After the "Build and Archive" process completes, Organizer should open automatically with your new "Archived Application" listed below.

  2. Problem: Download Application link does not work

    Solution: Make sure your web server has the correct MIME type set for both .plist and .ipa files

    Property List (.plist) and iPhone Application Archive (.ipa) files are served to the iPhone OS devices from your web server. Most web servers, in my case IIS, do not have a MIME type mapping for these file types. When tapping the "download application" link from the HTML page, the page did not initiate a download. The download does not work. It just sat there as if I did not tap at all. In IIS, when the MIME type is not recognized the web server delivers a 404 Page not Found error. The download will not start because the web server thinks the file does not exist, even though we know it does. Since the "download application link" uses the itms-services protocol, the server error does not get relayed to the user interface. Adding the MIME type to the web server's list corrects this problem and can be verified using a web browser. The MIME types for these files are:

    .plist - text/xml
    .ipa - application/octet-stream

  3. Problem: Download Application link still does not work

    Solution: Remove any spaces from your absolute URL's file name and web folder structure

    I beat my head against the wall on this for a while. It seems logical that a project file or web folder could have spaces in the name since we have a function of URL Encoding, but URL Encoded resources appeared to be the make it or break your head on the wall factor. I had %20 URL Encoded spaces in my web folder hosting the .ipa and .plist files and also had spaces in the file names. Removing the spaces made that "download application link" WORK. I can't explain it nor did I submit a bug report. Could be by design or an oversight. Just check it out for your own sanity.

Having an OTA distribution for iPhone work for you is a great relief on your application workflow. You can now send your testers an email with a link to a web page which holds the capabilities necessary to install your latest version of an iPhone app. As of today, I was successfully able to implement the iPhone OTA distribution using a regular iOS Developer Program account. I bring up this fact because Apple's reference document Distributing Enterprise Apps for iOS 4 Devices clearly states that this model is intended for usage with the iOS Enterprise Program and that the first step in "The process for deploying an in-house apps is: Register for the iOS Developer Enterprise Program with Apple". We all hate to have our heart broken. I just want you to be prepared for a day when the mercy of Apple may not be so kind and the privilege of using wireless distributions with iOS Developer accounts could be revoked without any notice.

Tags: , , , , ,

iPhone | OTA | Provision | Wireless Distribution | XCode

Distributed Architecture: Part 2 - Do you include messaging into your SOA? If not then you don't have a SOA!

by Michael Hodgdon posted on December 15 2010 01:45



I was pretty amazed by a presentation given by Udi Dahan. Udi focuses on addressing where the industry missed the boat with SOA.  He essentially says that a majority of the “SOA” implementations out there are nothing more than glorified RPC systems.  The idea being that contracts and schemas are great, but if you are dependent and synchronous in your calls you are chaining way too much.  If any service breaks down in that chain your SOA tenants are completely missed.  I will let his talk speak for the work as it’s his work and not mine J.  A summary of how messaging fulfills the SOA tenants is as follows:

Autonomous – By passing messages and handling requests and responses out of band you keep all of your services isolated and autonomous.

Schemas and Content – Because you are working with messages and the data that is within them (i.e. contracts) you have this by default.  The topic is messages that are passed through the infrastructure. Boundaries – Messages being the topic sent through the infrascture allow you to maintain policy and routing based on those messages.  This allows you to maintain boundaries and can keep your services fenced.

Follow this link to find his talk on msdn.

Tags: ,

Error Starting Executable No provisioned iPhone OS device is connected

by Stephen Dewitsky posted on December 6 2010 12:01

Well, here we are again.  Everything looks good but nothing acts right.  We just plugged the iPhone or iPod into the USB port and press "Build and Debug", expecting to test the latest changes of our app on a device.  However the effort comes to a screeching halt with a notice from XCode stating:

Error Starting Executable
No provisioned iPhone OS device is connected

 

 

What am I missing?

Step A. Plug USB cable into iPhone
Number 2. Plug USB cable into XCode
And Third. Press "Build and Debug"

OOps, I forgot to wave the magic iWand and recite the iTunes license agreement....backwards. 

Speaking of iTunes, I just finished the "Download and Upgrade" process to the latest iOS.  Let's think about this.  If I upgrade my device to the latest iOS, that usually means XCode needs an upgrade.  Since the version of XCode installed on my computer is now somewhat out of date, it does not recognize the fancy new iOS projecting through the USB port.  The same may be true for you.  Take the time and 3.5 gigs to make sure the version of XCode installed on your machine supports the iOS version installed on your device.

Not to mention the error specifically states "No provisioned iPhone OS device is connected".  Let's break it down and debug:

No provisioned - tells us to check the provision file for our device id and ensure this file is selected for the app build
iPhone OS - tells us to check if the operating system version is supported by XCode
device is connected - tells us to plug it in

That is all I can suggest.  Remember, if all else fails, restart the system.....if that does not work, hit it with a hammer.

Tags: , ,

iPhone | Provision | XCode

Microsoft Opens F# ?!?!?!?

by Michael Hodgdon posted on December 6 2010 01:34

Had to take a double take on this one.  Microsoft opening something up under the Apache 2.0 License -> http://www.infoq.com/news/2010/11/FSharp-Open-Source

Tags:

Re-Post - Understanding Windows Azure Storage Billing – Bandwidth, Transactions, and Capacity

by Michael Hodgdon posted on December 1 2010 00:12

We have been poking at different hosting models here at Syndicated Methods for our MobilePipes platform for some time now.  As we roll the product out to more and more customers we want to provide the most convenient way possible to consume MobilePipes instances.  Provided that MobilePipes is a .NET platform Azure has been on our mind for some time.  While doing some research I stumbled along the following article that I wanted to re-post for our audience.  

Understanding Windows Azure Storage Billing – Bandwidth, Transactions, and Capacity

Tags:

Comparing the iPhone and Android development experience: Simulators, IDE's, and ALM.

by Michael Hodgdon posted on November 22 2010 00:51

As a multi platform device consultancy, we constantly get asked from our customers the difference between the development environments they use verses other mobile and device platforms.  Probably the most common, as you would imagine, is the difference between iPhone and the Android.  InfoQ just posted a recent article summarizing posts from David Green and John Blanco.  It seems like each of the posts come from different preferences, so it's great to hear the difference of opinion.  They do a great job though of summarizing the key differences.  I think they covered the topics well, but they missed one major mark that I would give Apple a fail on.  For some reason Apple has decided that it's a good idea to bundle the SDK with a new version of xCode.  It just seems wrong to me that when I want to target the latest IOS bits I must also download their xCode IDE (~ 2.5 GB each time)!  The  consensus is that, although each have their own drawbacks, Apple wins the vote for simplicity, and Android wins the vote for being the most feature rich.  Kind of funny that their development platform matches their devices!

Enjoy!

 

Tags:

Syndicated Methods Releases L*Space Designer Swimwear App!

by Michael Smallwood posted on November 18 2010 13:10

Great news for the designer swimwear lovers of the world!

Syndicated Methods has released a new iPhone app for L*Space Swimwear of Irvine, CA allowing users to view the latest collections, find stores using location-based services, and even interact with social networking. We received great praise from Monica Wise, the creative director and founder of L*Space. Read more including client quotes in the press release by clicking here.

Want to checkout the L*Space app for yourself? Click here to download on iTunes!

Tags: , , ,

Hey, my UILabel isn't updating! AKA IOS threading issues

by Christopher Gregory posted on November 9 2010 05:35

This is I'm sure a pretty common problem to someone just getting started doing more complex App development for iPhone/iPad, the answer fortunately is very simple.

So you’re polishing up your new app, everything appears to be in order code wise, but then the strangest thing happens. Your wait screens that you set up with progress bars and/or a text-based progress indicator isn’t updating during the task at hand.

The reason this happens is because of threading. IOS will automatically split off threads for different framework method calls depending on what you use. But when you write code that’s going to be particularly resource intensive it’s up to you to ensure things are running in a separate thread.  By default all processing occurs on Thread-1, which is the main IOS thread, and is also the only thread that can update the IOS GUI. So to update your progress bars or labels you need to keep that thread open to receive your updates ASAP during the task at hand.

Fortunately for many cases this is relatively easy to do. Recently with one of our newest mobile applications we ran into this issue since we have to both download large amounts of data and also process that data into a SQL database. Resource intensive, but synchronous tasks we need to all run in the background.

There are just four quick steps to making your synchronous code asynchronous.

1:  The main body of your task must have its own auto release pool, which needs to be started before anything else and cleared by hand prior to your task exiting.

2: Call your function main body using performSelectorInBackground:withObject: (documentation)

3: Set up simple delegate methods for updating your UI from within the task body instead of trying to update their properties directly.

4: Call those delegate methods using performSelectorOnMainThread:withObject:waitUntilDone: (documentation)

This keeps Thread-1 clear to receive updates and sends them back asynchronously as the task runs. Of course for doing more complicated things such as cross-thread communication, setting up a run-loop/job-queue to process tasks you’ll need something a bit more complicated. But for a lot of simple tasks this is all you’ll need.

Before I go there’s one other thing worth mentioning. If you think your App is going to be doing a even a fair amount of asynchronous transfers  from the web, a great, and free (BSD) utility for that is ASIHTTPRequest; which you can find here. ASIHTTPRequest has been under development for years and already has some very heavily optimized methods of handling downloads, form posts, and uploads to web sources and it handles threading all by itself.

Tags: , , ,

Adapting the Facebook API for the iPad

by Christopher Gregory posted on August 9 2010 12:51

So recently I was wrapping up development work with the same iPad app port for Mobile Innovations as I had mentioned in my last post, when I ran across a rather interesting problem.

We make use of multiple APIs for allowing you to share what you’ve made in our Applications with all of your friends. However with the iPad things take on a new dynamic. Before everything would be displayed as its own full-screen view controller but the iPad allows us to focus more into a single view. Popovers are a great way to add extra controls that are relevant to on-screen content but not important enough to take up the whole screen.

We currently make use of Facebook, twitter and email as means for sharing. The last two are relatively easy to display inside a popover. Facebook however, is a bit more of a challenge. The Facebook API, of which they have yet to make a native iPad port, displays a series of procedurally generated dialogs that are meant to take up almost the entire screen. This simply won’t do for the iPad, since it has so much screen real-estate doing something like that would break the design theme of centralizing all the content onto as few views as possible and making use of contextual  items to display related content.

Facebook doesn’t make this easy though. Since everything is generated in code, and not from a xib file, we’ve got to dig around to find the parts we need to alter to make it work. We just need to make a few key modifications to FBDialog.m and we’ll be set. As with my last post I’ll be using the self-defined preprocessor macro TARGET_OS_IPAD to separate the code out, so that the FB API remains usable for either device based on your build target.

First step, sizeToFitOrientation is the main function called to generate the main FB dialog window. We’ll just add this here:


 
I’ve excluded everything after the else, as it’s just the main body of the function. In this case we’re just telling it to set a static frame for all dialogs, you can alter this of course to size it however you’d like. Since all of our dialogs should be appearing inside a view we’ve already set up in the view controller we’ll be presenting in the popover it’s easy to just set a static size. Next:


We need to remove this because we don’t want the facebook dialog to try and re-orient itself on orientation change since our popover will automatically handle repositioning itself. Next we’ll add some important code to our Init function

 



By setting ourselves as the active popover delegate this lets us automatically dismiss any open dialog when the popover is dismissed.
And this goes at the end of dismiss method



The above returns the popover delegate to its original source and removes the FB dialog from our view hierarchy.  It’s important to remove the FB dialog’s view from the superview because otherwise you’ll get a memory exception later when the View Controller tries to deallocate the view again as part of its cleanup. This frees everything up in order so we don’t have anything lingering in memory. Now when assigning and removing the Facebook view your implimentation of the above may be slightly different. In my case my main controller view was given the tag 8426 and 9999 is a container view I created just for the Facebook API dialogs, which I move back and forth in the hierarchy as necessary. For the code to work that also means that the view you're adding the dialogs to must already be a part of the view hierarchy.

Normally you might not see this but there’s a grey border typically drawn along the outside of the facebook dialogs. Depending on your app you may want to remove this. If so just put the following code at the start of the drawRect method like so:


 
There’s still one more part of the code that tries to resize our view. Now, you can either do this the way I did, which was to comment out the body like so:

Using preprocessor statements. Or you can just do it in the add/removeObservers methods, which add the keyboard change notifications. Either way it’s important that the above code doesn’t get called for the keyboard notifications as it’s another point where the FB dialog tries to resize and orient itself according to the main screen.

This last part is from the end of the show method:

 

This adds our dialog to our specified view, and removes the last instances of it trying to dynamically size and orient itself. Now no matter where it appears, no matter what size it is, all of our facebook dialogs will appear inside our special view controller, which in our case will appear inside a popover.

One last important tip. When adding any dialog to a popover, it’s always a good idea just in case to have the top level view as a scroll view with the content size set to the frame’s proper width and height. Popovers will try and move to avoid the keyboard when it appears, and that can cause the view to get shrunk. So using a scroll view will ensure that you can scroll while the keyboard’s up, in case it obscures anything important.

Tags: , , , ,

Distributed Architecture: Part 1 - WCF Data Services ... A RESTful way of doing things

by Michael Hodgdon posted on July 7 2010 14:50

One of our strong practices here at Syndicated Methods is design and implementation of Service Oriented Architectures (SOA).  When people immediately hear SOA, they think SOAP and bloated contracts.  Yes, SOA boasts some grandiose goals with its standards, and with those goals comes a complex implementation. I have seen SOA make sense of many enterprises, and like any loyal developer ready to fight for their technology,  this mantra has always rubbed me the wrong way.   As of the release of .NET 4.0 however, and the rise of REST services, it has become quite clear that SOA isn’t the only way.  It has actually changed how I think of our practice.  So much so that I make sure to tell clients and folks that I talk to that our practice specializes in “Distributed Architectures”.  I have come to realize that we can take all of those lessons learned in SOA and apply them to any number of manners for exposing enterprise data in a distributed fashion applying the most suitable manner for clients.

After reading a recent article on WCF Data Services, it got me thinking about how to spread the word for such technologies.  Oh yeah, did you know Syndicated Methods has a blog!  So, I want to start a series on the Syndicated Blogs titled ”Distributed Architectures”.  The first candidate … you guessed it.  WCF Data Services.

WCF Data Services

There are certain scenarios where the development overhead associated with SOA is just not necessary.  For example, you have an analytics group that needs to have open access to a data store.  Or, you have an application that allows the user to shape and export data how they see fit.  Maybe you do a lot of prototyping and are looking for a turnkey solution for getting to your data. Such business problems have been solved by the Open Data Protocol (i.e. OData).  Those familiar with RESTful services will immediately understand.  The idea is to expose a repository of data over a standard pathing system, such as urls.  WCF Data Services takes these concepts and allows you to define a WCF Service (without the contracts of course) over an Entity Data Model.  You can expose your data in just a couple of easy steps.

Step 1 – Create a new Web Project on your local file system.  Any name for the site should do.

Step 2 – Next we need an Entity Data Model of the standard Sql Server Nothwind database.  You will want to create a new Entity Data Model pointed to a local instance of Northwind.  Go ahead and run all of the default configurations (make sure you place this in the App_Code section of the project).  You should end up with a Entity Data Model that looks similar to the following diagram:

 

Step 3 –Now it’s time create your service.  Create a new WCF Data Service in the root of the website. Now we are going to have to write a little bit of code here.  We only want to expose the Employees table for this exercise, so we need to tell the WCF Data Service to expose the Employee table.  In a real world implementation this could be done for all of the data tables / data sources required.  The code is rather trivial and is represented below:

Step 4 – Now for the fun stuff.  Let’s get your data!  You can easily pull your Employee data from the service by pointing DataServiceQuery at the endpoint.  Pretty neat!  No messy configurations, no service endpoints to deal with, and better yet you get your data in 4 or less easy steps.  I will let you play around with your services to get an idea of what it’s like to pull this data. Below is sample code for consuming the endpoint.


Before I close out this post, I want to just show you something that you may have missed.  I know that I missed it the first time through, so I want to just call it out.  WCF Data Services are employing the power of .net and WCF to allow you to address your data.  Users of the system only need to know the schema of the database.  We accessed the data by pointing to the following url:

http://localhost/WcfDataService.svc/Employees

This url basically says, use this service repository location, and show me all of the employees.  If we wanted the Customer data (assuming it was exposed in the WCF Data Service) we only need to access the following url:

http://localhost/WcfDataService.svc/Customers

And keeping true to the RESTful theme, if you want to narrow your data down you can pass a query along with this path like so:

http://localhost/WcfDataService.svc/Customers('ALFKI')/Orders?$filter=Freight gt 50

This will capture Customers with the id of ALFKI and will then filter those by getting freight values that are Greater Than 50.  Pretty neat.  Using these powerful data services allows you to get to a repository of data by simply "asking" for data in a standardized format.  If you are wondering how all of this data gets transferred, under the hood .NET will serialize this data in POX or JSON format.  The following screenshot verifies our transport data as depicted in Fiddler

 

As you can see the output is a standard ATOM Xml format.  Internet Explorer will conveniently display this as a RSS feed.  Anyone that is tasked with exposing data in a distributed fashion should definitely put this one in their toolbox!

{Happy Coding}

Tags: , , ,

Contact Us

We want to hear from you.  Our community is important to us and we want to make sure we give you the contact you want.  Please contact our team if you want to sent us feedback of any kind.  Enjoy reading!

RecentComments

Comment RSS