Custom page to download and install specific .ipa files in end-user's iphone

Goal

I want to allow end-users to install specific .ipa (iOS App Store Package)  or .apk (Android Package File) files in their phones.

Most end-users are to be presented with a single link to install the app (usually the latest tested version of the mobile app). Other end-users (application admins) are to be presented with several install links (different versions of the mobile app).

In a way I want to be able to customize the appearance and functionality of this platform generated page:

https://<my-server-name/NativeAppBuilder/App?AppKey=<app-key-guid>

Besides having a fixed visual design, this page only allows to download the latest generated app. Btw, in this page, when the end-user clicks the Get button in iphone, it links to something like this:

https://<my-server-name/NativeAppBuilder/rest/Download/Ipa?AppKey=<app-key-guid>

In summary, I want to create a screen that has its own design (aligned with the application) and its own logic, and that allows end-users to install the chosen .ipa / .apk.

Context / issues

I'm using OutSystems 11. In this specific case the custom app download screen was created inside a traditional web application, but this should apply also to reactive applications. 

Each file content (.ipa or .apk) is stored in the database (Binary Data attribute) in an entity I created to store the content of the app binaries.

The android part presented no problems. My link destination is a screen action that fetches the intended .apk binary from the database and ends in a Download element. The Download element's  Mime-Type is set to "application/octet-stream". On download Android detects it is an app and allows the end-user to install it.

I tried he same approach with iOS (download the .ipa binary content). After pressing the download link, iOS would allow the end-user to save the file but wouldn't give the option to install the app.  

I searched the forums and found other developers with similar goals and issues. But I didn't find a solution there. After some research and trial and error I found a solution. I'm posting it below for the benefit of others in the future.

Solution for .ipa download and install

The approach was to have 3 screens and use the itms-services protocol (itms-services://...).

The first screen, e.g.: ListPackages, lists the packages the end-user is allowed to install and presents a link for each one. The link doesn't download the binary directly. Instead, it instructs the browser to download a .plist (property list) xml file through the itms-services protocol instead of https. 

The .plist is generated dynamically by the second screen, e.g. DownloadPListXML. Among other info, it includes a URL to the third screen in the application. 

That third screen, e.g. DownloadBinaryIPA, will return the .ipa binary content that was previously stored in the database.

ListPackages.aspx ----itms-services://----> DownloadPListXML.aspx (-------->DownloadBinaryIPA.aspx )

Below follows more detailed info regarding what you can do to implement a similar solution.

.plist content

The returned .plist should contain something 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> PLACE HERE THE URL TO YOUR SCREEN THAT DOWNLOADS THE .ipa BINARY FILE, e.g.: https://<my-server-name/myDownloadManagerApp/DownloadBinaryIPA.aspx?id=.... IF YOU JUST WANT TO DOWNLOAD THE LATEST GENERATED VERSION, JUST PLACE https://<my-server-name/NativeAppBuilder/rest/Download/Ipa?AppKey=YOUR-APP-KEY-GUID  </string>

               </dict>

           </array>

           <key>metadata</key>

           <dict>

               <key>bundle-identifier</key>

               <string>PLACE HERE THE BUNDLE IDENTIFIER, SOMETHING LIKE COM.COMPANY.SERVER (get more info below in the post) </string>

               <key>bundle-version</key>

               <string>1.0</string>

               <key>kind</key>

               <string>software</string>

               <key>title</key>

               <string>PLACE HERE YOUR PHONE APP NAME (get more info below in the post)</string>

           </dict>

       </dict>

   </array>

</dict>

</plist>

How to get the data to configure the xml attributes for the returned .plist xml 

Download your .ipa file (e.g.: MyApp.ipa) to you computer. Rename it to .zip and unzip it. Locate Info.plist and open it (if using windows, you may need to download this utility: https://plist-editor-for-windows.software.informer.com/download/ ). Just copy the content of these 2 attributes and use them in the returned xml .plist content (as specified above):

  • bundle-identifier: something like COM.COMPANY.SERVER
  • title: (your mobile app name)

First screen, ListPackages

In this ListPackages screen, list the packages stored in the database you want to allow your end-user to instal. For the iOS links, create a link whose destination is Common\ExternalURL and URL parameter is something like:

  • "itms-services://?action=download-manifest&url=https://<my-server-name>/myDownloadManagerApp/DownloadPListXML.aspx?id=..."

Second screen, DownloadPListXML

As presented, the .plist XMLis generated dynamically by this second screen. For this purpose, it  should have a Preparation and end in a Download element. 

For the Download element you'll need to provided a binary content of the .plist. To convert your text to binary use TextToBinaryData action located in the BinaryData extension. Provide "utf-8" for the Encoding parameter.

Provide the following values for the Download element's parameters:

  • File Content: TextToBinaryData.BinaryData
  • File Name: "MyApp.plist"
  • Mime-Type: "text/xml"
  • Save to Disk: Yes

Check image:


Third screen, DownloadBinaryIPA

This screen just needs to receive the database Id, and in the screen preparation:

  • Read binary data from database
  • End the action with a download element:
    • File Name: "<your iphone app name>.ipa"
    • Mime-Type: "application/octet-stream"
    • Save to Disk: Yes

Hi,

Is this an RFP? 

It is not clear what the question is you are asking the OutSystems community.

Are you experiencing a problem implementing your idea in OutSystems?

Regards,

Daniel

Hi

I probably should've been more clear right at the start of the post. But it seems now I don't have the privileges to edit my own post to clarify it.

The goal of the post is to present an implementation solution, for the benefit of others in the future, who also face a similar scenario.

Scenario:

You provide a web application and one or more mobile apps (for both iOS and Android). The mobile apps evolve, so along time you'll have several versions for each provided mobile app. 

You want to create a screen in your web application that will list the mobile apps / their versions, and that will allow your end-users to download and install them on their phones.

While this is simple for the Android packages (.apk), for iOS packages (.ipa) it is more difficult.

I hope now the post goal is clear. Thanks for asking. 


Btw, I placed the following text in the "Context / issues" section, but it seems it was too buried in the text:

I searched the forums and found other developers with similar goals and issues. But I didn't find a solution there. After some research and trial and error I found a solution. I'm posting it below for the benefit of others in the future.