作 Android 音視頻播放器開發的時候,咱們基本都會遇到一類需求:音量 & 亮度 調節。其中作亮度調節功能的時候,發現仍是有必定複雜度的。編碼
Android亮度調節分爲兩個類,分別是:code
Android系統亮度調節全局性最高,常見於系統設置中的亮度設置項。Android中提供了獲取和設置系統亮度值的接口,具體以下:視頻
// 獲取系統亮度 Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);
// 設置系統亮度 Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS,systemBrightness);
其中,須要注意的是,返回的亮度值是處於0-255之間的整型數值。blog
Android 2.1之後的系統中,系統亮度調節中新增了「自動亮度」選項。「自動亮度」是依據外界光源來自動的改變系統亮度,目前大部分手機中對「自動亮度」還能夠進行小幅度的調節其值。與自動亮度相對應的是「手動亮度」,當處於「手動亮度」下,設置拖動亮度進度條會大幅度的改變Android系統亮度。「手動亮度」和「自動亮度」分別稱之爲Android系統的「亮度模式」。接口
與之相對應的,Android系統中也提供了獲取和設置「亮度模式」的接口。開發
// 獲取系統亮度模式 Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE);
// 設置系統亮度模式 Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, systemMode);
但是遺憾的是,Android中並未提供處於「自動亮度」模式下的亮度值接口。上面所說的獲取系統亮度值接口實際上都是指「手動亮度」模式下的亮度值。get
通常而言,經過手動亮度值以及設置系統亮度模式接口,能夠知足常規的大部分針對Android系統亮度設置編碼需求,以完成系統亮度調節。it
Android針對當前屏幕(Window)提供了設置亮度的接口,常見寫法以下:class
Window window = activity.getWindow(); WindowManager.LayoutParams lp = window.getAttributes(); lp.screenBrightness = brightness; window.setAttributes(lp);
其中,須要注意的是此處的brightness是一個0.0-1.0之間的一個float類型數值。後臺
默認狀況下,當咱們直接修改了系統亮度值後,當前Window中是能夠即時反應出來亮度效果的,這是由於默認狀況下,WindowManager.LayoutParams的screenBrightness的默認值爲WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE。
即表示Window沒有本身的亮度參數,將依隨系統亮度效果的變化而變化。這也就是咱們最多見的:當調整系統亮度後,全部Window都即時反應出系統亮度設置效果。
當時,實際項目中咱們還會遇到此類需求:系統設置亮度時只針對當前Window或App內生效,而不影響到系統自己的亮度設置。
假設當前Window內有一個SeekBar,UI與系統亮度調節UI基本相似,用戶能夠滑動此SeekBar,使得當前Window亮度即時發生變化,且不影響到系統亮度效果。如何實現呢?
此時咱們須要啓用WindowManager.LayoutParams的screenBrightness參數,使之具備自動的特定亮度值,設置此值後在當前Window範圍內,其將覆蓋掉系統亮度設置。
所以,有必要將用戶選擇的亮度值轉換爲相應的Window亮度值(爲與系統亮度值相一致,假設SeekBar的最大值爲255)。
// 根據亮度值修改當前window亮度 public void changeAppBrightness(Context context, int brightness) { Window window = ((Activity) context).getWindow(); WindowManager.LayoutParams lp = window.getAttributes(); if (brightness == -1) { lp.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE; } else { lp.screenBrightness = (brightness <= 0 ? 1 : brightness) / 255f; } window.setAttributes(lp); }
其中,brightness形參爲用戶選擇的亮度值。
那麼,上述代碼中爲何有一個"brightness == -1"的判斷呢?在此主要是考慮到App設置項中可能出現的「跟隨系統亮度」或「恢復系統默認亮度」此類設置,當用戶進行此類操做時,直接將screenBrightness參數還原成默認參數值便可。由於由前文描述「自動亮度」模式下系統亮度值是不能直接獲得的,那麼當系統處於「自動亮度」模式下,此時brightness參數值將沒法準確肯定,所以,將screenBrightness參數還原成默認參數值成爲一個行之有效的方法。
目前網上有很多博文中提到App亮度調節時,提出的方案是在App設置項中,首先記錄下設置以前的系統亮度值和亮度模式,用戶在App設置項進行亮度調節時,直接修改系統亮度值,當用戶退出此App,或App至於後臺(如按下Home按鍵等),再將系統亮度還原。初看起來貌似一個可行的方案。可是主要存在以下幾個問題:
1.如何獲取到設置以前的系統亮度值和亮度模式(由於以後在此App外部要恢復系統亮度值到此初始值)?當用戶每次進入到設置頁時獲取?嚴格意義上來講,是無法準確記錄的。由於Android的用戶操做不可預知性,如進入到設置頁,拖動SeekBar設置了一個亮度值,此時直接修改了系統的亮度值,若是此時用戶在未將應用至於後臺或未將應用退出的狀況下直接在App外部修改了系統亮度設置,如小米中能夠經過下拉標題欄,直接就能夠設置系統亮度。所以,App亮度設置以前的系統亮度初始值獲取存在困難。
2.如何判斷用戶來到了App外部?由於此時須要恢復系統亮度設置到初始系統亮度。如用戶能夠按下Home按鍵,長按Home按鍵直接切換App,直接Back按鍵等一步步退出此App,下拉標題欄直接點擊其餘App通知信息進入到其餘App,手機自動鎖屏後解鎖時用戶直接進入其餘應用等等,此類操做場景也具備不可預知性,所以,判斷用戶來到了App外部以恢復系統亮度到初始值的時機上也存在必定困難。
由此,App亮度調節方案推薦經過設置當前屏幕(Window)方式進行。
大體思路以下:
1. 用戶在設置項中進行亮度調節時,調用changeAppBrightness()方法,將改變當前屏幕(Window)的亮度,此時對系統亮度無任何影響,接下來存在的問題終於要就集中於當用戶來到本App其餘Activity中,若是使得剛剛設置的亮度值得以即時反應出來。
2. 當用戶進行亮度調節後,將當前亮度設置值保存起來(如保存到SharedPreferences中),在基類Activity中的onResume方法中,能夠取出SharedPreferences中的用戶所設置的App亮度值,而後changeAppBrightness()方法以實現每一個當前屏幕的亮度調節。
整體說來,經過設置當前屏幕(Window)的方式來設置App亮度更加簡單有效。