Android sensor test

Demo application to plot the available sensors values.

This demo is used as a basic test of sensors data acquisition, in order to do further development in future (e.g. using the smart phone as controller for other applications).

main-page

The graph are based on androidplot package which is one of the pretty cool to see and easy to use software available to spare development time.

sensor-graphs

Main activity

The main activity extends ListActivity. It is an extended InteractiveArrayAdapter and a push button.

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		ArrayAdapter<Model> adapter = new InteractiveArrayAdapter(this,
				getModel());
		setListAdapter(adapter);

		ListView listView = getListView();
		listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);


		final Button button = (Button) findViewById(R.id.monitorselected);
		button.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {

				ArrayList<String> namesStringList = new ArrayList<String>();
				ArrayList<String> typesStringList = new ArrayList<String>();
				ArrayList<Integer> typesIntList = new ArrayList<Integer>();

				for (Model model : mModelList) {
					if (model.isSelected()) {
						namesStringList.add(model.getName());
						typesIntList.add(model.getSensorType());
						typesStringList.add(Integer.toString(model.getSensorType()));
					}
				}

				Intent intent = new Intent(MainActivity.this, SensorMonitorActivity.class);
				intent.putStringArrayListExtra("names", namesStringList);
				intent.putStringArrayListExtra("typesString", typesStringList);
				intent.putIntegerArrayListExtra("types", typesIntList);
				startActivity(intent);
			}
		});
	}

The list is populated used a predefined list of entries based on the android API.
Querying the system for a particular sensor we can infer if it is really present on that device and disable/enable it.

	private List<Model> getModel() {
		mModelList = new ArrayList<Model>();
		mModelList.add(getModelEntry("Accelerometer", Sensor.TYPE_ACCELEROMETER));
		mModelList.add(getModelEntry("Temperature", Sensor.TYPE_TEMPERATURE));
		mModelList.add(getModelEntry("Gravity", Sensor.TYPE_GRAVITY));
		mModelList.add(getModelEntry("Gyroscope", Sensor.TYPE_GYROSCOPE));
		mModelList.add(getModelEntry("Light", Sensor.TYPE_LIGHT));
		mModelList.add(getModelEntry("Linear acceleration", Sensor.TYPE_LINEAR_ACCELERATION));
		mModelList.add(getModelEntry("Magnetic field", Sensor.TYPE_MAGNETIC_FIELD));
		mModelList.add(getModelEntry("Pressure", Sensor.TYPE_PRESSURE));
		mModelList.add(getModelEntry("Proximity", Sensor.TYPE_PROXIMITY));
		mModelList.add(getModelEntry("Orientation", Sensor.TYPE_ORIENTATION));
		mModelList.add(getModelEntry("Rotation vector", Sensor.TYPE_ROTATION_VECTOR));
		//mModelList.add(get("Ambient temperature", Sensor.TYPE_AMBIENT_TEMPERATURE ));

		restorePreferences();

		return mModelList;
	}

	private Model getModelEntry(String s, int type) {
		Model model = new Model(s, type);

		SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

		Sensor sensor = sensorManager.getDefaultSensor(type);

		if (sensor != null)
			model.setAvailability(true);
		else
			model.setAvailability(false);

		return model;
	}

In order to have back the same selected sensors when the application get swapped for any reason, we need to store any settings we want using SharedPreferences.

	private void restorePreferences() {
		Log.i(TAG, "Restoring preferences from: " + PREFS_NAME);

		// Restore preferences
		SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);

		int counter = 0;
		for (Model model : mModelList) {
			if (model.isAvailable()) {
				model.setSelected(settings.getBoolean(Integer.toString(counter), false));
				//mModelList.get(counter).setSelected(model.isSelected());
			}
			counter++;
		}
	}

	@Override
	protected void onStop(){
		super.onStop();

		// We need an Editor object to make preference changes.
		// All objects are from android.context.Context
		SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
		SharedPreferences.Editor editor = settings.edit();

		int counter = 0;
		for (Model model : mModelList) {
			editor.putBoolean(Integer.toString(counter), model.isSelected());
			//Log.e(TAG, "Storing: " + Integer.toString(counter) + " " + model.isSelected());
			counter++;
		}

		// Commit the edits!
		editor.commit();
	}

InteractiveArrayAdapter

It is quite annoying, but in order to have a simple “check box and text” list we need to create it.

public class InteractiveArrayAdapter extends ArrayAdapter<Model> {

	//private static final String TAG = "InteractiveArrayAdapter";
	private final List<Model> list;
	private final Activity context;

	public InteractiveArrayAdapter(Activity context, List<Model> list) {
		super(context, R.layout.rowcheckboxnamelayout, list);
		this.context = context;
		this.list = list;
	}

