OTA Updates

Over-the-air (OTA) updates send a new version of your app's PHP code, views and assets straight to the phones it's installed on, without going through store review.

How it works

  1. You install the free nativephp/mobile-ota plugin in your app.
  2. You ship a normal iOS and/or Android store build with the plugin installed, and get it through review. This build is the app's shell.
  3. From then on, you can publish OTA updates from Ship It!. Installed shells download the update and apply it the next time the app starts.

An OTA build uses one build credit, just like an iOS or Android build.

Requirements

  • nativephp/mobile 4.6.1 or later.
  • The nativephp/mobile-ota plugin, installed and registered.
  • An iOS or Android store build, made by Bifrost with the plugin installed, live on the store and installed on your users' phones.

Installing the plugin

The plugin is available on Packagist now, and is coming to the SuperNative plugin marketplace soon.

composer require nativephp/mobile-ota
php artisan native:plugin:register nativephp/mobile-ota

Commit both composer.json and composer.lock, and push them.

You must rebuild and resubmit first

Installing the plugin does nothing for the apps already on your users' phones. Those apps were built without it, so they can never receive an OTA update.

After installing the plugin you must:

  1. Ship a new iOS and/or Android build from Bifrost.
  2. Submit it to the App Store and/or Google Play, and get it approved.
  3. Wait for your users to install that version.

Only phones running that build (or a later one) will receive OTA updates. Bifrost writes everything the app needs to find its updates into the build, so there's nothing else to configure.

Update modes

Set NATIVEPHP_OTA_MODE in your app's environment variables under Build Configuration:

Mode What happens
manual (default) Nothing happens on its own. Your app decides when to check and install, using the Ota facade.
prompt Once per launch, the app checks in the background and asks the user Later or Update. Update downloads it, then asks the user to close and reopen the app.
silent The app checks for and downloads updates automatically, with no dialog. A downloaded update is applied the next time the app starts.

In every mode, an update is only applied the next time the app starts. The app is never restarted for the user.

The mode is compiled into the shell, so set it before you ship the store build that should use it.

Use silent mode for iOS

prompt and manual modes work on iOS, but if you use them you take on more risk with App Review. On Android, any mode is fine.

Manual mode

Use the Ota facade, for example from a "Check for updates" button:

use Nativephp\MobileOta\Facades\Ota;

$update = Ota::check();

if ($update['available']) {
    Ota::downloadAndApply();
}

The plugin also has methods for checking status, and events for each step. See the plugin's README for the full reference.

Apple and Guideline 2.5.2

Guideline 2.5.2 says apps may not "download, install, or execute code which introduces or changes features or functionality of the app".

If App Review cites Guideline 2.5.2

Your app's code is PHP, which is interpreted code. Apple explicitly allows apps to download interpreted code in section 3.3.1(B) ("Executable Code") of the Apple Developer Program License Agreement, as long as that code:

  1. does not change the primary purpose of the app by providing features or functionality that are inconsistent with its intended and advertised purpose as submitted to the App Store,
  2. does not create a store or storefront for other code or applications, and
  3. does not bypass signing, sandbox, or other security features of the OS.

If you're cited, reply in App Store Connect's Resolution Center and explain that:

  • the app downloads only interpreted (PHP) code and web assets, run by the interpreter already in the reviewed binary,
  • no native or compiled code is ever downloaded, and every update is checksum-verified,
  • updates are used for bug fixes and improvements within the app's reviewed purpose, and comply with section 3.3.1(B) of the Apple Developer Program License Agreement.

Section numbers in the agreement change from time to time. Check the current agreement before you quote it.

This is only an argument you can make. It isn't a guarantee: App Review has the final say, and the best protection is to stay well inside the three conditions above.

What an OTA update can change

An OTA update replaces your Laravel app:

  • routes, controllers and EDGE components
  • Blade views, CSS and JavaScript
  • images and other assets
  • bug fixes, copy changes and small improvements to existing features

When you need a full rebuild and resubmit

An OTA update can't change anything compiled into the shell. You need a new store build, submitted for review, when you:

  • add, remove or update a SuperNative plugin (including nativephp/mobile-ota)
  • update nativephp/mobile or nativephp/mobile-ui
  • change native settings in config/nativephp.php: app ID, permissions, permission descriptions, deep links, orientation, iPad support, appearance, the runtime mode, or Android SDK and build settings
  • want to change the OTA mode for users who haven't installed an update yet

Bifrost checks this for you. Every store build records a fingerprint of its native setup. When you ship an OTA update, Bifrost only offers it to shells with the same fingerprint on the same Arc. If your commit's native setup doesn't match any shell, Ship It! tells you what changed and you'll need to ship a store build first.

Major changes should go through review

Even when an OTA update could carry a change, some changes should still go through the stores:

  • Major UI changes. A redesign, new navigation, or screens that look very different. Users who open the app to a completely different interface with no store update can be alarmed, and may think the app has been hijacked.
  • New features, or anything that changes what your app does or how it's described on the store.
  • Anything that affects the app's store listing, screenshots, age rating, privacy details or in-app purchases.

Ship these as a normal store build so App Review and your users see them coming. Keep OTA updates for fixes and small improvements.

Don't ship an OTA update while an app is in review

Wait until the App Store or Google Play has finished reviewing a build before you publish an OTA update for it. An update published during review can change the app while the reviewer is testing it, so they may not see the version you submitted.

Arcs

An app only receives updates published to its own Arc. A Staging shell gets Staging updates, and a Production shell gets Production updates. Test an update on Staging, then promote it to Production from Releases.

Safety

  • An app never installs an update older than the code it was built with.
  • A download whose checksum or size doesn't match what Bifrost published is discarded.