(Android) Slate+ Expand Samples with Riiiver
This is a sample app with which you can learn how to integrate the Riiiver SDK into your companion app for Slate+.
With this app you'll find:
- Expansion of UX with Slate+ by utilizing the Riiiver SDK.
- How the Riiiver functions, piece(s) and iiidea(s), work.
- User Interface provided by our SDK, e.g. login screen, iiidea list screen.
How does this sample demonstrate?
- (1) Scan BLE devices nearby.
(2) Connect to Slate+ evaluation board(EVB).
- Discover the service and characteristics provided as
Riiiver_Demo
by QCLI.
- Discover the service and characteristics provided as
(3) Login to Riiiver.
- (4) Complete the setup of the functions.
- (5) Assign the Riiiver functions that'll be triggered by pushing the button on the EVB.
- Push the button and find the result that appears on the display of the EVB.
Screenshots
Out of scope for this Sample App
- This app is not a template. Integrate our SDK to your app as you like, e.g. you can choose a suitable architecture for your app.
- This app does not implement data storage that keeps the app state even after killing and relaunching the app.
- This app does not implement a complete paring of BLE connection. The Riiiver functions only work when the connection is alive between Slate+ and your mobile phone.
Prepare for development using Riiiver SDK
Preparing for development
What this section describes:
- Sign up as a developer
- [resource file]
erconfiguration.json
To develop with Riiiver SDK, sign up as a developer and register information about your service. Please visit our developer site and sign up by following the instructions.
The required information is as follows:
- Your company information.
- Your application information.
- Your device information.
Riiiver SDK reads vendor and app information by referring to the erconfiguration.json
file. The VendorId
and AppId
should be the IDs that Riiiver has given you when you registered your vendor and app information.
The prepared erconfiguration.json
file must be located in the directory of res/raw
.
Using Riiiver SDK features
Initialize the Riiiver SDK
What this section describes:
- [method]
initialize(Context, String, Int, List<String>)
- [method]
addListener(ERSdkListener)
- [protocol]
ERSdkListener
Be sure to execute the initialize(Context, String, Int, List<String>)
method before using any of the methods provided in the Riiiver SDK.
The implementation is designed to return immediately if it has already been initialized, so it does not matter how many times it is called. The argument is passed the ID of the device supported by the application as an Array of String. If you have not registered your device information, please visit our developer site and register it first.
Also, since the ERSdkListener
protocol is provided to delegate processing to the app side when an event occurs in the Riiiver SDK, we use the addListener(ERSdkListener)
method to set the delegate after initialization is completed. This method is also implemented to do nothing if the delegate instance is the same, so it does not matter how many times it is called.
The ERSdkListener
protocol provides the following delegate methods, so please implement the necessary processing.
Methods of ERSdkListener
startApplet(ERAppelt, ERError?)
Called when the execution of iiidea is started.
endApplet(ERApplet, ERBlockName, Map<String, Any>?, ERError?)
Called when the execution of iiidea has finished.
ERBlockName
is the type of Piece (trigger, service, or action) that terminated. In case of abnormal termination, it will tell which Piece has been reached. Also,ERError
contains error information.onLogin(List<ERApplet>)
Called when login to Riiiver is completed.
onLogout(ERError?)
Called when users log out of Riiiver.
- Note
- - `Applet` is the name of iiidea when developing Riiiver. Please read "iiidea" instead of "applet" as it is used in the code and documentation.
- `Block` is the name of piece when developing Riiiver. Please read "piece" instead of "block" as it is used in the code and documentation.
Use the authentication features(login and out)
What this section describes:
- [method]
getLoginUrl()
- [method]
verifyCodeOf(Uri)
- [method]
logout()
An authentication page is provided to login to Riiiver. Please open the URL in the return value of the getLoginUrl()
method
When a user completes the login operation on the authentication page, a redirect will occur. The redirect URL is registered as a part of your application information via our developer site. If you have not registered, please visit our developer site and register the redirect URL. Please add it in AndroidManifest.xml
so that the app can be launched via a custom scheme.
<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="$your_redirect_uri" /> </intent-filter>
Also add the parameter of deeplinks
to your composable function where you want to receive the redirect. When the app is launched via a custom scheme, a short-lived authorization code is given as a query parameter in the URL. The parameter is named token
. So the parameter for uriPattern
of NavDeepLink
should be your_redirect_uri:///weblogin?token={token}
. To complete the login to Riiiver, please invoke verifyCodeOf(Uri)
method.
If you want to log out of Riiiver, execute the logout()
method at any time.
Display the iiidea list and the settings screen
What this section describes:
- [class]
ERUserWebPagesView
- [protocol]
ERUserWebPagesViewDelegate
We provide a web page that aggregates a iiidea store for users to search for and obtain iiidea, and a list view for users to set or delete already obtained iiidea. The ERUserWebPagesView
class, which inherits from the WebView
class, is provided as a class for displaying these web pages. The loadPage(ERPageType)
method can be executed to display the page.
Some iiidea require the use of device's permissions or OAuth authentication for third-party services at runtime, so when a user requests those permissions on a web page, the ERUserWebPagesViewDelegate
protocol is provided to delegate the handling of those events to the app side. The following delegate methods are provided for this delegate, so please implement the necessary processing.
Methods of ERUserWebPagesViewDelegate
.
didReceivePermissionRequest(ERPermissionType)
Called when the request button for a device's permission on a web page is tapped. The type of permission being requested is passed as an argument, so that you can present the user with the permission's usage authorization dialog.
didReceiveOpenUrlRequest(String)
Called when a new URL needs to be opened, such as for OAuth authentication. Open the URL passed as argument.
didReceiveCloseRequest()
Called when the close button on the web page is tapped.
onError(ERError)
Called when an error occurs on a web page.
Once the necessary settings for iiidea have been completed, iiidea can be activated. iiidea is activated and is ready to run.
Pre-install some iiidea(s)
What this section describes:
- [method]
forcedDownloadApplet(List<String>)
If you want to make pre-installed some features when the user installs your application, you can use the forcedDownloadApplet(appletIds:)
method to make the iiidea of the ID specified in the argument already obtained.
Get the available iiideas list
What this section describes:
- [method]
getMyApplets(List<String>)
- [class]
ERApplet
This sample app is implemented so that each of the two physical buttons on the Slate+ evaluation board can execute a different iiidea when pressed. For this purpose, the app provides a UI that allows the user to freely select the iiidea to be executed. At this time, the method getMyApplets(List<String>)
is used to retrieve the list of iiidea already obtained by the user. By passing a device ID as an argument in the form of a list of String, a list of available iiideas on that device can be obtained. The return value is a list of ERApplet
.
The ERApplet
class provides properties containing iiidea metadata, as well as methods related to activation deactivation and iiidea execution. When you want to find out if a iiidea is ready to run (activated state), you can call getActivateStatus()
method.
Implement the Piece(s) and execute iiidea
What this section describes:
- [protocol]
ERBlockExecutor
- [protocol]
ERBlockDelegate
iiidea is a small application that combines 3 Pieces. We call Trigger Piece for the first one, Service Piece for the second one, and Action Piece for the third one, respectively.
All Pieces implemented in the app or SDK must inherit the ERBlockExecutor
protocol. The following methods are defined in this protocol, so please implement the necessary processing.
Methods of ERBlockExecutor
enable(ERApplet)
Called when an
ERApplet
using this Piece is activated by the user. Return true if the piece can be activated, or false if it cannot be activated.Although there is no example implementation in this sample app, the geofence trigger implemented in the SDK, for example, checks whether permission to use location information has been obtained and returns false if permission has not been obtained.
execute(ERApplet, ERBlockName, Map<String, Any>?, Map<String, Any>?, ERBlockDelegate)
Called when an
ERApplet
that uses this Piece is executed and in the order of execution of this Piece. When the processing of the Piece is completed, you need invoke thecompleted(Map<String, Any>?. ERError?)
method of theERBlockDelegate
. In case of abnormal termination, call that method with the argumentERError
.Note that this method is called when it turns activated in the case of the first Piece of iiidea, the trigger Piece. It is necessary to make sure that the execution of iiidea starts when the desired event actually occurs. In the
QCC5100TriggerPieceCore
, which fires when a button on the Slate+ EVB is pressed by the user, theQCC5100TriggerPieceCore
instance holds the iiidea id and aERBlockDelegate
for it in the form of map type. And it implements thedidTrigger(String, Map<String, Any>?)
method to notify events. At the timing when theonCharacteristicChanged(BluetoothGatt, BluetoothGattCharacteristic, ByteArray)
method ofBluetoothGattCallback
is called where the received value corresponds to the button press event, thedidTrigger(String, Map<String, Any>?)
method is called to start iiidea execution.disable(ERApplet)
Called when an
ERApplet
that uses this Piece is deactivated. Implement a process such as releasing resources that needed to be held while waiting for execution.For example, the geofence trigger implemented in the SDK stops monitoring location information.
Run iiidea from outside the app using Firebase
What this section describes:.
- [method]
setNotificationToken(String)
- [method]
executeTaskForRemoteNotification(Map<String, String>)
Preparation
The Firebase Cloud Messaging API is used to achieve this. The following files are required to use the function.
- google-services.json
Add these dependencies in your build.gradle.kts
.
// Firebase implementation(platform("com.google.firebase:firebase-bom:32.7.4")) implementation("com.google.firebase:firebase-messaging")
FirebaseMessaging Setup
In order to use the FirebaseMessaging APIs, some implementation is required. In this sample, we prepare the FcmService
to handle Firebase Messaging tasks, and start it in onCreate(Bundle?)
of main activity.
Implement the onNewToken(String)
method, which will be called when the new FCM token is issued. And in that method, execute the setNotificationToken(Strng)
method to set the FCM token to the Riiiver SDK.
Implement the onMessageReceived(RemoteMessage)
method, which is called when a data message is received using Firebase (cf. message type). The received push notification is passed to the Riiiver SDK to delegate subsequent processing. Use the executeTaskForRemoteNotification(Map<String, String>)
method.
For Riiiver-based data messages, the RemoteMessage.data
contains the classification information of the push notification with the key "notification_id"
. If your project already uses Firebase, you can branch the process depending on the presence or absence of this key. In other words, determine if this key is included and execute the executeTaskForRemoteNotification(Map<String, String>)
method only if it is included.
val notificationId = remoteMessage.data["notification_id"] notificationId?.let { if (it == "link") { Timber.i("## Remote push for executing an iiidea") QCC5100Queue.enqueue(P2WCommand.DISPLAY) } riiiverSdkClient.executeTaskForRemoteNotification(remoteMessage) } ?: run { Timber.d("## Remote push does not have a notification_id (Riiiver SDK does not handle it)") // do something if needed }