A minimal Android app showing how to use the emteria Update SDK to drive over-the-air (OTA) OS updates from a third-party app. It binds to the update service that ships with emteria OS and demonstrates every operation the SDK exposes.
- Bind to / unbind from the emteria OTA service
- Query the currently installed emteria OS version
- Check for available OS updates on the configured channel
- Download a selected update in the background (with progress)
- Install a downloaded update (with progress and reboot-required signal)
All of this lives in a single screen — see
MainActivity.java.
- Runs only on emteria OS. The sample binds to the service
com.emteria.update/.UpdateService, which is part of emteria OS. On stock Android / AOSP or a plain emulator the bind fails and the operations do nothing. - No special permission is required. The update service is exported and freely bindable — the app only needs to run on a device where the service is present.
- Build targets:
compileSdk 34,targetSdk 34,minSdk 30(Android 11). - Bundled SDK:
app/src/main/libs/emteria-update-sdk-v1.7.jar.
The SDK is a thin contract over Android's bound-service Messenger IPC. There is no synchronous API — every call is a message, and every result comes back asynchronously on a callback handler.
- Bind to the service using the intent from
MessengerConfig.getServiceBindIntent(). On connect you receive a requestMessenger. - Build a request message with the relevant
*Contractclass, attaching your own responseMessenger, andsend()it. - The service replies with a message whose
whatis an ordinal ofMessengerConfig.ResponseReason. YourHandlermaps that reason to the matching*Contractextractor to read the payload out of theBundle.
// Bind (see MainActivity#bindUpdateService)
Intent bindIntent = MessengerConfig.getServiceBindIntent();
bindService(bindIntent, mConnection, Context.BIND_AUTO_CREATE);
// Request (example: OS version)
Message request = OsVersionContract.OsVersionRequest.buildMessage(mResponseMessenger);
mRequestMessenger.send(request);Responses are dispatched in MainActivity.CallbackHandler#handleMessage, which
switches on the ResponseReason.
-
Copy the SDK
.jarfromapp/src/main/libsinto your project. -
Add the JAR to your module's
build.gradle:implementation(fileTree("src/main/libs") { include("*.jar") })
-
Declare service visibility in
AndroidManifest.xmlso the OTA service is resolvable on Android 11+ (package visibility filtering):<queries> <package android:name="com.emteria.update" /> </queries>
That is the complete setup — no permissions to request.
Each operation sends one request and is answered by one or more of the response reasons below.
- Request:
OsVersionContract.OsVersionRequest.buildMessage(responseMessenger) - Result:
GET_OS_VERSION_RESULT→OsVersionContract.OsVersionResultResponse.extractOsVersion(payload)returns the version string. - Error:
GET_OS_VERSION_ERROR→OsVersionContract.OsVersionErrorResponse.extractErrorMessage(payload).
The version is the value of the system property ro.vendor.release.version
(e.g. 13.1.33), with any -debug suffix stripped. On a non-emteria system it
reads as 0.0.0.
- Request:
UpdateMetadataContract.MetadataRequest.buildMessage(responseMessenger, false) - Results:
GET_UPDATES_LIST→UpdateMetadataContract.MetadataListResponse.extractUpdateList(payload)returns aList<UpdatePackage>. EachUpdatePackageexposesgetUpdateId(),getVersion(),getChannel(), andgetFileSize().GET_UPDATES_UP_TO_DATE→ no newer version is available.
- Error:
GET_UPDATES_ERROR→UpdateMetadataContract.MetadataErrorResponse.extractErrorMessage(payload).
- Request:
UpdateDownloadContract.DownloadRequest.buildMessage(responseMessenger, updateId) - Results:
DOWNLOAD_UPDATE_PROGRESS→UpdateDownloadContract.DownloadProgressResponse.extractDownloadProgress(payload)returns 0–100 (or-1for indeterminate).DOWNLOAD_UPDATE_SUCCESS→UpdateDownloadContract.DownloadSuccessResponse.extractUpdateId(payload).
- Error:
DOWNLOAD_UPDATE_ERROR→UpdateDownloadContract.DownloadErrorResponse.extractErrorMessage(payload).
- Request:
UpdateInstallationContract.InstallationRequest.buildMessage(responseMessenger, updateId) - Results:
INSTALL_UPDATE_PROGRESS→UpdateInstallationContract.InstallationProgressResponse.extractInstallationProgress(payload).INSTALL_UPDATE_REBOOT_REQUIRED→ installation finished; the device must reboot to apply the update.
- Error:
INSTALL_UPDATE_ERROR→UpdateInstallationContract.InstallationErrorResponse.extractErrorMessage(payload).
The full set of response codes is defined in
MessengerConfig.ResponseReason. Those handled by this sample:
| Reason | Meaning |
|---|---|
GET_OS_VERSION_RESULT |
Installed OS version returned |
GET_OS_VERSION_ERROR |
Version lookup failed |
GET_UPDATES_LIST |
One or more updates available |
GET_UPDATES_UP_TO_DATE |
System is up to date |
GET_UPDATES_ERROR |
Update check failed |
DOWNLOAD_UPDATE_PROGRESS |
Download progress (0–100, -1 = pending) |
DOWNLOAD_UPDATE_SUCCESS |
Download complete |
DOWNLOAD_UPDATE_ERROR |
Download failed |
INSTALL_UPDATE_PROGRESS |
Installation progress |
INSTALL_UPDATE_REBOOT_REQUIRED |
Installed; reboot needed to apply |
INSTALL_UPDATE_ERROR |
Installation failed |
InvalidUpdatePayloadException is thrown by the extractors if a response
payload is malformed; the sample catches it in handleMessage.
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apkLaunch the app on an emteria OS device and use the on-screen buttons — Get OS version, Check for updates, Download update, Install update — in that order. The text box shows the current state and the progress bar reflects download/installation progress.
- "Service not bound, try again" — the OTA service could not be bound.
Confirm you are on an emteria OS device and that the
<queries>entry above is present in your manifest. - All operations silent / no response — same cause as above; the service is absent on non-emteria systems.
- OS version reads
0.0.0— the app is not running on emteria OS.
See the repository for licensing information. For SDK questions, contact emteria support.