Home | History | Annotate | Download | only in view
      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      */
     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      */
     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 
     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      */
     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      */
    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 
    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 
    147         public void onAccuracyChanged(Sensor sensor, int accuracy) {
    148 
    149         }
    150     }
    151 
    152     /*
    153      * Returns true if sensor is enabled and false otherwise
    154      */
    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      */
    172     abstract public void onOrientationChanged(int orientation);
    173 }
    174