The initial screen is a simple ListFragment that populates an adapter with a list of sensors on the device:
SensorListFragment.java
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mAdapter = new SensorListAdapter( getActivity() );
setListAdapter(mAdapter);
mSensorManager = (SensorManager) getActivity()
.getSystemService( Context.SENSOR_SERVICE );
for( Sensor sensor : mSensorManager.getSensorList( Sensor.TYPE_ALL ) )
mAdapter.add( sensor );
}
This adapter displays a simple_list_item_1 list row that is populated with the name of each sensor, so that the result looks like this on a Nexus 4:
SensorListFragment.java
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Sensor sensor = (Sensor) getListAdapter().getItem( position );
SensorDetailFragment mFragment = SensorDetailFragment.newInstance( sensor );
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, mFragment)
.addToBackStack(null)
.commit();
}
The sensor is passed to the SensorDetailFragment and the type is stored as an argument that can be retrieved when the fragment is attached and created.
SensorDetailFragment.java
public static SensorDetailFragment newInstance( Sensor sensor ) {
SensorDetailFragment mFragment = new SensorDetailFragment();
Bundle args = new Bundle();
args.putInt( EXTRA_SENSOR_TYPE , sensor.getType() );
mFragment.setArguments(args);
return mFragment;
}
When the fragment is attached and onCreate() is called, the SensorManager system service is retrieved and stored, then the sensor is retrieved from the manager by its type.
SensorDetailFragment.java
mSensorManager = (SensorManager) getActivity().getSystemService( Context.SENSOR_SERVICE );
mSensor = mSensorManager.getDefaultSensor( type );
After the TextViews, which label and display information, are initialized, the static information from the sensor is displayed using the sensor's various functions found here. The dynamic information, such as the readings from the sensor, are retrieved using the SensorEventListener. This interface consists of two methods that respond to events: onAccuracyChanged( Sensor sensor, int accuracy ) and onSensorChanged( SensorEvent event ).
onSensorChanged passes a SensorEvent item that consists of various attributes such as
- accuracy
- timestamp - useful for throwing out data that occurs more rapidly than needed by the application, but not already associated with a sampling speed
- sensor - the sensor that triggered the event
- values - an array of the actual readings from the sensor. This can have indices 0 - 3 populated, depending on the type of sensor giving the reading. Some, such as the gravity sensor, give readings for values[0] - values[2] for the X, Y and Z axis of the device, while others, such as the barometer, only give readings in values[0].
As with any listener interface, it is important to remember to register and unregister your listeners in a practical place, so as to not waste the device battery while the sensors are not being checked and their data used. In this sensor program, the listener is registered in onStart
SensorDetailFragment.java
mSensorManager.registerListener( SensorDetailFragment.this, mSensor, SensorManager.SENSOR_DELAY_UI );
and unregistered when the fragment is hidden.
SensorDetailFragment.java
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if( hidden )
mSensorManager.unregisterListener( this );
}
While there is a lot more to sensor-use in the Android platform, especially in how the data can be interpreted and used to take your apps to the next level, I hope I have given a decent introduction to retrieving data from a list of sensors, and that the source code on GitHub can help someone out there looking to implement sensors in their own projects.