在android设置(Settings)中我们可以看到显示(display)下有一个自动屏幕旋转的checkbox,
如果我们勾选checkbox的话当你手机屏幕就会根据重量自动旋转,那么我们就分析一下这个过程:
在Display_settings.xml文件中我们可以找到:
<CheckBoxPreference
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];等就是三个方向的重力加速度,我们可以将之改为负值就是我们眼睛常看到的