Build an Android app with BLE and ARTIK Cloud

This post updates our previous article to use the ARTIK Cloud endpoint and Java/Android SDK V2.

Today we’re developing an Android app that illustrates how well ARTIK Cloud and Bluetooth low energy (BLE) work together to get device data.

It’s a simple process. We are attempting to get our Android app to locate nearby BLE devices, collect their data and then send it directly to ARTIK Cloud.

Introduction

Many health and fitness sensors today use Bluetooth low energy (BLE) technologies. With this in mind, I want to develop an Android application that scans and connects to nearby BLE devices. The app collects relevant measurements from them, and sends this data to ARTIK Cloud.

Once in ARTIK Cloud, the data is useful in many ways. For example, my app and similar apps can retrieve data. ARTIK Cloud is a data exchange broker, which gives developers the opportunity to use the data from diverse devices in a variety of ways.

Our goal is to collect data from a BLE device and send it to ARTIK Cloud. Then it can be viewed in near-real-time in My ARTIK Cloud.

For this example, we will be using Heart Rate Measurement from a Polar H7 heart rate sensor. But it’s easy to modify the app to collect other Bluetooth measurements.

Demo: Collect data from BLE and view in ARTIK Cloud

  • Let’s focus on the first step. Start AKCnBLE on an Android phone.

ble_screen_1

  • Click “login” and enter your ARTIK Cloud account credentials to login. Note that these are also your Samsung account credentials.
  • Click “Allow” when the app asks for permission to access the data of the Heart Rate Tracker device. This screen appears when you use the app for the first time.
  • After you finish the authentication flow, you will see the “ARTIK Cloud Devices” screen:

ble_screen_2

The first time you open this screen, you will see the “Create a new device” button. On future logins, you can simply select one of your Heart Rate Tracker devices in the “ARTIK Cloud Devices” screen.

  • Click the “Create a new device” button to register your phone as a Heart Rate Tracker device in ARTIK Cloud. Later on, all heart rate data will be sent to ARTIK Cloud on behalf of this device.
  • After clicking the button, the “ARTIK Cloud Devices” screen transitions to the “BLE Device Scan” screen. The screen will list all BLE devices near your phone as follows:

ble_screen_2.5

  • Select one of the devices that sends Heart Rate Measurement—in this case, “Polar H7 Bluetooth Smart Heart Rate Sensor”. You will see the device detail screen:

ble_screen_3

The app attempts to connect to the BLE device. If the connection succeeds, the screen lists all services provided by the device. You will see Heart Rate Service listed for Polar H7.

  • Click “Heart Rate Service”, then “Heart Rate Measurement”. Now the app starts collecting heart rate data from the BLE device.
  • The “Data” field refreshes when new data comes in from the Polar H7.
  • Each data point is sent to ARTIK Cloud on the behalf of the Heart Rate Tracker device that you created (or selected) in the “ARTIK Cloud Devices” screen.
  • The ARTIK Cloud device ID is also shown in the device detail screen.

ble_screen_4

  • Different devices will provide different data points, and you can pick any of them to test. My focus for this prototype is only heart rate, so if you pick a different type, the app will stop receiving heart rate and show an “N/A” in the “Data” and “ARTIK Cloud device ID” fields.
  • Click “BLE Disconnection” to stop the connection between AKCnBLE and the BLE device.
  • Now use the back arrow on the top-left to navigate back to the “BLE Device Scan” screen.
  • Again, use the back arrow on the top-left to navigate back to the “ARTIK Cloud Devices” screen.
  • Click “logout” to logout from ARTIK Cloud.

While the app is collecting heart rate data, you can log into My ARTIK Cloud to view the data in near-real-time. Below is an animated screenshot.

Installation and setup

Once you build the app you are going to need to install it. I’ll walk you through the process with my own account.

I log into the Developer Dashboard to register my Android application on ARTIK Cloud. To properly test my application, I have two separate Samsung accounts with different email addresses:

  1. My official developer account. This is the account I use to log into the Developer Dashboard and register my application.
  2. A simulated user account. This is the account that I used in the above demo to log into ARTIK Cloud on phone and to log into My ARTIK Cloud.

