1 /* 2 * Copyright (C) 2008 The Android Open Source Project 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 android.view; 18 19 import android.content.Context; 20 import android.hardware.Sensor; 21 import android.hardware.SensorEvent; 22 import android.hardware.SensorEventListener; 23 import android.hardware.SensorManager; 24 import android.util.Log; 25 26 /** 27 * Helper class for receiving notifications from the SensorManager when 28 * the orientation of the device has changed. 29 */ 30 public abstract class OrientationEventListener { 31 private static final String TAG = "OrientationEventListener"; 32 private static final boolean DEBUG = false; 33 private static final boolean localLOGV = false; 34 private int mOrientation = ORIENTATION_UNKNOWN; 35 private SensorManager mSensorManager; 36 private boolean mEnabled = false; 37 private int mRate; 38 private Sensor mSensor; 39 private SensorEventListener mSensorEventListener; 40 private OrientationListener mOldListener; 41 42 /** 43 * Returned from onOrientationChanged when the device orientation cannot be determined 44 * (typically when the device is in a close to flat position). 45 * 46 * @see #onOrientationChanged 47 */ 48 public static final int ORIENTATION_UNKNOWN = -1; 49 50 /** 51 * Creates a new OrientationEventListener. 52 * 53 * @param context for the OrientationEventListener. 54 */ OrientationEventListener(Context context)55 public OrientationEventListener(Context context) { 56 this(context, SensorManager.SENSOR_DELAY_NORMAL); 57 } 58 59 /** 60 * Creates a new OrientationEventListener. 61 * 62 * @param context for the OrientationEventListener. 63 * @param rate at which sensor events are processed (see also 64 * {@link android.hardware.SensorManager SensorManager}). Use the default 65 * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL 66 * SENSOR_DELAY_NORMAL} for simple screen orientation change detection. 67 */ OrientationEventListener(Context context, int rate)68 public OrientationEventListener(Context context, int rate) { 69 mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); 70 mRate = rate; 71 mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 72 if (mSensor != null) { 73 // Create listener only if sensors do exist 74 mSensorEventListener = new SensorEventListenerImpl(); 75 } 76 } 77 registerListener(OrientationListener lis)78 void registerListener(OrientationListener lis) { 79 mOldListener = lis; 80 } 81 82 /** 83 * Enables the OrientationEventListener so it will monitor the sensor and call 84 * {@link #onOrientationChanged} when the device orientation changes. 85 */ enable()86 public void enable() { 87 if (mSensor == null) { 88 Log.w(TAG, "Cannot detect sensors. Not enabled"); 89 return; 90 } 91 if (mEnabled == false) { 92 if (localLOGV) Log.d(TAG, "OrientationEventListener enabled"); 93 mSensorManager.registerListener(mSensorEventListener, mSensor, mRate); 94 mEnabled = true; 95 } 96 } 97 98 /** 99 * Disables the OrientationEventListener. 100 */ disable()101 public void disable() { 102 if (mSensor == null) { 103 Log.w(TAG, "Cannot detect sensors. Invalid disable"); 104 return; 105 } 106 if (mEnabled == true) { 107 if (localLOGV) Log.d(TAG, "OrientationEventListener disabled"); 108 mSensorManager.unregisterListener(mSensorEventListener); 109 mEnabled = false; 110 } 111 } 112 113 class SensorEventListenerImpl implements SensorEventListener { 114 private static final int _DATA_X = 0; 115 private static final int _DATA_Y = 1; 116 private static final int _DATA_Z = 2; 117 onSensorChanged(SensorEvent event)118 public void onSensorChanged(SensorEvent event) { 119 float[] values = event.values; 120 int orientation = ORIENTATION_UNKNOWN; 121 float X = -values[_DATA_X]; 122 float Y = -values[_DATA_Y]; 123 float Z = -values[_DATA_Z]; 124 float magnitude = X*X + Y*Y; 125 // Don't trust the angle if the magnitude is small compared to the y value 126 if (magnitude * 4 >= Z*Z) { 127 float OneEightyOverPi = 57.29577957855f; 128 float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi; 129 orientation = 90 - (int)Math.round(angle); 130 // normalize to 0 - 359 range 131 while (orientation >= 360) { 132 orientation -= 360; 133 } 134 while (orientation < 0) { 135 orientation += 360; 136 } 137 } 138 if (mOldListener != null) { 139 mOldListener.onSensorChanged(Sensor.TYPE_ACCELEROMETER, event.values); 140 } 141 if (orientation != mOrientation) { 142 mOrientation = orientation; 143 onOrientationChanged(orientation); 144 } 145 } 146 onAccuracyChanged(Sensor sensor, int accuracy)147 public void onAccuracyChanged(Sensor sensor, int accuracy) { 148 149 } 150 } 151 152 /* 153 * Returns true if sensor is enabled and false otherwise 154 */ canDetectOrientation()155 public boolean canDetectOrientation() { 156 return mSensor != null; 157 } 158 159 /** 160 * Called when the orientation of the device has changed. 161 * orientation parameter is in degrees, ranging from 0 to 359. 162 * orientation is 0 degrees when the device is oriented in its natural position, 163 * 90 degrees when its left side is at the top, 180 degrees when it is upside down, 164 * and 270 degrees when its right side is to the top. 165 * {@link #ORIENTATION_UNKNOWN} is returned when the device is close to flat 166 * and the orientation cannot be determined. 167 * 168 * @param orientation The new orientation of the device. 169 * 170 * @see #ORIENTATION_UNKNOWN 171 */ onOrientationChanged(int orientation)172 abstract public void onOrientationChanged(int orientation); 173 } 174