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.Config;
     25 import android.util.Log;
     26 
     27 /**
     28  * Helper class for receiving notifications from the SensorManager when
     29  * the orientation of the device has changed.
     30  */
     31 public 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 }
    175