当前位置:   article > 正文

Android 7.1 亮度调节之BrightnessController_android brightnesscontroller

android brightnesscontroller

Android 7.1 亮度调节之BrightnessController

通过“设置->显示->亮度”可以调节屏幕亮度,当点击“亮度”这个选项时,会弹出如下菜单:
亮度调节实际上这是一个系统Activity,下面就先来分析一下是如何启动这个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>

       ...以下省略
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

当点击“亮度”的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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

可以看到,这个action会启动SystemUI的"BrightnessDialog"。 那么接下来就分析一下BrightnessDialog这个Activity吧。

BrightnessDialog

这个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);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

BrightnessDialog的onCreate一共干了两件事,一是加载了布局文件,二是创建了BrightnessController。而onStart就是执行了BrightnessController.registerCallbacks。所以,重点在BrightnessController。接下来就分析一下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);
        ...以下省略
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

其中创建了一个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);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这一段代码非常有用。标记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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

标记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);
            } 
            ...以下省略
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

我只选取了对亮度值变化的处理,即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();
            }
        }
    };

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

这个Runnable的作用是updateSlider。(其实在滑动ToggleSlider进行亮度调节时,并不需要updateSlider,但是在另一种调节亮度的方式——通过按键调节时,就需要updateSlider了。否则你按了Brightness Up 按键,屏幕亮度也增加了,ToggleSlider的进度条却岿然不动,所以此处还是加上了mUpdateSliderRunnable 。)
以上就分析完用手滑动ToggleSlider进行亮度调节的全过程。至于真正设置亮度的方法setBrightness:

private void setBrightness(int brightness) {
        try {
            mPower.setTemporaryScreenBrightnessSettingOverride(brightness);
        } catch (RemoteException ex) {
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

留待下篇再说。ヾ( ̄▽ ̄)ByeBye

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/643005
推荐阅读
相关标签
  

闽ICP备14008679号