I follow these instructions to create an application. For this Android app, I select the following:

  • Under “AUTHORIZATION METHODS”, check “Client credentials, auth code, implicit”.
  • Set “Redirect URL” to android-app://redirect.
  • Under “PERMISSIONS”, check “Read” for “Profile”.
  • Click the “Add Device Type” button. Choose “SAMI Example Heart Rate Tracker” as the device type. Check “Read” and “Write” permissions for this device type.

Make a note of the client ID, for use in the source file later.

Prepare source files and libraries

I will use the ARTIK Cloud Java/Android SDK, which takes care of managing all my REST calls to ARTIK Cloud. 

  • Check out AKCnBLE from GitHub.
  • In Android Studio, open the project.
  • Use the client ID (obtained above, when registering the app in the Developer Dashboard) to replace YOUR CLIENT ID in ArtikCloudSession.java.

Now build the project, and deploy the APK to an Android phone. I am able to play with the app like in the above demo.

Implementation

Implement the following functionalities:

  1. Create a new device type in ARTIK Cloud, “SAMI Example Heart Rate Tracker”.
  2. Authenticate a user using the OAuth 2.0 workflow.
  3. Collect user information such as the username and user ID.
  4. Get the list of devices that the user owns in ARTIK Cloud.
  5. Add the user’s phone to ARTIK Cloud as a Heart Rate Tracker device.
  6. Establish a WebSocket device channel.
  7. Stream heart rate data to ARTIK Cloud via the channel.
  8. Scan BLE devices, connect to a BLE device, and read heart rate data from it.

For the last functionality above, I use the code of the Android sample application BluetoothLeGatt. There is no need to discuss its implementation here. After you read Android’s documentation on Bluetooth Low Energy, you should be able to understand the implementation related to BLE in this app.

You can easily change the code to collect measurements other than Heart Rate Measurement from BLE devices.

The following code from SampleGattAttributes.java identifies the heart rate measurement. You could do the same for other measurements by consulting Bluetooth Characteristics.

public static String HEART_RATE_MEASUREMENT = "00002a37-0000-1000-8000-00805f9b34fb";

Create the Heart Rate Tracker device type

Creating a new device type for AKCnBLE is easy. I published a device type “SAMI Example Heart Rate Tracker” with multiple data fields (see below). 

HeartRateManifest

Below is the example of the data field in a message:

1 {
2     "heart_rate":70,
3     "comments":"blah"
4 }

This device type is visible to other developers, and can be used by any app, including AKCnBLE.

Authenticate the user

ARTIK Cloud supports multiple OAuth 2.0 workflows.

Since this app is a standalone mobile application, you’ll need to implement the Implicit method in LoginActivity class.

This is similar to the implementation in Section “Login to obtain access token” in Your first Android app.

Get the user’s information

Before the app can query ARTIK Cloud for the devices that the user owns, the app must get the user ID.

ArtikCloudDeviceActivity calls method GetUserInfo to trigger an API call to ARTIK Cloud. This is similar to the implementation in Section “Get user’s name from ARTIK Cloud” in Your first Android app.

Get the list of devices in ARTIK Cloud

ArtikCloudDeviceActivity queries ARTIK Cloud to get the list of the devices that the user owns, and for which the app has read permissions.

Then the list is parsed to identify Heart Rate Tracker devices. Only similar devices show up in the UI. The user can choose which one to use to record heart rate data from a BLE.

Under the hood, the following method makes “Get a user’s devices” REST call!

private void GetDeviceList() {
    try {
       ArtikCloudSession.getInstance().getUsersApi().getUserDevicesAsync(ArtikCloudSession.getInstance().getUserId(),
                null, null, false, new ApiCallback<DevicesEnvelope>() {
                    @Override
                    public void onFailure(ApiException e, int statusCode, Map<String, List<String>> responseHeaders) {
                        processFailure(tag, e);
                    }

                    @Override
                    public void onSuccess(DevicesEnvelope result, int statusCode, Map<String, List<String>> responseHeaders) {
                        UpdateDeviceListOnUIThread(result.getData());
                    }
                ...
                });
    }  catch (ApiException exc) {
        processFailure(tag, exc);
    }
}

