Developer Guide Mobile App Engine (Android)
Getting Started
Step 1: Get the Mobile App Engine and an API Key from Arrayent
The Arrayent Mobile App Engine for Android is only available to existing Arrayent customers. If you are an existing customer with a contractual agreement to use the Mobile App Engine, complete the instructions below to get your API Key and Mobile App Engine package. If you are not an existing Arrayent customer, contact sales@arrayent.com to request access.
- Decide on a package name. We recommend a package that conforms to the following pattern:
com.<company>.<project>.<app>
- Submit a customer support ticket to Arrayent. Provide your package name in the ticket. Request the following items from Arrayent:
- Mobile App Engine for Android
- API Key
- Application Name
- Cloud URL
See the following to learn how to submit support requests: Zendesk
If you ever change your package name you will need to submit a new customer support ticket and get a new API key from Arrayent.
Step 2: Import the App Engine
- Go to the File menu, select Import Module and choose your appengine-android folder. Hit the Finish button. Please wait a couple minutes to sync the appengine-android module.
- Click on the Project explorer, open settings.gradle and add the following entries
include ':appengine-android' include ':appengine-android:Volley' include ':appengine-android:ZXing'
- Click on the Project explorer, open build.gradle of the app module and add the following entries under dependencies
compile project (':appengine-android')
- Verify that you can now see appengine-android in your Project explorer.
API Overview
This chapter contains an overview of how to use the Arrayent Mobile App Engine API in your project. See the example application and Javadocs contained inside of the Arrayent Mobile App Engine for more detailed examples and documentation.
Initialization
When initializing the Mobile App Engine (Step 1: Get the Mobile App Engine and an API Key from Arrayent), pass your API Key as an argument.
Arrayent.init(appContext,API_KEY);
App Permissions
Define the following permissions in AndroidManifest.xml
:
<usespermission android:name="android.permission.INTERNET"/> <usespermission android:name="android.permission.ACCESS_WIFI_STATE"/> <usespermission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Content Provider
Define the following content provider in AndroidManifest.xml
:
<!-- AndroidManifest.xml --> <provider android:name="com.arrayent.appengine.database.provider.ArrayentContentProvider" android:authorities ="com.arrayent.appengine.test.provider" android:exported= "false"></provider>
In the com.arrayent.appengine.data
package define a file called ArrayentContentProviderAuthority.java
with the following contents:
// ArrayentContentProviderAuthority.java package com.arrayent.appengine.data; public class ArrayentContentProviderAuthority { public static final String CONTENT_AUTHORITY = "com.arrayent.appengine.test.provider"; }
CONTENT_AUTHORITY
must matchandroid:authorities
.
Configuration
Cloud Environments
By default the Mobile App Engine points to the Arrayent DevKit cloud environment:
https://DevKit-api.arrayent.com:8081/zdk/services/zamapi/
To point the application to a different environment, use setCloudUrl()
:
public static final String CLOUD_URL = "https://SUBDOMAIN.arrayent.com:8081/zdk/services/zamapi/"; Arrayent.getInstance().setCloudUrl(CLOUD_URL);
CLOUD_URL
must be a URL like the following:
``https:://<SUBDOMAIN>.arrayent.com:8081/zdk/services/zamapi/``
Replace <SUBDOMAIN>
with the subdomain of your cloud environment. Do not modify anything else in the URL.
Application Name
Use setApplicationName()
to specify an application name on the Arrayent Cloud. This is only needed for applications using the Arrayent Web Service v2 API:
public static final String APPLICATION_NAME = "Thunderbolt"; Arrayent.getInstance().setApplicationName(APPLICATION_NAME);
Database Caching
Setting the Mobile App Engine to demonstration mode forces the Mobile App Engine to return pre-populated data from a locally stored database file, rather than actually send web service requests to the Arrayent Cloud. The database file should be stored in the assets
directory of your application. To set the Mobile App Engine to demonstration mode:
Arrayent.getInstance().setDatabaseCachingType(DatabaseCachingType.DBCT_DEMO); Arrayent.getInstance().setDatabaseName("ArrayentDemo");
To set it to normal mode:
Arrayent.getInstance().setDatabaseCachingType(DatabaseCachingType.DBCT_FULL); Arrayent.getInstance().setDatabaseName("");
Changing modes resets the Object Factory and forces the Mobile App Engine to return new objects. Other caching modes are not yet supported.
Object Factory
The Object Factory class provides concrete objects for all the management classes that can have multiple implementations depending on the state of the application. Never keep a local copy of any object. Always use the Object Factory for requesting objects. For example, to retrieve the account management instance:
ObjectFactory.getInstance().getAccountMgmtInstance();
Account and Session Management
Login and Authentication
To log in to the Arrayent Cloud as a Customer Account:
ObjectFactory.getInstance().getAccountMgmtV2Instance() .login(userName, password, new UserLoginSuccessCallback() { @Override public void onResponse(UsersInfoResponse response) { // Implement as needed. } }, new ArrayentErrorCallback () { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
Logout
To log out of the Arrayent Cloud:
ObjectFactory.getInstance().getAccountMgmtInstance() .logout(new LogoutSuccessCallback() { @Override public void onResponse(ReturnCodeResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
Logging out clears all session tokens from the Mobile App Engine.
Get User Account Information
To retrieve the current values for all of the user attributes for the currently logged in user:
ObjectFactory.getInstance().getAccountMgmtInstance() .getAccount(userId, new GetAccountSuccessCallback() { @Override public void onResponse(GetAccountResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
Set User Account Information
To set the value of a user attribute:
ObjectFactory.getInstance().getAccountMgmtInstance() .updateAccount(new HashMap<String, String>(), new UpdateAccountSuccessCallback() { @Override public void onResponse(ReturnCodeResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
Device Management
To retrieve a list of current defined Device Types (device data models):
ObjectFactory.getInstance().getDeviceMgmtInstance() .getDeviceTypes(new GetDeviceTypesSuccessCallback() { @Override public void onResponse(GetDeviceTypesResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError response) { // Implement as needed. } } );
Add Device
To add a device to the user account:
ObjectFactory.getInstance().getDeviceMgmtInstance() .addDeviceToAccount(deviceCode, deviceType, new AddDeviceSuccessCallback() { @Override public void onResponse(AddDeviceResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
Get Device
To get the current device attribute values of a single device (as well as information about each the definition of each device attribute):
ObjectFactory.getInstance().getDeviceMgmtInstance() .getDevice(deviceId, typeName, new GetDeviceSuccessCallback() { @Override public void onResponse(GetDeviceResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
Get Devices Attributes With Value Since Time
To get all device attributes which have been updated on or after a specified timestamp (in milliseconds):
ObjectFactory.getInstance().getDeviceMgmtInstance() .getDeviceUpdatesSince(deviceId, typeName, timestampSince , new GetDeviceSuccessCallback() { @Override public void onResponse(GetDeviceResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
Set timestampSince
to 0
to return all attributes. When this operation is used in combination with Periodic Update, the timestamp will be automatically calculated and updated by the Arrayent engine.
Get Multiple Devices
To perform the equivalent of getDevice()
(Get Device) on multiple devices simultaneously, provide a HashMap
of key-value pairs, where the key is an Integer
representing the Device ID, and the value is a String
representing the Device Type:
ObjectFactory.getInstance().getDeviceMgmtInstance() .getDevice(new HashMap<Integer, String>(), new GetDeviceSuccessCallback() { @Override public void onResponse(GetDeviceResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
Set Device
To set a device attribute (i.e. send a command to a device):
ObjectFactory.getInstance().getDeviceMgmtInstance() .updateDevice(deviceId, new HashMap<String, String>(), new UpdateDeviceSuccessCallback() { @Override public void onResponse(ReturnCodeResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
You can set up to seven attributes with a single call.
Delete Device
To delete a device from a user account (so that the user can no longer monitor and control it):
ObjectFactory.getInstance().getDeviceMgmtInstance() .removeDevice(deviceId, new RemoveDeviceSuccessCallback() { @Override public void onResponse(ReturnCodeResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
Alert Management
For general information about alerts see Alerts.
Create Alert
To create a new alert:
ObjectFactory.getInstance().getAlertMgmtInstance() .addTrigger(triggerConfig, new AddTriggerSuccessCallback() { @Override public void onResponse(AddTriggerResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
The TriggerConfig
class contains the following properties:
Name | Description |
---|---|
attrName |
The name of a Device Attribute defined in the Device Type. |
operation |
One of the following boolean operators: > , >= , < , <= , == ,regex , equals . |
threshold |
A numerical threshold value. Omit if operation is regex orequals . |
stringThreshold |
A string threshold value. Only include when operation isregex or equals . |
Enable / Disable Alerts
To enable or disable a single alert:
ObjectFactory.getInstance().getAlertMgmtInstance() .enableTrigger(triggerId, true, new EnableTriggerSuccessCallback() { @Override public void onResponse(ReturnCodeResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
Note that this method is called enableTrigger
. There is also a separate method called enableTriggers
, discussed next. To simultaneously enable or disable all alerts for all devices owned by this user:
ObjectFactory.getInstance().getAlertMgmtInstance() .enableTriggers(true, new EnableTriggersSuccessCallback() { @Override public void onResponse(ReturnCodeResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
To simultaneously enable or disable all alerts for a single device owned by this user:
ObjectFactory. getInstance ().getAlertMgmtInstance() .enableTriggersByDeviceId(deviceId, true, new EnableTriggerByDeviceSuccessCallback() { @Override public void onResponse(ReturnCodeResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
Delete Alerts
To delete a single alert:
ObjectFactory.getInstance().getAlertMgmtInstance() .removeTrigger(triggerId, new RemoveTriggerSuccessCallback() { @Override public void onResponse(ReturnCodeResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
To delete all alerts defined for a single device:
ObjectFactory. getInstance ().getAlertMgmtInstance() .removeTriggersByDeviceId(deviceId, new RemoveTriggerByDeviceSuccessCallback() { @Override public void onResponse(ReturnCodeResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
To delete all alerts for all devices owned by this user:
ObjectFactory. getInstance ().getAlertMgmtInstance().removeTriggers(new RemoveTriggersSuccessCallback() { @Override public void onResponse(ReturnCodeResponse response) { // Implement as needed. } }, new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } } );
Push Notifications
Setup
- Go to http://cloud.google.com/console.
- Click CREATE PROJECT.
- Enter a Project Name and Project ID.
- Click on your newly created project.
- Record your Project Number. This will be used for
SENDERID
in the Arrayent Mobile App Engine. - Click on APIs & auth > APIs and enable Cloud Messaging for Android.
- Click on APIs & auth > Credentials and click CREATE NEW KEY.
- Click Browser Key.
- Record your API Key.
- Upload your API Key to the Arrayent Cloud via the Arrayent Configurator.See Configurator Reference for more information on using the Configurator.
Initializing Push Notifications
To initialize the application to be able to receive push notifications:
RegisterDeviceSuccessCallback successCallback = new RegisterDeviceSuccessCallback() { @Override public void onResponse(RegisterDeviceResponse response) { Log. d ("TAG", "Device Registered on Arrayent Cloud, For push notifications register separately."); } }; ArrayentErrorCallback errCallback = new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { Log. d ("TAG", "Failed in registering device on Arrayent Cloud."); } }; String mobileAppName= "enter your package name here"; Arrayent.getInstance().initPush(SENDER_ID, mobileAppName, this, successCallback, errCallback);
Recall that SENDER_ID
is the ProjectNumber
of your Google application. See Setup for review. It is recommended to use your application package name as the mobileAppName.
Registering / Unregistering for Push Notifications
To register the device to receive push notifications:
RegisterDeviceSuccessCallback successCallback = new RegisterDeviceSuccessCallback() { @Override public void onResponse(RegisterDeviceResponse response) { Log.d ("TAG", "Device Registered on Arrayent Cloud and now will receive push notifications"); } }; ArrayentErrorCallback errCallback = new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { Log.d ("TAG", "Failed in registering device for push notifications."); } }; String mobileAppName= "enter your package name here"; ObjectFactory.getInstance().getAlertMgmtInstance().registerDevice(successCallback, errCallback,mobileAppName);
To unregister the device and stop receiving push notifications:
UnregisterDeviceSuccessCallback successCallback = new UnregisterDeviceSuccessCallback() { @Override public void onResponse(UnregisterDeviceResponse response) { Log. d ("TAG", "Device UnRegistered from Arrayent Cloud and now will not receive push notifications"); } }; ArrayentErrorCallback errCallback = new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { Log. d ("TAG", "Failed to unregister device for push notifications."); } }; ObjectFactory. getInstance ().getAlertMgmtInstance().unRegisterDevice(successCallback, errCallback);
Periodic Updates
Use periodic updates to call Mobile App Engine API methods (e.g. getDevice()
) on a regular interval:
public void testGetDevicePeriodicUpdate() { GetDeviceSuccessCallback successCallback = new GetDeviceSuccessCallback() { @Override public void onResponse(GetDeviceResponse response) { Logger.i("PeriodicUpdate", "Success"); } }; ArrayentErrorCallback errorCallback = new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { Logger.e("PeriodicUpdate", "Error"); } }; ArrayList<Object> paramList = new ArrayList<Object>(); paramList.add(new Integer(19282)); // Device ID paramList.add(new String("monitorDemo")); // Device Type Timer timer = ObjectFactory.getInstance() .getPeriodicUpdateInstance() .startTimerForUpdates(APIType.IDEV_GETDEVICE , 0, 30, paramList, successCallback, errorCallback); // When periodic update is no longer needed... timer.cancel(); timer.purge(); }
QR Code Scanning
The Mobile App Engine contains a QR code scanner API. When an end user wants to add a device to his account, he can scan the QR code on the device. This is usually more convenient than reading a label and manually typing in a Device Code.
public void testScanQRCode() { ScanQRCodeSuccessCallback successCallback = new ScanQRCodeSuccessCallback() { private static final long serialVersionUID = 8422668011428663568L; @Override public void onResponse(String response) { Logger.i("QRCode", "Scanned QRCode is " + response); } }; ScanQRCodeErrorCallback errorCallback = new ScanQRCodeErrorCallback() { private static final long serialVersionUID = 4752830679000086135L; @Override public void onResponse(ArrayentError error) { Logger.e("QRCode", "QRCode scanning failed (" + error.getErrorMessage() + " : " + String. valueOf(error.getErrorCode()) + ")"); } }; UtilityMgmt.scanQRCode(successCallback, errorCallback); }
The application will transition to the screen below after calling testScanQRCode()
.
Ecosystem Integration
Cloud Environments
To point the application to a different ecosystem environment, use setEcoCloudUrl()
:
public static final String ECO_CLOUD_URL = "https://SUBDOMAIN.arrayent.com/ecoadaptors/"; Arrayent.getInstance().setEcoCloudUrl(ECO_CLOUD_URL);
ECO_CLOUD_URL
must be a URL like the following:
``https:://<SUBDOMAIN>.arrayent.com:8081/ecoadaptors/``
Replace <SUBDOMAIN>
with the subdomain of your cloud environment. Do not modify anything else in the URL.
Update Federated Token
The updateFederatedToken API is used to register federated token with Arrayent Ecosystem Cloud.
public void testUpdateFederatedToken() { String accessToken = "ecosysten_access_token"; String ecoSystemName = "Nest"; UpdateFederatedTokenSuccessCallback successResponseHandler = new UpdateFederatedTokenSuccessCallback() { @Override public void onResponse(UpdateFederatedTokenResponse response) { // Implement as needed. } }; ArrayentErrorCallback arrayentErrorCallback = new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { // Implement as needed. } }; ObjectFactory.getInstance().getAccountMgmtInstance().updateFederatedToken(accessToken, ecoSystemName, successResponseHandler , arrayentErrorCallback); }
Delete Federated Token (Un-federate ecosystem)
The unFederateEcosystem API is used to un-federate the ecosystem device with Arrayent Ecosystem Cloud.
String mEcoSystemName = "Nest"; DeleteFederatedTokenSuccessCallback successResponseHandler = new DeleteFederatedTokenSuccessCallback () { @Override public void onResponse(UpdateFederatedTokenResponse response) { } }; ArrayentErrorCallback arrayentErrorCallback = new ArrayentErrorCallback() { @Override public void onResponse(ArrayentError error) { } }; ObjectFactory.getInstance().getAccountMgmtInstance().unfederateEcosystem(mEcoSystemName, successResponseHandler, errorResponseHandler);
Troubleshooting
Android Support JAR Compilation Error
Problem A compilation error related to the Android Support JAR is reported. Solution Replace the Android Support JAR in the Mobile App Engine with the version that your application is using. This error occurs because the Mobile App Engine is bundled with a specific version of the Android Support JAR and the application is using a different version.