在android设置(Settings)中我们可以看到显示(display)下有一个自动屏幕旋转的checkbox,


如果我们勾选checkbox的话当你手机屏幕就会根据重量自动旋转,那么我们就分析一下这个过程:



在Display_settings.xml文件中我们可以找到:

            android:key="accelerometer"
            android:title="@string/accelerometer_title"/>这是选项框的布局,然后我们到package/app/settings/src/com/android/Settings中的DiaplaySettings.java中去找,


在onCreate方法中,我们发现没有,也没有亮度调节(这个就是博客中自动调节屏幕亮度所讲),不要急,我没继续找,发现在onPreferenceTreeClick方法中有它的影子,


public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
        if (preference == mAccelerometer) {
            Settings.System.putInt(getContentResolver(),
                    Settings.System.ACCELEROMETER_ROTATION,
                    mAccelerometer.isChecked() ? 1 : 0);
        }
        return true;
    }

将选中后值设为1,而在updateState方法中:

  mAccelerometer.setChecked(Settings.System.getInt(
                getContentResolver(),
                Settings.System.ACCELEROMETER_ROTATION, 0) != 0);

意思就是当我们勾选了之后就将1存到(adb shell 进入)/data/data/com.android.providers.settings/databases/settings.db数据库下的system表中:accelerometer_rotation|1

自动旋转和自动调节屏幕亮度一样是用一个observe来监测数据库中的数据是否发生变化,它在PhoneWindownManager.java中会有

  ContentResolver resolver = mContext.getContentResolver();

.......

 resolver.registerContentObserver(Settings.System.getUriFor(
                    Settings.System.ACCELEROMETER_ROTATION), false, this);

........

然后就会在PhoneWindownManager.java中的updateSettings()方法中更新:

nt accelerometerDefault = Settings.System.getInt(resolver,
                    Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION);
            if (mAccelerometerDefault != accelerometerDefault) {
                mAccelerometerDefault = accelerometerDefault;
                updateOrientationListenerLp();
            }

如果accelerometerDefault不等于mAccelerometerDefault也就是不等于0,也就是等于1时,就updateOrientationListenerLp()


在 updateOrientationListenerLp()方法中会调用mOrientationListener.enable(),找到enable方法,实在WindowOrientationListener.java中,它在不断的监听,如果有enable()那么就去执行enable方法:

public void enable() {
        if (mSensor == null) {
            Log.w(TAG, "Cannot detect sensors. Not enabled");
            return;
        }
        if (mEnabled == false) {
            if (localLOGV) Log.d(TAG, "WindowOrientationListener enabled");
            mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);
            mEnabled = true;
        }
    }

也就为重力传感器的对象增加一个监听:  mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);


那么这个Listener到底做什么的呢?

来看一下:这个Listener是WindowOrientationListener.java中SensorEventListenerImpl类的一个对象主要看这个类具体实现了什么功能,


这个类就是实现屏幕根据重力感应器并计算一些数据来实现屏幕的旋转,像计算Rotation的方法calculateNewRotation等,这个可以自己去深入了解,


特别要讲的是: onSensorChanged(SensorEvent event) 方法,

public void onSensorChanged(SensorEvent event) {
            // the vector given in the SensorEvent points straight up (towards the sky) under ideal
            // conditions (the phone is not accelerating).  i'll call this upVector elsewhere.
            //xiugai by xxnan 2012-9-13
            float x = -event.values[_DATA_X];
            float y = -event.values[_DATA_Y];
            float z = -event.values[_DATA_Z];
           //xiugai by xxnan 2012-9-13
            float magnitude = vectorMagnitude(x, y, z);
            float deviation = Math.abs(magnitude - SensorManager.STANDARD_GRAVITY);

            handleAccelerationDistrust(deviation);
            if (magnitude < MIN_ABS_ACCELERATION) {
                return; // Ignore tilt and orientation when (0, 0, 0) or low reading
            }

            // only filter tilt when we're accelerating
            float alpha = 1;
            if (mAccelerationDistrust > 0) {
                alpha = ACCELERATING_LOWPASS_ALPHA;
            }
            float newTiltAngle = tiltAngle(z, magnitude);
            mTiltAngle = lowpassFilter(newTiltAngle, mTiltAngle, alpha);

            float absoluteTilt = Math.abs(mTiltAngle);
            checkFullyTilted(absoluteTilt);
            if (mTiltDistrust > 0) {
                return; // when fully tilted, ignore orientation entirely
            }

            float newOrientationAngle = computeNewOrientation(x, y);
            filterOrientation(absoluteTilt, newOrientationAngle);
            calculateNewRotation(mOrientationAngle, absoluteTilt);
        }

这里面的event.values[_DATA_X],event.values[_DATA_Y],event.values[_DATA_Z];等就是三个方向的重力加速度,我们可以将之改为负值就是我们眼睛常看到的


屏幕倒置(也就是我博客android修改重力感应方向http://blog.csdn.net/xiaxiangnanxp1989/article/details/8013520),当然你也可以尝试去修改一些其它的东西。


好了,这就是我所了解的屏幕自动旋转的大概流程,讲的不好请大牛指出!

更多相关文章

  1. Android代码混淆配置(Proguard文件解析)
  2. Android源码获取方法
  3. Handler
  4. RN集成自签名https及双向认证-android(2)
  5. AsyncTask异步执行
  6. Android7.0 系统启动流程---system_server
  7. Android应用程序防止被LMK干掉
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. android 内核添加tourch screen
  2. android listview check 事件
  3. 横向 纵向结合的ScrollView
  4. android 遍历安装过的包名
  5. Android(安卓)一些常用的但是记不住的设
  6. Android中的MD5加密
  7. android 实现无限定时循环viewpager
  8. Android(安卓)– Video/Music 视频音乐播
  9. android 倒影
  10. Android(安卓)自定义文本框(带图片)