Create a heart rate tracker

If the user does not already have a Heart Rate Tracker device in ARTIK Cloud, ArtikCloudDeviceActivity creates such a device for the user.

Later on, heart rate data from a BLE device will be sent to this Heart Rate Tracker device in ARTIK Cloud. Use addDevice to achieve this, which calls “Create a device” REST API:

private void addDevice() {
    cloud.artik.model.Device device = new cloud.artik.model.Device();
    device.setDtid(ArtikCloudSession.DEVICE_TYPE_ID_HEART_RATE_TRACKER);
    device.setUid(ArtikCloudSession.getInstance().getUserId());
    device.setName("ble test device");
    try {
        ArtikCloudSession.getInstance().getDevicesApi().addDeviceAsync(device, new ApiCallback<DeviceEnvelope>() {
            @Override
            public void onFailure(ApiException e, int statusCode, Map<String, List<String>> responseHeaders) {
                processFailure(tag, e);
            }

            @Override
            public void onSuccess(DeviceEnvelope result, int statusCode, Map<String, List<String>> responseHeaders) {
                handleDeviceCreationSuccessOnUIThread(result.getData());
            }
            
            ...

        });
    } catch (ApiException exc) {
        processFailure(tag, exc);
    }
}

Set up a WebSocket device channel

To stream sensor data to ARTIK Cloud in real-time, you need to establish a WebSocket device channel

Method connectDeviceChannelWebSocket() in ArtikCloudSession  opens the WebSocket, then sends a message to ARTIK Cloud to register the device, and finally gets callbacks on various events like onMessage and onClose.

mWebsocket = new DeviceChannelWebSocket(true, new ArtikCloudWebSocketCallback() {
    @Override
    public void onOpen(int i, String s) {
        final RegisterMessage registerMessage = getWSRegisterMessage();
        try {
            mWebsocket.registerChannel(registerMessage);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onMessage(MessageOut messageOut) {
        Log.d(TAG, "DeviceChannelWebSocket: onMessage(" + messageOut.toString() + ")");
    }
    
    @Override
    public void onClose(int code, String reason, boolean remote) {
         Log.d(TAG, "DeviceChannelWebSocket: onClose() code = " + code + "; reason = " + reason + "; remote = " + remote);
    }
  
    ...

});

Stream heart rate data to ARTIK Cloud

After the device channel is established, it is super-easy to send heart rate data to ARTIK Cloud.

I modified BluetoothLeService from the Google sample app to add this functionality. The method sendHeartRateToArtikCloud is called once there is new data from the BLE device.

 1 private void sendHeartRateToArtikCloud() {
 2     ArtikCloudSession.getInstance().onNewHeartRate(rate, System.currentTimeMillis());
 3 }

Eventually the data is sent out in method sendOnDeviceChannelInBackground of ArtikCloudSession:

public void onNewHeartRate(final int heartRate, final long ts) {
    MessageIn message = getWSMessage(heartRate, ts);
    new SendOnDeviceChannelInBackground().execute(message);
}

private class SendOnDeviceChannelInBackground extends AsyncTask<MessageIn, Void, Void> {
    @Override
    protected Void doInBackground(MessageIn... messages) {
        try {
            mWebsocket.sendMessage(messages[0]);
        } catch (Exception e) {
            ...
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        ...
    }
}

The above utility method getWSMessage() assembles WebSocket messages as follows:

1 {"sdid": "<HeartRateTrackerDeviceID>", "ts": "<millisecond when heart rate is received from BLE>", data":{"heart_rate": <integer>}}

Conclusion

It’s easy to connect Bluetooth low energy devices to ARTIK Cloud, as this sample application demonstrates.

Development of the app that interfaces with nearby BLE connections is also simple, thanks to the native SDK. Along with ARTIK Cloud, such a third-party app provides a service that is highly relevant to individual users, because it brings together their data from different types of data sources.

If you found this useful, also see my tutorial Monitor Fire and Temperature Using ARTIK Cloud, Open-Source IoT hardware and Android.

Looking to connect many devices to the cloud and build innovative IoT solutions? Click here to get started for free.