赞
踩
通过“设置->显示->亮度”可以调节屏幕亮度,当点击“亮度”这个选项时,会弹出如下菜单:
实际上这是一个系统Activity,下面就先来分析一下是如何启动这个Activity的。
“设置->显示”的布局文件是"display_settings.xml":
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
android:title="@string/display_settings"//亮度
settings:keywords="@string/keywords_display">
<PreferenceScreen
android:key="brightness"
android:title="@string/brightness"
settings:keywords="@string/keywords_display_brightness_level">
//通过Intent启动SHOW_BRIGHTNESS_DIALOG
<intent android:action="android.intent.action.SHOW_BRIGHTNESS_DIALOG" />
</PreferenceScreen>
...以下省略
当点击“亮度”的PreferenceScreen时,会通过Intent启动 “android.intent.action.SHOW_BRIGHTNESS_DIALOG”。这个action对应的是什么呢?可以在“frameworks\base\packages\SystemUI\AndroidManifest.xml”中找到答案:
<activity
android:name=".settings.BrightnessDialog"
android:label="@string/quick_settings_brightness_dialog_title"
android:theme="@android:style/Theme.DeviceDefault.Dialog"
android:finishOnCloseSystemDialogs="true"
android:launchMode="singleInstance"
android:excludeFromRecents="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.SHOW_BRIGHTNESS_DIALOG" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
可以看到,这个action会启动SystemUI的"BrightnessDialog"。 那么接下来就分析一下BrightnessDialog这个Activity吧。
这个Activity非常简单,我都在犹豫要不要贴代码。。。
public class BrightnessDialog extends Activity { private BrightnessController mBrightnessController; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Window window = getWindow(); window.setGravity(Gravity.TOP); window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); window.requestFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.quick_settings_brightness_dialog); final ImageView icon = (ImageView) findViewById(R.id.brightness_icon); final ToggleSlider slider = (ToggleSlider) findViewById(R.id.brightness_slider); mBrightnessController = new BrightnessController(this, icon, slider); } @Override protected void onStart() { super.onStart(); mBrightnessController.registerCallbacks(); MetricsLogger.visible(this, MetricsEvent.BRIGHTNESS_DIALOG); } @Override protected void onStop() { super.onStop(); MetricsLogger.hidden(this, MetricsEvent.BRIGHTNESS_DIALOG); mBrightnessController.unregisterCallbacks(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) { finish(); } return super.onKeyDown(keyCode, event); } }
BrightnessDialog的onCreate一共干了两件事,一是加载了布局文件,二是创建了BrightnessController。而onStart就是执行了BrightnessController.registerCallbacks。所以,重点在BrightnessController。接下来就分析一下BrightnessController。
先看一下BrightnessController的构造函数:
public BrightnessController(Context context, ImageView icon, ToggleSlider control) {
mContext = context;
mIcon = icon;
mControl = control;
mBackgroundHandler = new Handler(Looper.getMainLooper());
mUserTracker = new CurrentUserTracker(mContext) {
@Override
public void onUserSwitched(int newUserId) {
mBackgroundHandler.post(mUpdateModeRunnable);
mBackgroundHandler.post(mUpdateSliderRunnable);
}
};
//创建BrightnessObserver
mBrightnessObserver = new BrightnessObserver(mHandler);
...以下省略
其中创建了一个BrightnessObserver对象,BrightnessObserver继承自ContentObserver,当注册的Content发生变化时,它会接收到回调。那么我们看看它注册了什么Content:
public void startObserving() { final ContentResolver cr = mContext.getContentResolver(); cr.unregisterContentObserver(this); cr.registerContentObserver( BRIGHTNESS_MODE_URI,//亮度模式 false, this, UserHandle.USER_ALL); cr.registerContentObserver( BRIGHTNESS_URI,//亮度 false, this, UserHandle.USER_ALL); cr.registerContentObserver( BRIGHTNESS_FOR_VR_URI,//用于VR的亮度 false, this, UserHandle.USER_ALL); cr.registerContentObserver( BRIGHTNESS_ADJ_URI,//自动亮度调节 false, this, UserHandle.USER_ALL); }
BrightnessObserver一共对四个URI进行了关注,就好像拿起了望远镜对他们说:“I am watching U"。
BrightnessObserver.startObserving的调用关系是:BrightnessDialog.start -> BrightnessController.registerCallbacks ->mBackgroundHandler.post(mStartListeningRunnable) ->mBrightnessObserver.startObserving()。所以,当启动BrightnessDialog时,这望远镜就拿起来了。因为今天是分析亮度调节,我们只关注BRIGHTNESS_URI即亮度值的变化即可。
接着看一下BrightnessController在registerCallbacks 时,mStartListeningRunnable除了startObserving还做了什么:
private final Runnable mStartListeningRunnable = new Runnable() {
@Override
public void run() {
mBrightnessObserver.startObserving();
mUserTracker.startTracking();
// Update the slider and mode before attaching the listener so we don't
// receive the onChanged notifications for the initial values.
mUpdateModeRunnable.run();//1
mUpdateSliderRunnable.run();//2
mHandler.sendEmptyMessage(MSG_ATTACH_LISTENER);//3
}
};
这一段代码非常有用。标记1处是更新了亮度模式和icon。标记2处updateSlider,以使进度条与当前亮度值一致。标记3处是注册BrightnessController为ToggleSlider的Listener,所以当滑动TogglerSlider时,会触发BrightnessController.onChanged。我们只看手动滑动TogglerSlider的情形:
@Override public void onChanged(ToggleSlider view, boolean tracking, boolean automatic, int value, boolean stopTracking) { ...以上省略 } else if (!mAutomatic) { final int val = value + mMinimumBacklight; if (stopTracking) { MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val); } setBrightness(val);//1 if (!tracking) {//2 AsyncTask.execute(new Runnable() { public void run() { Settings.System.putIntForUser(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, val, UserHandle.USER_CURRENT);//3 } }); } } for (BrightnessStateChangeCallback cb : mChangeCallbacks) { cb.onBrightnessLevelChanged();//目前为空 } }
标记1处是实际设置亮度的地方,本篇先不展开。标记3处是将当前亮度值保存到系统数据库。标记2处对tracking进行了判断,当tracking为false时才保存亮度值。当连续滑动调节亮度的ToggleSlider没有停止时,tracking为true;当停止滑动后,tracking为false。也就是说在滑动过程中只改变屏幕亮度,并不保存亮度值,只有在停止滑动时,才保存亮度值。
此时有没有想起,我们最开始registerCallbacks时已经注册了BrightnessObserver?其中就包括数据库中的亮度值。标记3处修改了数据库中亮度值,所以此时会调用BrightnessObserver的onChange:
@Override
public void onChange(boolean selfChange, Uri uri) {
if (selfChange) return;
...以上省略
else if (BRIGHTNESS_URI.equals(uri) && !mAutomatic) {
mBackgroundHandler.post(mUpdateSliderRunnable);
}
...以下省略
}
我只选取了对亮度值变化的处理,即mUpdateSliderRunnable。
private final Runnable mUpdateSliderRunnable = new Runnable() { @Override public void run() { ...以上省略 } else { int value; value = Settings.System.getIntForUser(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, mMaximumBacklight, UserHandle.USER_CURRENT); mHandler.obtainMessage(MSG_UPDATE_SLIDER, mMaximumBacklight - mMinimumBacklight, value - mMinimumBacklight).sendToTarget(); } } };
这个Runnable的作用是updateSlider。(其实在滑动ToggleSlider进行亮度调节时,并不需要updateSlider,但是在另一种调节亮度的方式——通过按键调节时,就需要updateSlider了。否则你按了Brightness Up 按键,屏幕亮度也增加了,ToggleSlider的进度条却岿然不动,所以此处还是加上了mUpdateSliderRunnable 。)
以上就分析完用手滑动ToggleSlider进行亮度调节的全过程。至于真正设置亮度的方法setBrightness:
private void setBrightness(int brightness) {
try {
mPower.setTemporaryScreenBrightnessSettingOverride(brightness);
} catch (RemoteException ex) {
}
}
留待下篇再说。ヾ( ̄▽ ̄)ByeBye
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。