Building Real-Time Android Apps with InfluxDB Cloud: Data Logging, Querying, and Visualization

Navigate to:

With over 8 billion smartphones in use, predominantly running Android, how do you efficiently manage and analyze the flood of real-time data generated by apps, games, and other services? Whether it’s tracking user interactions, monitoring health metrics, or managing IoT devices, handling this data can be overwhelming. Enter InfluxDB Cloud Serverless—a robust, no-cost solution for developers to start storing, querying, and visualizing real-time data without a credit card, and effortlessly gain valuable insights.

In this article, we’ll explore how to integrate Android (Java) with InfluxDB through a ‘Sensor Logging’ use case. We’ll build an Android Java app that captures motion data, specifically from accelerometers and gyroscopes in the x, y, and z axes of a smartphone and stores it in InfluxDB Cloud. This data will be ingested at sub-second speeds and then queried within the app to display a line graph using a third-party charting library.

Building-Real-Time-Android-Apps

Prerequisites

  1. Ensure you have the latest version of Android Studio installed.

  2. Account information: You need access to an InfluxDB instance (local or cloud-based) to get your URL, API Token, Org Name, and Bucket name.

  3. Gradle dependencies: Your project must include the InfluxDB Java client library and the MPAndroidChart library for data visualization purposes.

In your module’s build.gradle file, add the following dependencies to download and use the InfluxDB client library.

dependencies {
    implementation 'com.influxdb:influxdb-client-java:6.10.0'
    implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
  }

Initialize the InfluxDB client

Start by initializing the InfluxDB client in your Android app. The InfluxDBManager class manages the connection and handles data writing and querying.

private void initializeClient() {
  String url = sharedPreferences.getString("INFLUX\_URL", "");
  String apiToken = sharedPreferences.getString("INFLUX\_API\_TOKEN", "");
  String org = sharedPreferences.getString("INFLUX\_ORG", "");
  String bucket = sharedPreferences.getString("INFLUX\_BUCKET", "");

  this.influxDBClient = InfluxDBClientFactory.create(url, apiToken.toCharArray(), org, bucket);
  this.writeApi = influxDBClient.makeWriteApi();
  this.executorService = Executors.newSingleThreadExecutor();
  this.isOpen = true;
}

Write sensor data to InfluxDB bucket using point object

When the app captures sensor data, it writes it to InfluxDB using the writeSensorData() method. The data includes accelerometer and gyroscope readings for each axis.

public void writeSensorData(String measurement, float accelX, float accelY, float accelZ, float gyroX, float gyroY, float gyroZ) {
  if (!isOpen) {
    Log.e("InfluxDBManager", "InfluxDB client is not initialized. Please set credentials first.");
    return;
  }

 Log.d("InfluxDBManager", "Writing data: AccelX=" + accelX + ", AccelY=" + accelY + ", AccelZ=" + accelZ + ", GyroX=" + gyroX + ", GyroY=" + gyroY + ", GyroZ=" + gyroZ);

 Point point = Point.measurement(measurement)
    .addTag("device", android.os.Build.MODEL)
    .addField("accel\_x", accelX)
    .addField("accel\_y", accelY)
    .addField("accel\_z", accelZ)
    .addField("gyro\_x", gyroX)
    .addField("gyro\_y", gyroY)
    .addField("gyro\_z", gyroZ)
    .time(Instant.now(), WritePrecision.MS);

executorService.execute(() -> {
    try {
      writeApi.writePoint(point);
    } 
    catch (Exception e) {
      Log.e("InfluxDBManager", "Error writing to InfluxDB", e);
    }
  });
}

Querying data from InfluxDB

To visualize the captured data, the app queries it from InfluxDB using Flux (flux support is currently limited to cloud serverless). The following method retrieves the data within the last 10 minutes and groups it into 5-second intervals.

public void querySensorData(String query, QueryCallback callback) {
  executorService.execute(() -> {
    try {
      QueryApi queryApi = influxDBClient.getQueryApi();
      List<FluxTable> tables = queryApi.query(query);
      callback.onSuccess(tables);
    } 
    catch (Exception e) {
      Log.e("InfluxDBManager", "Error querying InfluxDB", e);
      callback.onError(e);
    }
  });
}

Displaying sensor data with GraphActivity

In the GraphActivity, the queried sensor data is displayed using a line chart created using the MPAndroidChart library. The refreshData() method updates the chart with the latest data from the InfluxDB Serverless cloud bucket, which just stored the same data.

private void refreshData() {
  String bucket = influxDBManager.getBucket();
  String flux = "from(bucket:\"" + bucket + "\") " +
    "|> range(start: -10m) " +
    "|> filter(fn:(r) => r.\_measurement == \"sensor\_data\") " +
    "|> filter(fn:(r) => r.\_field == \"accel\_x\" or r.\_field == \"gyro\_x\") " +
    "|> aggregateWindow(every: 1s, fn: mean, createEmpty: false) " +
    "|> yield(name: \"mean\")";

influxDBManager.querySensorData(flux, new InfluxDBManager.QueryCallback() {
    @Override
    public void onSuccess(List<FluxTable> tables) {
      List<Entry> accelEntries = new ArrayList<>();
      List<Entry> gyroEntries = new ArrayList<>();

      for (FluxTable table : tables) {
        for (FluxRecord record : table.getRecords()) {
          long time = record.getTime().toEpochMilli();
          double value = (double) record.getValue();
          String field = record.getField();

          if ("accel\_x".equals(field)) {
            accelEntries.add(new Entry(time, (float) value));
          } 
          else if ("gyro\_x".equals(field)) {
            gyroEntries.add(new Entry(time, (float) value));
          }
        }
      }
      runOnUiThread(() -> updateChart(accelEntries, gyroEntries));
    }
    @Override
    public void onError(Exception e) {
      Log.e("GraphActivity", "Error fetching data from InfluxDB", e);
      runOnUiThread(() -> Toast.makeText(GraphActivity.this, "Error fetching data: " + e.getMessage(), Toast.LENGTH\_LONG).show());
    }
  });
}

Conclusion

By integrating InfluxDB with Android, developers can efficiently manage and visualize real-time data from smartphone sensors. Whether for health tracking, wearable applications, or even games, this setup allows for seamless data logging, querying, and visualization directly within the app. Feel free to explore the sample app on GitHub, and remember you can start using InfluxDB Cloud for free. If you have any questions or feedback, don’t hesitate to reach out to us on our community Slack or community forum.