Third-party Integration with Android Client v1 | Update Factory
Warning
These APIs are deprecated. Use of APIs v1.2 is recommended when using UF Android Service ≥ v1.4.
uf-android-service has a set of APIs that allow a third party application to interact with it.
To integrate the uf-android-service into your application you must:
- Import the module
uf-client-service-api
(see Module uf-client-service-api section) - Bind to the uf-android-service service (see Bind to uf-android-service service section)
The UF Service API Reference Implementation provides an example third party application that is able to:
- show the current service status
- open the preferences page of uf-android-service (Settings page)
- grant authorization to execute an action during a soft update
Bind to uf-android-service¶
uf-android-service is a bound service, it allows components (such as activities) to bind to the service, send requests, receive responses, and perform inter-process communication.
To bind with the service create an intent with:
- action =
UFServiceInfo.SERVICE_ACTION
- package =
UFServiceInfo.SERVICE_PACKAGE_NAME
This is an example of how to bind an Application with the service:
private val mService:Messenger;
private val mConnection = object : ServiceConnection {
override fun onServiceConnected(
className: ComponentName,
service: IBinder
) {
mService = Messenger(service)
Toast.makeText(this@MainActivity, R.string.ui_connected,
Toast.LENGTH_SHORT).show()
handleRemoteException {
mService!!.send(Communication.V1.In.RegisterClient(mMessenger).toMessage())
mService!!.send(Communication.V1.In.Sync(mMessenger).toMessage())
}
mIsBound = true
}
override fun onServiceDisconnected(className: ComponentName) {
Log.i(TAG, "Service is disconnected")
doUnbindService()
}
override fun onBindingDied(name: ComponentName?) {
Log.i(TAG, "Service binding is died")
mIsBound = false
}
}
private fun doBindService() {
val intent = Intent(UFServiceInfo.SERVICE_ACTION)
intent.setPackage(UFServiceInfo.SERVICE_PACKAGE_NAME)
intent.flags = FLAG_INCLUDE_STOPPED_PACKAGES
val serviceExist = bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
if (!serviceExist && !mServiceExist) {
Toast.makeText(applicationContext, "UpdateFactoryService not found", Toast.LENGTH_LONG).show()
unbindService(mConnection)
this.finish()
} else {
mServiceExist = true
}
}
private fun doUnbindService() {
if (mIsBound) {
if (mService != null) {
try {
mService!!.send(Communication.V1.In.UnregisterClient(mMessenger).toMessage())
} catch (e: RemoteException) {
}
}
unbindService(mConnection)
mIsBound = false
}
}
Messages¶
The Android client Service uses Android Messenger to receive user inputs and to notify its status. The uf-client-service-api provides a set of help classes that must be used to communicate with the service (see communication).
For more details see the official documentation.
Module uf-client-service-api¶
The module uf-client-service-api
contains all of the classes that a third party application must include to handle the communication with the uf-android-service
.
uf-client-service-api
contains:
- UFServiceInfo: object class with the main information about the service
- Communication: a set of classes to build (parse) messages to send (receive) to the service
- UFServiceConfiguration: a data class that contains the current configuration of the service
- UFServiceMessageV1: a set of classes that represents the state of the service
To import this module:
- configure your project to use jitpack (see jitpack documentation).
- add
implementation 'com.github.kynetics:uf-android-client:v1.y.z'
, for exampleimplementation 'com.github.kynetics:uf-android-client:v1.2.0'
- if your application is obfuscated, add the following ProGuard rule:
-keep class com.kynetics.uf.android.api.*{
*;
}
See API reference documentation for additional info.
UFServiceInfo¶
UFServiceInfo is an object class with the main information about the service
object UFServiceInfo {
/**
* Package name of the Update Factory Service
*/
const val SERVICE_PACKAGE_NAME = "com.kynetics.uf.service"
/**
* Action to bind with the Update Factory Service
*/
const val SERVICE_ACTION = "com.kynetics.action.BIND_UF_SERVICE"
/**
* Action to open the Update Factory Settings
*/
const val ACTION_SETTINGS = "com.kynetics.action.SETTINGS"
}
UFServiceConfiguration¶
UFServiceConfiguration contains:
tenant
= the name of the tenantcontrollerId
= device idurl
= url of update factory servertargetToken
= device's token to communicate with uf servergatewayToken
= a token in common with all targets to communicate with uf serverisApiMode
= if false, the uf service shows a pop up window asking for user authorization. If true the service sends an AuthorizationRequest message (see In messages)isUpdateFactoryServe
= if true the service is optimized for UFServer, if false the service is optimized for hawkBit servertargetAttributes
= a map of string to string that the service sends to the server.
UFServiceConfiguration(
tenant = <tenant_name>,
controllerId = <controller_id>,
url = <uf_server_url>,
targetToken = <target_token>,
gatewayToken = <gateway_token>,
isApiMode = true,
isEnable = true,
isUpdateFactoryServe = true,
targetAttributes = mutableMapOf("DeviceOS" to "Android")
)
Communication¶
Communication classes are hierarchy organized:
Communication.V1.[<In>
| <Out>
].<message_type>
In
classes represent all messages that can be sent to the service, instead, Out
classes represent all messages that
can be received from the service.
In¶
To send a message to the UF service, you must create an instance of an In class and then invoke the method toMessage
//mService:Messenger;
mService!!.send(Communication.V1.In.RegisterClient(mMessenger).toMessage())
ConfigureService¶
Class to build a message to configure the service.
Arguments:
conf
: new service configuration (instance of UFServiceConfiguration)
RegisterClient¶
Class to build a message to register the client (the service will notify any update to the client)
Constructor Arguments:
replyTo
: Messenger where reply
UnregisterClient¶
Class to build a message to unregister the client to the service
Constructor Arguments:
replyTo
: Messenger where reply
AuthorizationResponse¶
Class to build a message to grant or deny the authorization to download or apply an update.
Constructor Arguments:
granted
:true
to immediately grant authorization,false
to deny authorization until a force ping is called, or the device is rebooted
Note
An AuthorizationResponse
message with granted = false
will cause subsequent AuthorizationResponse
messages with granted = true
to be ignored, until a force ping is called, or the device is rebooted.
A third-party application is not required to provide an immediate answer to an AuthorizationRequest message, and can send an AuthorizationResponse
message with granted = true
at a later time.
Sync¶
Class to build a message which requires a sync with the service. The service will respond with its configuration and its state (see Out section)
Constructor Arguments:
replyTo
: Messenger where reply
ForcePing¶
Class to build a message to force a poll to the Update Factory Server
Out¶
When you receive a message from the service you must use toOutV1Message()
(see kotlin extension function)
function that returns an instance of Out class.
override fun handleMessage(msg: Message) {
val v1Msg = msg.toOutV1Message()
when (v1Msg) {
is Communication.V1.Out.CurrentServiceConfiguration -> handleServiceConfigurationMsg(v1Msg)
is Communication.V1.Out.AuthorizationRequest -> handleAuthorizationRequestMsg(v1Msg)
is Communication.V1.Out.ServiceNotification -> handleServiceNotificationMsg(v1Msg)
}
}
ServiceNotification¶
ServiceNotification contains the current status of the service. It has a field called content
of type UFServiceMessageV1
AuthorizationRequest¶
AuthorizationRequest has a field called authName
that contains the type of authorization (typically one between download and update).
CurrentServiceConfiguration¶
CurrentServiceConfiguration has a field called conf
that contains the current service configuration (an instance of UFServiceConfiguration
)
UFServiceMessageV1¶
Classes that map states and events of Update factory service:
States:¶
Downloading¶
Client is downloading artifacts from server.
Fields:
artifacts
: list of artifacts to download
Artifact¶
Fields:
name
: artifact namesize
: artifact sizemd5
: artifact MD5 checksum
Updating¶
The update process is started. Any request to cancel an update will be rejected.
CancellingUpdate¶
Last update request is being cancelled.
WaitingDownloadAuthorization¶
Waiting authorization to start download.
WaitingUpdateAuthorization¶
Waiting authorization to start update.
Idle¶
Client is waiting for new requests from server.
ConfigurationError¶
Bad service configuration.
Fields:
details
: additional information
Events:¶
Polling¶
Client is contacting server to retrieve new action to execute.
StartDownloadFile¶
A file downloading is started.
Fields:
fileName
: name of the file to download
FileDownloaded¶
A file is downloaded.
Fields:
fileDownloaded
: the file that is downloaded
DownloadProgress¶
Percentage of the file downloaded.
Fields:
fileName
: the file that is downloadedpercentage
: the percentage downloaded (in [0,1])
AllFilesDownloaded¶
All needed file are downloaded.
UpdateFinished¶
The update is finished.
Fields:
successApply
: true if the update is successfully applied, false otherwise.details
: additional details
Error¶
An error has occurred.
Fields:
details
: additional details
UpdateProgress¶
Percentage of phase updated
Fields:
phaseName
: the name of the update phasephaseDescription
: the description of the update phasepercentage
: the percentage of phase
UpdateAvailable¶
An update is available on cloud.
Fields:
id
: update id