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