Android SDK

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.

  1. Decide on a package name. We recommend a package that conforms to the following pattern:com.<company>.<project>.<app>
  2. 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

  1. 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.../../_images/import_studio-01.png
  2. Click on the Project explorer, open settings.gradle and add the following entries
    include ':appengine-android'
    include ':appengine-android:Volley'
    include ':appengine-android:ZXing'
    

    ../../_images/import_studio-02.png

  3. Click on the Project explorer, open build.gradle of the app module and add the following entries under dependencies
    compile project (':appengine-android')
    

    ../../_images/import_studio-03.png

  4. Verify that you can now see appengine-android in your Project explorer.../../_images/import_studio-04.png

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:

<uses­permission android:name="android.permission.INTERNET"/>
<uses­permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses­permission 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_AUTHORITYmust 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

  1. Go to http://cloud.google.com/console.
  2. Click CREATE PROJECT.../../_images/push-1.png
  3. Enter a Project Name and Project ID.../../_images/push-2.png
  4. Click on your newly created project.
  5. Record your Project Number. This will be used for SENDERID in the Arrayent Mobile App Engine.../../_images/push-3.png
  6. Click on APIs & auth > APIs and enable Cloud Messaging for Android.../../_images/push-4.png
  7. Click on APIs & auth > Credentials and click CREATE NEW KEY.../../_images/push-5.png
  8. Click Browser Key.../../_images/push-6.png
  9. Record your API Key.../../_images/push-7.png
  10. Upload your API Key to the Arrayent Cloud via the Arrayent Configurator.../../_images/push-8.pngSee 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(). ../../_images/qr-1.png

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.