Home | History | Annotate | Download | only in demos
      1 /*
      2  * Copyright 2012 AndroidPlot.com
      3  *
      4  *    Licensed under the Apache License, Version 2.0 (the "License");
      5  *    you may not use this file except in compliance with the License.
      6  *    You may obtain a copy of the License at
      7  *
      8  *        http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  *    Unless required by applicable law or agreed to in writing, software
     11  *    distributed under the License is distributed on an "AS IS" BASIS,
     12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  *    See the License for the specific language governing permissions and
     14  *    limitations under the License.
     15  */
     16 
     17 package com.androidplot.demos;
     18 
     19 import android.app.Activity;
     20 import android.content.Context;
     21 import android.graphics.Color;
     22 import android.hardware.Sensor;
     23 import android.hardware.SensorEvent;
     24 import android.hardware.SensorEventListener;
     25 import android.hardware.SensorManager;
     26 import android.os.Bundle;
     27 import android.view.View;
     28 import android.widget.CheckBox;
     29 import android.widget.CompoundButton;
     30 import com.androidplot.Plot;
     31 import com.androidplot.util.PlotStatistics;
     32 import com.androidplot.util.Redrawer;
     33 import com.androidplot.xy.*;
     34 import java.text.DecimalFormat;
     35 import java.util.Arrays;
     36 
     37 // Monitor the phone's orientation sensor and plot the resulting azimuth pitch and roll values.
     38 // See: http://developer.android.com/reference/android/hardware/SensorEvent.html
     39 public class OrientationSensorExampleActivity extends Activity implements SensorEventListener
     40 {
     41 
     42     private static final int HISTORY_SIZE = 300;            // number of points to plot in history
     43     private SensorManager sensorMgr = null;
     44     private Sensor orSensor = null;
     45 
     46     private XYPlot aprLevelsPlot = null;
     47     private XYPlot aprHistoryPlot = null;
     48 
     49     private CheckBox hwAcceleratedCb;
     50     private CheckBox showFpsCb;
     51     //private SimpleXYSeries aprLevelsSeries = null;
     52     private SimpleXYSeries aLvlSeries;
     53     private SimpleXYSeries pLvlSeries;
     54     private SimpleXYSeries rLvlSeries;
     55     private SimpleXYSeries azimuthHistorySeries = null;
     56     private SimpleXYSeries pitchHistorySeries = null;
     57     private SimpleXYSeries rollHistorySeries = null;
     58 
     59     private Redrawer redrawer;
     60 
     61     /** Called when the activity is first created. */
     62     @Override
     63     public void onCreate(Bundle savedInstanceState) {
     64         super.onCreate(savedInstanceState);
     65         setContentView(R.layout.orientation_sensor_example);
     66 
     67         // setup the APR Levels plot:
     68         aprLevelsPlot = (XYPlot) findViewById(R.id.aprLevelsPlot);
     69         aprLevelsPlot.setDomainBoundaries(-1, 1, BoundaryMode.FIXED);
     70         aprLevelsPlot.getGraphWidget().getDomainLabelPaint().setColor(Color.TRANSPARENT);
     71 
     72         aLvlSeries = new SimpleXYSeries("A");
     73         pLvlSeries = new SimpleXYSeries("P");
     74         rLvlSeries = new SimpleXYSeries("R");
     75 
     76         aprLevelsPlot.addSeries(aLvlSeries,
     77                         new BarFormatter(Color.rgb(0, 200, 0), Color.rgb(0, 80, 0)));
     78         aprLevelsPlot.addSeries(pLvlSeries,
     79                         new BarFormatter(Color.rgb(200, 0, 0), Color.rgb(0, 80, 0)));
     80         aprLevelsPlot.addSeries(rLvlSeries,
     81                         new BarFormatter(Color.rgb(0, 0, 200), Color.rgb(0, 80, 0)));
     82 
     83         aprLevelsPlot.setDomainStepValue(3);
     84         aprLevelsPlot.setTicksPerRangeLabel(3);
     85 
     86         // per the android documentation, the minimum and maximum readings we can get from
     87         // any of the orientation sensors is -180 and 359 respectively so we will fix our plot's
     88         // boundaries to those values.  If we did not do this, the plot would auto-range which
     89         // can be visually confusing in the case of dynamic plots.
     90         aprLevelsPlot.setRangeBoundaries(-180, 359, BoundaryMode.FIXED);
     91 
     92         // update our domain and range axis labels:
     93         aprLevelsPlot.setDomainLabel("");
     94         aprLevelsPlot.getDomainLabelWidget().pack();
     95         aprLevelsPlot.setRangeLabel("Angle (Degs)");
     96         aprLevelsPlot.getRangeLabelWidget().pack();
     97         aprLevelsPlot.setGridPadding(15, 0, 15, 0);
     98         aprLevelsPlot.setRangeValueFormat(new DecimalFormat("#"));
     99 
    100         // setup the APR History plot:
    101         aprHistoryPlot = (XYPlot) findViewById(R.id.aprHistoryPlot);
    102 
    103         azimuthHistorySeries = new SimpleXYSeries("Az.");
    104         azimuthHistorySeries.useImplicitXVals();
    105         pitchHistorySeries = new SimpleXYSeries("Pitch");
    106         pitchHistorySeries.useImplicitXVals();
    107         rollHistorySeries = new SimpleXYSeries("Roll");
    108         rollHistorySeries.useImplicitXVals();
    109 
    110         aprHistoryPlot.setRangeBoundaries(-180, 359, BoundaryMode.FIXED);
    111         aprHistoryPlot.setDomainBoundaries(0, HISTORY_SIZE, BoundaryMode.FIXED);
    112         aprHistoryPlot.addSeries(azimuthHistorySeries,
    113                 new LineAndPointFormatter(
    114                         Color.rgb(100, 100, 200), null, null, null));
    115         aprHistoryPlot.addSeries(pitchHistorySeries,
    116                 new LineAndPointFormatter(
    117                         Color.rgb(100, 200, 100), null, null, null));
    118         aprHistoryPlot.addSeries(rollHistorySeries,
    119                 new LineAndPointFormatter(
    120                         Color.rgb(200, 100, 100), null, null, null));
    121         aprHistoryPlot.setDomainStepMode(XYStepMode.INCREMENT_BY_VAL);
    122         aprHistoryPlot.setDomainStepValue(HISTORY_SIZE/10);
    123         aprHistoryPlot.setTicksPerRangeLabel(3);
    124         aprHistoryPlot.setDomainLabel("Sample Index");
    125         aprHistoryPlot.getDomainLabelWidget().pack();
    126         aprHistoryPlot.setRangeLabel("Angle (Degs)");
    127         aprHistoryPlot.getRangeLabelWidget().pack();
    128 
    129         aprHistoryPlot.setRangeValueFormat(new DecimalFormat("#"));
    130         aprHistoryPlot.setDomainValueFormat(new DecimalFormat("#"));
    131 
    132         // setup checkboxes:
    133         hwAcceleratedCb = (CheckBox) findViewById(R.id.hwAccelerationCb);
    134         final PlotStatistics levelStats = new PlotStatistics(1000, false);
    135         final PlotStatistics histStats = new PlotStatistics(1000, false);
    136 
    137         aprLevelsPlot.addListener(levelStats);
    138         aprHistoryPlot.addListener(histStats);
    139         hwAcceleratedCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    140             @Override
    141             public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
    142                 if(b) {
    143                     aprLevelsPlot.setLayerType(View.LAYER_TYPE_NONE, null);
    144                     aprHistoryPlot.setLayerType(View.LAYER_TYPE_NONE, null);
    145                 } else {
    146                     aprLevelsPlot.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    147                     aprHistoryPlot.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    148                 }
    149             }
    150         });
    151 
    152         showFpsCb = (CheckBox) findViewById(R.id.showFpsCb);
    153         showFpsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    154             @Override
    155             public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
    156                 levelStats.setAnnotatePlotEnabled(b);
    157                 histStats.setAnnotatePlotEnabled(b);
    158             }
    159         });
    160 
    161         // get a ref to the BarRenderer so we can make some changes to it:
    162         BarRenderer barRenderer = (BarRenderer) aprLevelsPlot.getRenderer(BarRenderer.class);
    163         if(barRenderer != null) {
    164             // make our bars a little thicker than the default so they can be seen better:
    165             barRenderer.setBarWidth(25);
    166         }
    167 
    168         // register for orientation sensor events:
    169         sensorMgr = (SensorManager) getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
    170         for (Sensor sensor : sensorMgr.getSensorList(Sensor.TYPE_ORIENTATION)) {
    171             if (sensor.getType() == Sensor.TYPE_ORIENTATION) {
    172                 orSensor = sensor;
    173             }
    174         }
    175 
    176         // if we can't access the orientation sensor then exit:
    177         if (orSensor == null) {
    178             System.out.println("Failed to attach to orSensor.");
    179             cleanup();
    180         }
    181 
    182         sensorMgr.registerListener(this, orSensor, SensorManager.SENSOR_DELAY_UI);
    183 
    184         redrawer = new Redrawer(
    185                 Arrays.asList(new Plot[]{aprHistoryPlot, aprLevelsPlot}),
    186                 100, false);
    187     }
    188 
    189     @Override
    190     public void onResume() {
    191         super.onResume();
    192         redrawer.start();
    193     }
    194 
    195     @Override
    196     public void onPause() {
    197         redrawer.pause();
    198         super.onPause();
    199     }
    200 
    201     @Override
    202     public void onDestroy() {
    203         redrawer.finish();
    204         super.onDestroy();
    205     }
    206 
    207     private void cleanup() {
    208         // aunregister with the orientation sensor before exiting:
    209         sensorMgr.unregisterListener(this);
    210         finish();
    211     }
    212 
    213 
    214     // Called whenever a new orSensor reading is taken.
    215     @Override
    216     public synchronized void onSensorChanged(SensorEvent sensorEvent) {
    217 
    218         // update level data:
    219         aLvlSeries.setModel(Arrays.asList(
    220                 new Number[]{sensorEvent.values[0]}),
    221                 SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
    222 
    223         pLvlSeries.setModel(Arrays.asList(
    224                         new Number[]{sensorEvent.values[1]}),
    225                         SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
    226 
    227         rLvlSeries.setModel(Arrays.asList(
    228                         new Number[]{sensorEvent.values[2]}),
    229                         SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
    230 
    231         // get rid the oldest sample in history:
    232         if (rollHistorySeries.size() > HISTORY_SIZE) {
    233             rollHistorySeries.removeFirst();
    234             pitchHistorySeries.removeFirst();
    235             azimuthHistorySeries.removeFirst();
    236         }
    237 
    238         // add the latest history sample:
    239         azimuthHistorySeries.addLast(null, sensorEvent.values[0]);
    240         pitchHistorySeries.addLast(null, sensorEvent.values[1]);
    241         rollHistorySeries.addLast(null, sensorEvent.values[2]);
    242     }
    243 
    244 
    245     @Override
    246     public void onAccuracyChanged(Sensor sensor, int i) {
    247         // Not interested in this event
    248     }
    249 }