4

We have an enterprise app for which we are ending support of iOS6. During a recent test, we created a build of the app, and set the following values in Info.plist

<key>MinimumOSVersion</key>
<string>7.0</string>

The app was built with the iOS 7.1 SDK. If it matters (and I'm not certain that it does), it is a Xamarin.iOS project.

As we were testing, we expected that when we attempted to install on iOS6 that the installation would be rejected early in the process, since we were installing on an unsupported version of iOS. We anticipated that the previously installed version of the app would continue to function as it had before, without all of the new features.

Instead what happened was that the installation failure happened later in the installation than expected, and the old version of the app was unusable after the upgrade failed.

To double check a couple of things, I downloaded the IPA file, and unzipped it. Inside the bundled Info.plist, I see this:

MinimumOSVersion = "7.0";

which is a good sign. However I think that it also explains why the attempted installation broke the previously installed version.

For regular apps, i.e. apps from the iOS App Store, you aren't given the option of installing applications for which your installed iOS is too old, and the installed version of the app remains unchanged.

Is there a way to do such a thing for Enterprise Apps without having to build everything out? I'm thinking that maybe there is a setting in the manifest.plist that is used for OTA deployment.

For the sake of thoroughness, here is my Info.plist prior to build:

<?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>CFBundleDisplayName</key>
    <string>OurApp Stage</string>
    <key>CFBundleIconFiles</key>
    <array>
        <string>Images/OurApp_72.png</string>
        <string>Images/OurApp_50.png</string>
        <string>Images/OurApp_29.png</string>
        <string>Images/OurApp_512.png</string>
    </array>
    <key>CFBundleIdentifier</key>
    <string>com.ourappproject.staging.mycompany</string>
    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleURLName</key>
            <string>com.ourappproject.staging-handler</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>ourapp-staging</string>
            </array>
        </dict>
    </array>
    <key>CFBundleVersion</key>
    <string>2014.2.04.05</string>
    <key>MinimumOSVersion</key>
    <string>7.0</string>
    <key>UIBackgroundModes</key>
    <array>
        <string>audio</string>
    </array>
    <key>UIDeviceFamily</key>
    <array>
        <integer>2</integer>
    </array>
    <key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>UISupportedInterfaceOrientations~ipad</key>
    <array>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
</dict>
</plist> 

Info.plist from within the IPA:

// !!! BINARY PROPERTY LIST WARNING !!!
//
// The pretty-printed property list below has been created
// from a binary version on disk and should not be saved as
// the ASCII format is a subset of the binary representation!
//
{   BuildMachineOSBuild = "13C1021";
    CFBundleDevelopmentRegion = "en";
    CFBundleDisplayName = "OurApp Stage";
    CFBundleExecutable = "OurAppMobileApp";
    CFBundleIconFiles = ( "OurApp_72.png", "OurApp_50.png", "OurApp_29.png" );
    CFBundleIdentifier = "com.ourappproject.staging.mycompany";
    CFBundleInfoDictionaryVersion = "6.0";
    CFBundleName = "OurAppMobileApp";
    CFBundlePackageType = "APPL";
    CFBundleResourceSpecification = "ResourceRules.plist";
    CFBundleSignature = "????";
    CFBundleSupportedPlatforms = ( "iPhoneOS" );
    CFBundleURLTypes = (
        {   CFBundleURLName = "com.ourappproject.staging-handler";
            CFBundleURLSchemes = ( "ourapp-staging" );
        },
    );
    CFBundleVersion = "2014.2.04.05";
    DTCompiler = "com.apple.compilers.llvm.clang.1_0";
    DTPlatformBuild = "11D167";
    DTPlatformName = "iphoneos";
    DTPlatformVersion = "7.1";
    DTSDKBuild = "11D167";
    DTSDKName = "iphoneos7.1";
    DTXcode = "0510";
    DTXcodeBuild = "5B1008";
    LSRequiresIPhoneOS = :true;
    MinimumOSVersion = "7.0";
    UIBackgroundModes = ( "audio" );
    UIDeviceFamily = ( 2 );
    UIRequiredDeviceCapabilities = ( "armv7" );
    UISupportedInterfaceOrientations = ( "UIInterfaceOrientationLandscapeLeft", "UIInterfaceOrientationLandscapeRight" );
    "UISupportedInterfaceOrientations~ipad" = ( "UIInterfaceOrientationLandscapeLeft", "UIInterfaceOrientationLandscapeRight" );
}

The manifest.plist:

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <!-- array of downloads. -->
        <key>items</key>
        <array>
            <dict>
                <!-- an array of assets to download -->
                <key>assets</key>
                <array>
                    <!-- software-package: the ipa to install. -->
                    <dict>
                        <!-- required.  the asset kind. -->
                        <key>kind</key>
                        <string>software-package</string>
                        <!-- required.  the URL of the file to download. -->
                        <key>url</key>
                        <string>https://arm.staging.ourappproject.com:443/Store/App/9/17/OurAppMobileApp.ipa</string>
                    </dict>
                    <!-- display-image: the icon to display during download .-->
                    <dict>
                        <key>kind</key>
                        <string>display-image</string>
                        <!-- optional.  indicates if icon needs shine effect applied. -->
                        <key>needs-shine</key>
                        <true/>
                        <key>url</key>
                        <string>https://arm.staging.ourappproject.com:443/Assets/OurAppMobileApp.png</string>
                    </dict>
                    <!-- full-size-image: the large 512x512 icon used by iTunes. -->
                    <dict>
                        <key>kind</key>
                        <string>full-size-image</string>
                        <key>needs-shine</key>
                        <true/>
                        <key>url</key>
                        <string>https://arm.staging.ourappproject.com:443/Assets/OurApp_512.png</string>
                    </dict>
                </array>
                <key>metadata</key>
                <dict>
                    <!-- required -->
                    <key>bundle-identifier</key>
                    <string>com.ourappproject.staging.mycompany</string>
                    <!-- optional (software only) -->
                    <key>bundle-version</key>
                    <string>2014.2.04.05</string>
                    <!-- required.  the download kind. -->
                    <key>kind</key>
                    <string>software</string>
                    <!-- optional. displayed during download; typically company name -->
                    <key>subtitle</key>
                    <string>mycompany</string>
                    <!-- required.  the title to display during the download. -->
                    <key>title</key>
                    <string>OurApp Mobile</string>
                </dict>
            </dict>
        </array>
    </dict>
</plist>

Any and all suggestions are appreciated.

  • [for] apps from the iOS App Store, you aren't given the option of installing applications for which your installed iOS is too old <--- not strictly true. Depending on the behavior of the older iOS version, when installing an app that requires a newer iOS version, the installation process starts by closing the App Store and placing in the Springboard the app icon, then it will check to see if the system version is compatible. If not, sometimes you will be given the option to install the last version of the app that was compatible with that version of iOS. – chillin May 1 '14 at 8:48
  • That's interesting. I'm beginning to think that I need to keep hardware around with older iOSs on it. So once the app hits the springboard, if the user does not opt to install the last supported version, then the version that they had installed previously is toasted? – Kirk May 1 '14 at 15:32
  • If the app has been installed before on the earlier iOS version, and now the earlier iOS version is no longer supported, upgrades will continue up to the last version of the app compatible with that version of iOS. However, once that version of iOS is no longer supported, the process will work as I described above, but the result is that the installation will fail, it will not install, and it will inform the user they need to upgrade their system to install the app. – chillin May 4 '14 at 12:26
  • Yeah I understand. Since we are enterprise developers, we aren't distributing via the app store, but we came up with a pretty simple work around. – Kirk May 5 '14 at 2:59
2
+100

I don't think it is possible to do.

If you are using a web based deployment you can always check for an OS version from the browser and force it that way.

You can use Request.UserAgent to get the OS version and then JQuery to disable the button and throw an alert explaining to the user why they can't download.

        string agent = Request.UserAgent;


        if (agent.Contains("iPad; CPU OS 6_"))
        {
            ClientScript.RegisterStartupScript(this.GetType(), "iOS",
                                               " $('#appInstall a').click(function(e) {e.preventDefault();});",
                                               true);
            ClientScript.RegisterStartupScript(this.GetType(), "iOSAlert",
                                               " $('#appInstall a').click(function() {alert('The application is now only available on iPads running iOS 7 or higher. Please upgrade your iPad to get the latest version.');});",
                                               true);
        }
2

I found that:

You should not specify MinimumOSVersion in your Info.plist.

Instead see this for guidance Information Property List Key reference:

Information Property List key ref

  • 1
    The IDE created Info.plist for me automatically. Not certain what I can do to make it otherwise, nor am I convinced that this actually addresses the issue at hand. – Kirk May 1 '14 at 15:30
  • I am just reporting what I found been unable to replicate your scenario, and obviously your setting does not work as you explained. You say the info.plist was created based on ? – Ruskes May 1 '14 at 17:46
  • The setting works perfectly. I am looking for a way for the setting to take effect earlier in the installation process. Based on the comment from @chillin up above, I would say that what I am looking to do is not possible without a bunch of extra work on my part. – Kirk May 2 '14 at 0:41
  • I do appreciate your taking the time to look. What I meant up there was that the Info.plist file was automatically generated by the development tool that we use. I didn't create the file manually. – Kirk May 2 '14 at 0:42
  • I would contact Xamarin support. If needed, maybe fill a bug report. – Édouard May 5 '14 at 12:23
0

(This isn't a proper answer, but it is too long for a comment.)

I don't know much about Xamarin, but in Xcode, the setting that specifies the minimum iOS version required is called the deployment target. See this stackoverflow question and answers for a few links to some details.

According to this article, one of the consequences of setting the deployment target is to add a MinimumOSVersion string to the Info.plist file, but perhaps there are others too (in the binary itself?).

If you haven't tried this already, try searching for details on "deployment target" rather than MinimumOSVersion. Also perhaps consider asking your question on stackoverflow?

  • In Xamarin Studio, it also shows up as deployment target. We have it set to 7.0 -- and it is the same deal. Changing the deployment target causes the MinimumOSVersion to change in Info.plist. – Kirk May 2 '14 at 19:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .