The latest version of the Android system provided by Digi enables you to update the firmware of the ConnectCore 8X device from the Android system itself. See Update Android with OTA packages to learn how to perform the firmware update through the Android settings. If you prefer, you can add the firmware update functionality to an Android application using the firmware update service provided by Digi.
With the firmware update API you can perform a firmware update of the system from an Android application, install new applications and wipe the user and data partitions. In the Digi APIx javadoc documentation you can find a complete list of the available methods in this API.
Unless noted, all Firmware update API methods require the com.digi.android.permission.FIRMWARE_UPDATE
permission.
If your application does not have the com.digi.android.permission.FIRMWARE_UPDATE permission it will not have access to any Firmware update service feature.
|
First of all, a new FirmwareUpdateManager
object must be instantiated by passing the Android Application Context.
import android.app.Activity;
import android.os.Bundle;
import com.digi.android.firmwareupdate.FirmwareUpdateManager;
public class FirmwareUpdateSampleActivity extends Activity {
FirmwareUpdateManager firmwareUpdateManager;
[...]
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Instantiate the FirmwareUpdateManager manager object.
firmwareUpdateManager = new FirmwareUpdateManager(this);
[...]
}
[...]
}
Install an application
One of the features provided by the firmware update service is to install an Android application.
Use the installApplication(String, boolean)
method of the FirmwareUpdateManager
with the full path of the APK to install.
This method also offers the possibility of rebooting the module after the application installation.
Method | Description |
---|---|
|
Installs the application represented by the given APK full path |
The installApplication(String, boolean)
method may fail for the following reasons:
-
The provided application path is
null
throwing aNullPointerException
. -
There is an error installing the application throwing an
IOException
.
import com.digi.android.firmwareupdate.FirmwareUpdateManager;
[...]
FirmwareUpdateManager firmwareUpdateManager = [...];
[...]
// Install the application located at '/storage/emulated/0/Download/MyApplication.apk'.
// Do not restart the device after application installation.
firmwareUpdateManager.installApplication("/storage/emulated/0/Download/MyApplication.apk", false);
This method will not ask for permission to install the application, as the installation process is performed by the Android Firmware update service. |
Install an update package
The main purpose of this firmware update service is to install an update package to update the Android system. The firmware update process requires two files:
-
An OTA package that contains the update files. To generate this package, follow the steps in Create a signed OTA package.
-
A JSON configuration file that describes the OTA package contents and the update process. To generate the configuration file, follow the steps described in JSON OTA configuration file.
Once you have both files, you can configure your application to trigger a firmware update using the firmware update service.
Before applying the update, Digi recommends you subscribe to the firmware update service to receive event and progress notifications for the firmware update operation. See Listen for firmware update events for more information. |
To trigger the firmware update, use the applyUpdate(String)
method with the following parameters:
-
otaJSONString
: JSON configuration string describing the OTA update package (the contents of the JSON file).
Method | Description |
---|---|
|
Applies the update package described in the given JSON configuration string |
The applyUpdate(String)
may fail throwing an IOException
in the following cases:
-
If the provided JSON configuration string is invalid or malformed.
-
If an update is already running.
import com.digi.android.firmwareupdate.FirmwareUpdateManager;
[...]
String jsonConfigurationString = [...];
FirmwareUpdateManager firmwareUpdateManager = [...];
try {
firmwareUpdateManager.applyUpdate(jsonConfigurationString);
} catch (IOException e) {
[...]
}
[...]
Once the update has started, you can control and manage the update with the functions described in Control the firmware update process chapter.
After a successful firmware update, you must reboot the device to boot in the update system. |
Control the firmware update process
The firmware update service provides several methods to control and manage the update process once it has started:
Method | Description |
---|---|
|
Permanently cancels an in-progress update. No changes are applied. |
|
Resets the bootable flag on the non-current partition and all internal update_engine state. This means that, if an update has been applied, it is ignored. |
|
Suspends an in-progress update. |
|
Resumes a suspended update. |
Some of the methods described above may fail with an IllegalStateException
:
-
The
cancelUpdate()
method will fail if there is not an update in progress. -
The
suspendUpdate()
method will fail if there is not an update in progress. -
The
resumeUpdate()
method will fail if there is not any suspended update.
import com.digi.android.firmwareupdate.FirmwareUpdateManager;
[...]
FirmwareUpdateManager firmwareUpdateManager = [...];
[...]
firmwareUpdateManager.resetUpdate();
[...]
try {
firmwareUpdateManager.cancelUpdate();
} catch (IllegalStateException e) {
[...]
}
[...]
try {
firmwareUpdateManager.suspendUpdate();
} catch (IllegalStateException e) {
[...]
}
[...]
try {
firmwareUpdateManager.resumeUpdate();
} catch (IllegalStateException e) {
[...]
}
[...]
Listen for firmware update events
The firmware update process generates some events that can be get and processed in your application.
To make your application aware of these events, create your own Firmware update listener by implementing the IFirmwareUpdateListener
interface and register it using the registerFirmwareUpdateListener(listener)
method passing the listener as argument.
import com.digi.android.firmwareupdate.IFirmwareUpdateListener;
import com.digi.android.firmwareupdate.FirmwareUpdateManager;
[...]
class MyFirmwareUpdateListener implements IFirmwareUpdateListener {
@Override
void statusUpdate(FirmwareUpdaterStatus status, String details) {
[...]
}
@Override
void onProgress(int progress) {
[...]
}
}
[...]
FirmwareUpdateManager firmwareUpdateManager = [...];
MyFirmwareUpdateListener myFirmwareUpdateListener = new MyFirmwareUpdateListener();
firmwareUpdateManager.registerFirmwareUpdateListener(myFirmwareUpdateListener);
[...]
firmwareUpdateManager.removeFirmwareUpdateListener(myFirmwareUpdateListener);
[...]
The IFirmwareUpdateListener
interface defines the following methods to handle the events generated during a firmware update process:
Method | Description |
---|---|
|
Notifies a firmware update status change. |
|
Notifies percentage progress during the firmware update. |
During the firmware update operation, the statusUpdate
method is triggered several times to describe the different states of the process.
This method provides the status
argument which is a value of the FirmwareUpdaterStatus
enumeration class and a string with detailed information of the new state.
See Firmware update status for more information about the different update states.
The onProgress(int)
method is fired to notify about update progress percentage (0-100).
To unsubscribe a listener from the firmware update service, call removeFirmwareUpdateListener(listener)
passing the listener to remove as argument at any time.
It is convenient to subscribe to firmware update events before applying a system update. See Install an update package for more information. |
Firmware update status
The firmware service allows you to retrieve the firmware update operation status at any time. You can either:
-
Subscribe a listener to receive status event changes (see Listen for firmware update events)
-
Or execute the
getUpdaterStatus()
method.
getUpdaterStatus()
method returns a FirmwareUpdaterStatus
enumeration value to describe the current firmware update state.
The available values of the FirmwareUpdaterStatus
are:
-
IDLE
: The firmware update service is IDLE waiting for an update operation. -
ERROR
: The firmware update operation ended with error. -
RUNNING
: The firmware update service is applying an update. -
PAUSED
: The firmware update service has a paused update. -
SLOT_SWITCH_REQUIRED
: The firmware update operation has finished successfully and a manual slot switch is required. See Manual A/B slot switch. -
REBOOT_REQUIRED
: The firmware update operation has finished successfully and a reboot is required.
import com.digi.android.firmwareupdate.FirmwareUpdateManager;
import com.digi.android.firmwareupdate.FirmwareUpdaterStatus;
[...]
FirmwareUpdateManager firmwareUpdateManager = [...];
FirmwareUpdaterStatus status = firmwareUpdateManager.getUpdaterStatus();
switch (status) {
case IDLE:
[...]
break;
case ERROR:
[...]
break;
case RUNNING:
[...]
break;
case PAUSED:
[...]
break;
case SLOT_SWITCH_REQUIRED:
[...]
break;
case REBOOT_REQUIRED:
[...]
break;
}
[...]
It is also possible to check if an update is already running by invoking the isUpdateRunning()
method:
import com.digi.android.firmwareupdate.FirmwareUpdateManager;
[...]
FirmwareUpdateManager firmwareUpdateManager = [...];
boolean updateRunning = firmwareUpdateManager.isUpdateRunning();
[...]
Manual A/B slot switch
Android can automatically change the boot slot after the update depending on the JSON file configuration.
Firmware service provides a method to check whether a manual A/B slot switch is required.
The method to call is isManualSwitchSlotRequired()
and returns true
if a manual A/B slot switch is required or false
otherwise.
If a manual slot switch is required, the firmware service reports SLOT_SWITCH_REQUIRED
status and you have to invoke the switchBootPartition()
method.
This method throws an IllegalStateException
if there is not a previous update applied or if there is an update already running.
import com.digi.android.firmwareupdate.FirmwareUpdateManager;
[...]
FirmwareUpdateManager firmwareUpdateManager = [...];
if (firmwareUpdateManager.isManualSwitchSlotRequired()) {
try {
firmwareUpdateManager.switchBootPartition();
} catch (IllegalStateException e) {
[...]
}
}
[...]
Wipe partitions
The latest feature you can find inside the Firmware update service is functionality to wipe some of the Android system partitions. These are the data and cache partitions, where you have full access and can read and write files. Use any of the following methods to start a wipe process:
Method | Description |
---|---|
|
Wipes the cache ( |
|
Wipes the cache ( |
|
Wipes the user data ( |
|
Wipes the user data ( |
|
Wipes the user data ( |
These methods may fail if there is any error preparing for the wipe process throwing an IOException
.
import com.digi.android.firmwareupdate.FirmwareUpdateManager;
[...]
FirmwareUpdateManager firmwareUpdateManager = [...];
[...]
// Wipe the cache partition and provide a reason message.
firmwareUpdateManager.wipeCache("I'm sorry for your cache");
import com.digi.android.firmwareupdate.FirmwareUpdateManager;
[...]
FirmwareUpdateManager firmwareUpdateManager = [...];
[...]
// Wipe the user data and cache partitions and provide a reason message.
firmwareUpdateManager.wipeData("I'm extremely sorry for your data and cache");
The device is restarted in order to perform the wipe operation.
The wipeUserData(String, boolean)
method shutdowns the device, instead of rebooting it, if the shutdown
parameter is true
.
Firmware update example
The Firmware Update Sample Application demonstrates the usage of the Firmware Update API to apply OTA update packages to the system. The application uses JSON configuration files that describe the OTA update package and process.
You can import the example using Digi’s Android Studio plugin. For more information, see Import a Digi sample application. To look at the application source code, go to the GitHub repository.