/* * Copyright (C) 2008 The Android Open Source Project * * 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 android.view; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.util.Log; /** * Helper class for receiving notifications from the SensorManager when * the orientation of the device has changed. */ public abstract class OrientationEventListener { private static final String TAG = "OrientationEventListener"; private static final boolean DEBUG = false; private static final boolean localLOGV = false; private int mOrientation = ORIENTATION_UNKNOWN; private SensorManager mSensorManager; private boolean mEnabled = false; private int mRate; private Sensor mSensor; private SensorEventListener mSensorEventListener; private OrientationListener mOldListener; /** * Returned from onOrientationChanged when the device orientation cannot be determined * (typically when the device is in a close to flat position). * * @see #onOrientationChanged */ public static final int ORIENTATION_UNKNOWN = -1; /** * Creates a new OrientationEventListener. * * @param context for the OrientationEventListener. */ public OrientationEventListener(Context context) { this(context, SensorManager.SENSOR_DELAY_NORMAL); } /** * Creates a new OrientationEventListener. * * @param context for the OrientationEventListener. * @param rate at which sensor events are processed (see also * {@link android.hardware.SensorManager SensorManager}). Use the default * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL * SENSOR_DELAY_NORMAL} for simple screen orientation change detection. */ public OrientationEventListener(Context context, int rate) { mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); mRate = rate; mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); if (mSensor != null) { // Create listener only if sensors do exist mSensorEventListener = new SensorEventListenerImpl(); } } void registerListener(OrientationListener lis) { mOldListener = lis; } /** * Enables the OrientationEventListener so it will monitor the sensor and call * {@link #onOrientationChanged} when the device orientation changes. */ public void enable() { if (mSensor == null) { Log.w(TAG, "Cannot detect sensors. Not enabled"); return; } if (mEnabled == false) { if (localLOGV) Log.d(TAG, "OrientationEventListener enabled"); mSensorManager.registerListener(mSensorEventListener, mSensor, mRate); mEnabled = true; } } /** * Disables the OrientationEventListener. */ public void disable() { if (mSensor == null) { Log.w(TAG, "Cannot detect sensors. Invalid disable"); return; } if (mEnabled == true) { if (localLOGV) Log.d(TAG, "OrientationEventListener disabled"); mSensorManager.unregisterListener(mSensorEventListener); mEnabled = false; } } class SensorEventListenerImpl implements SensorEventListener { private static final int _DATA_X = 0; private static final int _DATA_Y = 1; private static final int _DATA_Z = 2; public void onSensorChanged(SensorEvent event) { float[] values = event.values; int orientation = ORIENTATION_UNKNOWN; float X = -values[_DATA_X]; float Y = -values[_DATA_Y]; float Z = -values[_DATA_Z]; float magnitude = X*X + Y*Y; // Don't trust the angle if the magnitude is small compared to the y value if (magnitude * 4 >= Z*Z) { float OneEightyOverPi = 57.29577957855f; float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi; orientation = 90 - (int)Math.round(angle); // normalize to 0 - 359 range while (orientation >= 360) { orientation -= 360; } while (orientation < 0) { orientation += 360; } } if (mOldListener != null) { mOldListener.onSensorChanged(Sensor.TYPE_ACCELEROMETER, event.values); } if (orientation != mOrientation) { mOrientation = orientation; onOrientationChanged(orientation); } } public void onAccuracyChanged(Sensor sensor, int accuracy) { } } /* * Returns true if sensor is enabled and false otherwise */ public boolean canDetectOrientation() { return mSensor != null; } /** * Called when the orientation of the device has changed. * orientation parameter is in degrees, ranging from 0 to 359. * orientation is 0 degrees when the device is oriented in its natural position, * 90 degrees when its left side is at the top, 180 degrees when it is upside down, * and 270 degrees when its right side is to the top. * {@link #ORIENTATION_UNKNOWN} is returned when the device is close to flat * and the orientation cannot be determined. * * @param orientation The new orientation of the device. * * @see #ORIENTATION_UNKNOWN */ abstract public void onOrientationChanged(int orientation); }