1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.android.tests.testsensors; 18 19 import java.util.ArrayList; 20 import java.util.List; 21 22 import android.app.Activity; 23 import android.hardware.Sensor; 24 import android.hardware.SensorEvent; 25 import android.hardware.SensorEventListener; 26 import android.hardware.SensorManager; 27 import android.os.Bundle; 28 import android.view.LayoutInflater; 29 import android.widget.TableLayout; 30 import android.widget.TableRow; 31 import android.widget.TextView; 32 33 public class TestSensorsActivity extends Activity { 34 private static final String TAG = "testSensors"; 35 /** Array containing monitored sensors. */ 36 private List<MonitoredSensor> mSensors; 37 /** Controls displayed list of sensors. */ 38 private TableLayout mTableLayout; 39 40 /** 41 * Encapsulates a sensor. 42 */ 43 private class MonitoredSensor implements SensorEventListener { 44 /** Sensor to monitor. */ 45 private final Sensor mSensor; 46 /** Check box representing the sensor on the screen. */ 47 private final TextView mName; 48 /** Text view displaying the value of the sensor. */ 49 private final TextView mVal; 50 /** Formats string to show in the TextView. */ 51 private String mTextFmt; 52 53 /** 54 * Constructs MonitoredSensor instance, and register the listeners. 55 * 56 * @param sensor Sensor to monitor. 57 */ MonitoredSensor(Sensor sensor)58 MonitoredSensor(Sensor sensor) { 59 mSensor = sensor; 60 61 // Add a row representing this sensor on the display 62 final LayoutInflater inflater = getLayoutInflater(); 63 final TableRow row = (TableRow) inflater.inflate(R.layout.one_row, mTableLayout, false); 64 mTableLayout.addView(row); 65 66 // Initialize displayed checkbox for this sensor, and register 67 // checked state listener for it. 68 mName = (TextView) row.findViewById(R.id.row_textview_name); 69 70 // Initialize displayed text box for this sensor. 71 mVal = (TextView) row.findViewById(R.id.row_textview_value); 72 mVal.setText(""); 73 74 // Set appropriate sensor name depending on the type. Unfortunately, 75 // we can't really use sensor.getName() here, since the value it 76 // returns (although resembles the purpose) is a bit vaguer than it 77 // should be. Also choose an appropriate format for the strings that 78 // display sensor's value, and strings that are sent to the 79 // emulator. 80 switch (sensor.getType()) { 81 case Sensor.TYPE_ACCELEROMETER: 82 mName.setText("Accelerometer"); 83 // 3 floats. 84 mTextFmt = "%+.2f %+.2f %+.2f"; 85 break; 86 case 9: // Sensor.TYPE_GRAVITY is missing in API 7 87 // 3 floats. 88 mName.setText("Gravity"); 89 mTextFmt = "%+.2f %+.2f %+.2f"; 90 break; 91 case Sensor.TYPE_GYROSCOPE: 92 mName.setText("Gyroscope"); 93 // 3 floats. 94 mTextFmt = "%+.2f %+.2f %+.2f"; 95 break; 96 case Sensor.TYPE_LIGHT: 97 mName.setText("Light"); 98 // 1 integer. 99 mTextFmt = "%.0f"; 100 break; 101 case 10: // Sensor.TYPE_LINEAR_ACCELERATION is missing in API 7 102 mName.setText("Linear acceleration"); 103 // 3 floats. 104 mTextFmt = "%+.2f %+.2f %+.2f"; 105 break; 106 case Sensor.TYPE_MAGNETIC_FIELD: 107 mName.setText("Magnetic field"); 108 // 3 floats. 109 mTextFmt = "%+.2f %+.2f %+.2f"; 110 break; 111 case Sensor.TYPE_ORIENTATION: 112 mName.setText("Orientation"); 113 // 3 integers. 114 mTextFmt = "%+03.0f %+03.0f %+03.0f"; 115 break; 116 case Sensor.TYPE_PRESSURE: 117 mName.setText("Pressure"); 118 // 1 integer. 119 mTextFmt = "%.0f"; 120 break; 121 case Sensor.TYPE_PROXIMITY: 122 mName.setText("Proximity"); 123 // 1 integer. 124 mTextFmt = "%.0f"; 125 break; 126 case 11: // Sensor.TYPE_ROTATION_VECTOR is missing in API 7 127 mName.setText("Rotation"); 128 // 3 floats. 129 mTextFmt = "%+.2f %+.2f %+.2f"; 130 break; 131 case Sensor.TYPE_TEMPERATURE: 132 mName.setText("Temperature"); 133 // 1 integer. 134 mTextFmt = "%.0f"; 135 break; 136 default: 137 mName.setText("<Unknown>"); 138 mTextFmt = "N/A"; 139 break; 140 } 141 } 142 143 /** 144 * Gets sensor type. 145 * 146 * @return Sensor type as one of the Sensor.TYPE_XXX constants. 147 */ getType()148 private int getType() { 149 return mSensor.getType(); 150 } 151 152 /** 153 * Starts monitoring the sensor. NOTE: This method is called from 154 * outside of the UI thread. 155 */ startListening()156 private void startListening() { 157 SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); 158 sm.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_UI); 159 } 160 161 /** 162 * Stops monitoring the sensor. NOTE: This method is called from outside 163 * of the UI thread. 164 */ stopListening()165 private void stopListening() { 166 SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); 167 sm.unregisterListener(this); 168 } 169 170 /** 171 * Handles "sensor changed" event. This is an implementation of the 172 * SensorEventListener interface. 173 */ 174 @Override onSensorChanged(SensorEvent event)175 public void onSensorChanged(SensorEvent event) { 176 // Display current sensor value, and format message that will be 177 // sent to the emulator. 178 final int nArgs = event.values.length; 179 String val; 180 if (nArgs == 3) { 181 val = String.format(mTextFmt, event.values[0], event.values[1], event.values[2]); 182 } else if (nArgs == 2) { 183 val = String.format(mTextFmt, event.values[0], event.values[1]); 184 } else if (nArgs == 1) { 185 val = String.format(mTextFmt, event.values[0]); 186 } else { 187 return; 188 } 189 mVal.setText(val); 190 } 191 192 /** 193 * Handles "sensor accuracy changed" event. This is an implementation of 194 * the SensorEventListener interface. 195 */ 196 @Override onAccuracyChanged(Sensor sensor, int accuracy)197 public void onAccuracyChanged(Sensor sensor, int accuracy) { 198 } 199 } // MonitoredSensor 200 201 /** Called when the activity is first created. */ 202 @Override onCreate(Bundle savedInstanceState)203 public void onCreate(Bundle savedInstanceState) { 204 super.onCreate(savedInstanceState); 205 setContentView(R.layout.main); 206 207 mTableLayout = (TableLayout) findViewById(R.id.tableLayout); 208 209 // Iterate through the available sensors, adding them to the array. 210 mSensors = new ArrayList<MonitoredSensor>(); 211 SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); 212 List<Sensor> sensors = sm.getSensorList(Sensor.TYPE_ALL); 213 int cur_index = 0; 214 for (int n = 0; n < sensors.size(); n++) { 215 Sensor avail_sensor = sensors.get(n); 216 217 // There can be multiple sensors of the same type. We need only one. 218 if (!isSensorTypeAlreadyMonitored(avail_sensor.getType())) { 219 // The first sensor we've got for the given type is not 220 // necessarily the right one. So, use the default sensor 221 // for the given type. 222 Sensor def_sens = sm.getDefaultSensor(avail_sensor.getType()); 223 MonitoredSensor to_add = new MonitoredSensor(def_sens); 224 cur_index++; 225 mSensors.add(to_add); 226 to_add.startListening(); 227 } 228 } 229 } 230 231 /** 232 * Checks if a sensor for the given type is already monitored. 233 * 234 * @param type Sensor type (one of the Sensor.TYPE_XXX constants) 235 * @return true if a sensor for the given type is already monitored, or 236 * false if the sensor is not monitored. 237 */ isSensorTypeAlreadyMonitored(int type)238 private boolean isSensorTypeAlreadyMonitored(int type) { 239 for (int n = 0; n < mSensors.size(); n++) { 240 if (mSensors.get(n).getType() == type) { 241 return true; 242 } 243 } 244 return false; 245 } 246 } 247