Using the Sensors API



Sensor support in Android is fairly simple yet versatile. It is handled via the SensorManager which is provided from your app context via getSystemService(). Once you have the sensor manager, you have to register to get its notifications. To do this, we implement the SensorListener interface.

Notice that we register to get sensor updates in onResume() and unregister in onPause(). This is important. Sensors data come in erratic intervals and can consume a lot of CPU and battery power. To optimize our app for performance, it is the best practice to get the notifications just while your app is in running state.

The notifications come via onSensorChanged() and onAccuracyChanged(). Notice that each has a parameter for the sensor reporting. Android sensor API can support a large number of sensors, each one having its own unique integer ID. The current ones are expressed via their constants, such as SensorManager.SENSOR_ORIENTATION.

The sensor values we get in onSensorChanged() will depend on the specific sensor. For example, orientation sensor reports azimuth as value at index 0, pitch at index 1 and roll at index 2.



SensorsDemo.java
Code:

package com.marakana;

import android.app.Activity;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class SensorDemo extends Activity implements SensorListener {
private static final String TAG = "SensorDemo";
private SensorManager sensorManager;
private TextView outView;
private int sensor = SensorManager.SENSOR_ORIENTATION;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
outView = (TextView) findViewById(R.id.output);

// Real sensor manager
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
}

/** Register for the updates when Activity is in foreground */
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
sensorManager.registerListener(this, sensor);
}

/** Stop the updates when Activity is paused */
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause");
sensorManager.unregisterListener(this, sensor);
}

public void onAccuracyChanged(int sensor, int accuracy) {
Log.d(TAG, String.format("onAccuracyChanged sensor: %d accuraccy: %d",
sensor, accuracy));
}

public void onSensorChanged(int sensorReporting, float[] values) {
if (sensorReporting != sensor)
return;

float azimuth = Math.round(values[0]);
float pitch = Math.round(values[1]);
float roll = Math.round(values[2]);

String out = String.format("Azimuth: %.2f\n\nPitch:%.2f\nRoll", azimuth,
pitch, roll);
Log.d(TAG, out);
outView.setText(out);
}
}

The layout for this example is trivial, containing one TextView for the output.

/res/layout/main.xml
Code:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/output" android:layout_width="fill_parent"
android:text="@string/hello" android:textSize="24sp"
android:layout_height="fill_parent" android:layout_margin="30dp" />
</LinearLayout>



Notice that emulating sensors in the emulator is not supported. There is a way via an OpenIntents tool, but requires a bit of setup. Here's what the output looks like on the real device:


Source Code:

https://www.protechtraining.com/static/tutorials/SensorDemo.zip

Published November 18, 2009