/* | |
* Copyright 2012 AndroidPlot.com | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package com.androidplot.demos; | |
import android.app.Activity; | |
import android.content.Context; | |
import android.graphics.Color; | |
import android.hardware.Sensor; | |
import android.hardware.SensorEvent; | |
import android.hardware.SensorEventListener; | |
import android.hardware.SensorManager; | |
import android.os.Bundle; | |
import android.view.View; | |
import android.widget.CheckBox; | |
import android.widget.CompoundButton; | |
import com.androidplot.Plot; | |
import com.androidplot.util.PlotStatistics; | |
import com.androidplot.util.Redrawer; | |
import com.androidplot.xy.*; | |
import java.text.DecimalFormat; | |
import java.util.Arrays; | |
// Monitor the phone's orientation sensor and plot the resulting azimuth pitch and roll values. | |
// See: http://developer.android.com/reference/android/hardware/SensorEvent.html | |
public class OrientationSensorExampleActivity extends Activity implements SensorEventListener | |
{ | |
private static final int HISTORY_SIZE = 300; // number of points to plot in history | |
private SensorManager sensorMgr = null; | |
private Sensor orSensor = null; | |
private XYPlot aprLevelsPlot = null; | |
private XYPlot aprHistoryPlot = null; | |
private CheckBox hwAcceleratedCb; | |
private CheckBox showFpsCb; | |
//private SimpleXYSeries aprLevelsSeries = null; | |
private SimpleXYSeries aLvlSeries; | |
private SimpleXYSeries pLvlSeries; | |
private SimpleXYSeries rLvlSeries; | |
private SimpleXYSeries azimuthHistorySeries = null; | |
private SimpleXYSeries pitchHistorySeries = null; | |
private SimpleXYSeries rollHistorySeries = null; | |
private Redrawer redrawer; | |
/** Called when the activity is first created. */ | |
@Override | |
public void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.orientation_sensor_example); | |
// setup the APR Levels plot: | |
aprLevelsPlot = (XYPlot) findViewById(R.id.aprLevelsPlot); | |
aprLevelsPlot.setDomainBoundaries(-1, 1, BoundaryMode.FIXED); | |
aprLevelsPlot.getGraphWidget().getDomainLabelPaint().setColor(Color.TRANSPARENT); | |
aLvlSeries = new SimpleXYSeries("A"); | |
pLvlSeries = new SimpleXYSeries("P"); | |
rLvlSeries = new SimpleXYSeries("R"); | |
aprLevelsPlot.addSeries(aLvlSeries, | |
new BarFormatter(Color.rgb(0, 200, 0), Color.rgb(0, 80, 0))); | |
aprLevelsPlot.addSeries(pLvlSeries, | |
new BarFormatter(Color.rgb(200, 0, 0), Color.rgb(0, 80, 0))); | |
aprLevelsPlot.addSeries(rLvlSeries, | |
new BarFormatter(Color.rgb(0, 0, 200), Color.rgb(0, 80, 0))); | |
aprLevelsPlot.setDomainStepValue(3); | |
aprLevelsPlot.setTicksPerRangeLabel(3); | |
// per the android documentation, the minimum and maximum readings we can get from | |
// any of the orientation sensors is -180 and 359 respectively so we will fix our plot's | |
// boundaries to those values. If we did not do this, the plot would auto-range which | |
// can be visually confusing in the case of dynamic plots. | |
aprLevelsPlot.setRangeBoundaries(-180, 359, BoundaryMode.FIXED); | |
// update our domain and range axis labels: | |
aprLevelsPlot.setDomainLabel(""); | |
aprLevelsPlot.getDomainLabelWidget().pack(); | |
aprLevelsPlot.setRangeLabel("Angle (Degs)"); | |
aprLevelsPlot.getRangeLabelWidget().pack(); | |
aprLevelsPlot.setGridPadding(15, 0, 15, 0); | |
aprLevelsPlot.setRangeValueFormat(new DecimalFormat("#")); | |
// setup the APR History plot: | |
aprHistoryPlot = (XYPlot) findViewById(R.id.aprHistoryPlot); | |
azimuthHistorySeries = new SimpleXYSeries("Az."); | |
azimuthHistorySeries.useImplicitXVals(); | |
pitchHistorySeries = new SimpleXYSeries("Pitch"); | |
pitchHistorySeries.useImplicitXVals(); | |
rollHistorySeries = new SimpleXYSeries("Roll"); | |
rollHistorySeries.useImplicitXVals(); | |
aprHistoryPlot.setRangeBoundaries(-180, 359, BoundaryMode.FIXED); | |
aprHistoryPlot.setDomainBoundaries(0, HISTORY_SIZE, BoundaryMode.FIXED); | |
aprHistoryPlot.addSeries(azimuthHistorySeries, | |
new LineAndPointFormatter( | |
Color.rgb(100, 100, 200), null, null, null)); | |
aprHistoryPlot.addSeries(pitchHistorySeries, | |
new LineAndPointFormatter( | |
Color.rgb(100, 200, 100), null, null, null)); | |
aprHistoryPlot.addSeries(rollHistorySeries, | |
new LineAndPointFormatter( | |
Color.rgb(200, 100, 100), null, null, null)); | |
aprHistoryPlot.setDomainStepMode(XYStepMode.INCREMENT_BY_VAL); | |
aprHistoryPlot.setDomainStepValue(HISTORY_SIZE/10); | |
aprHistoryPlot.setTicksPerRangeLabel(3); | |
aprHistoryPlot.setDomainLabel("Sample Index"); | |
aprHistoryPlot.getDomainLabelWidget().pack(); | |
aprHistoryPlot.setRangeLabel("Angle (Degs)"); | |
aprHistoryPlot.getRangeLabelWidget().pack(); | |
aprHistoryPlot.setRangeValueFormat(new DecimalFormat("#")); | |
aprHistoryPlot.setDomainValueFormat(new DecimalFormat("#")); | |
// setup checkboxes: | |
hwAcceleratedCb = (CheckBox) findViewById(R.id.hwAccelerationCb); | |
final PlotStatistics levelStats = new PlotStatistics(1000, false); | |
final PlotStatistics histStats = new PlotStatistics(1000, false); | |
aprLevelsPlot.addListener(levelStats); | |
aprHistoryPlot.addListener(histStats); | |
hwAcceleratedCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { | |
@Override | |
public void onCheckedChanged(CompoundButton compoundButton, boolean b) { | |
if(b) { | |
aprLevelsPlot.setLayerType(View.LAYER_TYPE_NONE, null); | |
aprHistoryPlot.setLayerType(View.LAYER_TYPE_NONE, null); | |
} else { | |
aprLevelsPlot.setLayerType(View.LAYER_TYPE_SOFTWARE, null); | |
aprHistoryPlot.setLayerType(View.LAYER_TYPE_SOFTWARE, null); | |
} | |
} | |
}); | |
showFpsCb = (CheckBox) findViewById(R.id.showFpsCb); | |
showFpsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { | |
@Override | |
public void onCheckedChanged(CompoundButton compoundButton, boolean b) { | |
levelStats.setAnnotatePlotEnabled(b); | |
histStats.setAnnotatePlotEnabled(b); | |
} | |
}); | |
// get a ref to the BarRenderer so we can make some changes to it: | |
BarRenderer barRenderer = (BarRenderer) aprLevelsPlot.getRenderer(BarRenderer.class); | |
if(barRenderer != null) { | |
// make our bars a little thicker than the default so they can be seen better: | |
barRenderer.setBarWidth(25); | |
} | |
// register for orientation sensor events: | |
sensorMgr = (SensorManager) getApplicationContext().getSystemService(Context.SENSOR_SERVICE); | |
for (Sensor sensor : sensorMgr.getSensorList(Sensor.TYPE_ORIENTATION)) { | |
if (sensor.getType() == Sensor.TYPE_ORIENTATION) { | |
orSensor = sensor; | |
} | |
} | |
// if we can't access the orientation sensor then exit: | |
if (orSensor == null) { | |
System.out.println("Failed to attach to orSensor."); | |
cleanup(); | |
} | |
sensorMgr.registerListener(this, orSensor, SensorManager.SENSOR_DELAY_UI); | |
redrawer = new Redrawer( | |
Arrays.asList(new Plot[]{aprHistoryPlot, aprLevelsPlot}), | |
100, false); | |
} | |
@Override | |
public void onResume() { | |
super.onResume(); | |
redrawer.start(); | |
} | |
@Override | |
public void onPause() { | |
redrawer.pause(); | |
super.onPause(); | |
} | |
@Override | |
public void onDestroy() { | |
redrawer.finish(); | |
super.onDestroy(); | |
} | |
private void cleanup() { | |
// aunregister with the orientation sensor before exiting: | |
sensorMgr.unregisterListener(this); | |
finish(); | |
} | |
// Called whenever a new orSensor reading is taken. | |
@Override | |
public synchronized void onSensorChanged(SensorEvent sensorEvent) { | |
// update level data: | |
aLvlSeries.setModel(Arrays.asList( | |
new Number[]{sensorEvent.values[0]}), | |
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY); | |
pLvlSeries.setModel(Arrays.asList( | |
new Number[]{sensorEvent.values[1]}), | |
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY); | |
rLvlSeries.setModel(Arrays.asList( | |
new Number[]{sensorEvent.values[2]}), | |
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY); | |
// get rid the oldest sample in history: | |
if (rollHistorySeries.size() > HISTORY_SIZE) { | |
rollHistorySeries.removeFirst(); | |
pitchHistorySeries.removeFirst(); | |
azimuthHistorySeries.removeFirst(); | |
} | |
// add the latest history sample: | |
azimuthHistorySeries.addLast(null, sensorEvent.values[0]); | |
pitchHistorySeries.addLast(null, sensorEvent.values[1]); | |
rollHistorySeries.addLast(null, sensorEvent.values[2]); | |
} | |
@Override | |
public void onAccuracyChanged(Sensor sensor, int i) { | |
// Not interested in this event | |
} | |
} |