	static class ViewHolder {
		protected TextView text;
		protected CheckBox checkbox;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		View view = null;
		if (convertView == null) {
			LayoutInflater inflator = context.getLayoutInflater();
			view = inflator.inflate(R.layout.rowcheckboxnamelayout, null);
			final ViewHolder viewHolder = new ViewHolder();
			viewHolder.text = (TextView) view.findViewById(R.id.label);
			viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
			
			viewHolder.checkbox
			.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

				@Override
				public void onCheckedChanged(CompoundButton buttonView,
						boolean isChecked) {
					Model element = (Model) viewHolder.checkbox.getTag();

					element.setSelected(buttonView.isChecked());

				}
			});
			
			view.setTag(viewHolder);
			viewHolder.checkbox.setTag(list.get(position));
			
			
			Model element = (Model) viewHolder.checkbox.getTag();
			if (!element.isAvailable()) {
				viewHolder.text.setEnabled(false);
				viewHolder.checkbox.setEnabled(false);
				viewHolder.checkbox.setClickable(false);
			}
			
			
		} else {
			view = convertView;
			((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
		}
		ViewHolder holder = (ViewHolder) view.getTag();
		holder.text.setText(list.get(position).getName());
		holder.checkbox.setChecked(list.get(position).isSelected());
		
		return view;
	}
} 

SensorMonitor activity

public class SensorMonitorActivity extends Activity implements SensorEventListener

For every sensor type we have the same structure.

	/// Accelerometer data
	private Sensor mAccelerometerSensor = null;
	private SimpleXYSeries xAccelerometerHistorySeries = null;
	private SimpleXYSeries yAccelerometerHistorySeries = null;
	private SimpleXYSeries zAccelerometerHistorySeries = null;
	private LinkedList<Number> xAccelerometerHistory;
	private LinkedList<Number> yAccelerometerHistory;
	private LinkedList<Number> zAccelerometerHistory;
	private XYPlot accelerometerHistoryPlot;
	{
		xAccelerometerHistory = new LinkedList<Number>();
		yAccelerometerHistory = new LinkedList<Number>();
		zAccelerometerHistory = new LinkedList<Number>();

		xAccelerometerHistorySeries = new SimpleXYSeries("x");
		yAccelerometerHistorySeries = new SimpleXYSeries("y");
		zAccelerometerHistorySeries = new SimpleXYSeries("z");
	}
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		/// request full screen
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
				WindowManager.LayoutParams.FLAG_FULLSCREEN);

		setContentView(R.layout.activity_sensor_monitor);

		Bundle bundle = getIntent().getExtras();

		mNamesStringList = bundle.getStringArrayList("names");
		mTypesIntList = bundle.getIntegerArrayList("types");

		//====================================================================
		//====================================================================

		mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

		createGraphs();

	}

To create the graphs we simply iterate over the selected sensors, and based on the type we set up the parameters.

		LinearLayout ll = (LinearLayout) findViewById(R.id.scrollView1ll);
		for (int sensor : mTypesIntList) {
			switch (sensor) {
			case Sensor.TYPE_ACCELEROMETER:
				accelerometerHistoryPlot = new XYPlot(this, mNamesStringList.get(mTypesIntList.indexOf(sensor)));

				accelerometerHistoryPlot.setPadding(10, 10, 10, 10);
				accelerometerHistoryPlot.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
				accelerometerHistoryPlot.setMinimumHeight(120);

				accelerometerHistoryPlot.setRangeBoundaries(-180, 359, BoundaryMode.FIXED);
				accelerometerHistoryPlot.setRangeBoundaries(-20, 20, BoundaryMode.FIXED);
				accelerometerHistoryPlot.setDomainBoundaries(0, 30, BoundaryMode.FIXED);

				accelerometerHistoryPlot.addSeries(xAccelerometerHistorySeries, new LineAndPointFormatter(Color.rgb(100, 100, 200), null, null));
				accelerometerHistoryPlot.addSeries(yAccelerometerHistorySeries, new LineAndPointFormatter(Color.rgb(100, 200, 100), null, null));
				accelerometerHistoryPlot.addSeries(zAccelerometerHistorySeries, new LineAndPointFormatter(Color.rgb(200, 100, 100), null, null));

				accelerometerHistoryPlot.setDomainStepValue(5);
				accelerometerHistoryPlot.setTicksPerRangeLabel(3);
				accelerometerHistoryPlot.getDomainLabelWidget().pack();
				accelerometerHistoryPlot.getRangeLabelWidget().pack();
				accelerometerHistoryPlot.disableAllMarkup();	

				ll.addView(accelerometerHistoryPlot);

				break;

This piece of code is important. The application must unregister itself from the sensor manager when it is not the main window. This is very important to spare the battery life.

	@Override
	protected void onResume() {
		super.onResume();

		registerSensors();
	}

	@Override
	protected void onPause() {
		super.onPause();
		mSensorManager.unregisterListener(this);
	}

On resume we simply re register the desired sensors.

	private void registerSensors() {
		for (int sensor : mTypesIntList) {
			switch (sensor) {
			case Sensor.TYPE_ACCELEROMETER:
				mAccelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
				mSensorManager.registerListener(this, mAccelerometerSensor, SensorManager.SENSOR_DELAY_NORMAL);	
				break;
                [...]

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.