天天看點

詳解Android螢幕亮度和息屏的實作

1.前言

在實際應用的裝置中,特别是對于基于安卓平控制的終端裝置,需要投放至外面使用, 例如自動售貨機、安卓采集器、廣告牌等,但外面環境由于光照環境的影響,螢幕顯示的效果有所差異,是以需要基于關照強度的變化修改螢幕顯示的亮度。

同時由于特殊的應用場景,例如檢測到有人員流動等螢幕亮起,否則處于息屏狀态。本項目的整體運作效果如下所示。

詳解Android螢幕亮度和息屏的實作

2.螢幕亮度的修改

對于螢幕的亮度修改有兩種方式,一種是修改基于目前Activity的修改,該修改的效果僅僅針對于目前界面有效果,切換至其他界面時,便恢複至系統的亮度值。還有一種是基于對于系統的螢幕亮度的修改,該修改的效果如同我們在安卓的“設定–顯示–亮度”中修改的效果一樣,是對于安卓系統的整體修改。

2.1 擷取目前亮度值

在設定目前亮度前,可先擷取目前系統設定的亮度資料,系統的亮度值預設區間是0-255,可通過系統提供的ContentResolver接口的通路系統的ContentProver的資料,在Activity中可通過getContentResolver()方法得到目前的ContentResolver執行個體,進而實作對系統的ContentProver資料的通路,而Settings.System.SCREEN_BRIGHTNESS隻在系統Settings中定義好的通路的key(“screen_brightness”),通過以上方式擷取目前系統的亮度值。

int screenBrightness = 255;
        try {
            screenBrightness = Settings.System.getInt(MyApplication.mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);
        } catch (Exception localException) {

        }
           

2.2 設定目前螢幕界面亮度

擷取到目前亮度值後,可參照該值,根據業務需設定對應的亮度值,如果僅僅是對于目前螢幕的亮度的設定,可直接通過修改目前Window的LayoutParams屬性,來實作,如下所示。

Window localWindow = activity.getWindow();
        WindowManager.LayoutParams localLayoutParams = localWindow.getAttributes();
        float f = paramInt / 255.0F;
        localLayoutParams.screenBrightness = f;
        localWindow.setAttributes(localLayoutParams);
           

系統的源碼解釋如下:

public float screenBrightness = BRIGHTNESS_OVERRIDE_NONE;

大意為:在調節螢幕亮度時,使用者應首選該方法。該值區間為0-1,對應于從黑到全亮的調節。

2.3 設定系統螢幕亮度

對于擷取螢幕亮度和設定目前螢幕界面的亮度值,不需要申請權限,但是設定系統亮度值時,需要申請WRITE_SETTINGS權限,特别是當安卓版本6.0之後,還需要動态申請該權限。

在6.0後除了常見的9大類危險權限外,對于設定懸浮窗(SYSTEM_ALERT_WINDOW)和修改系統設定(WRITE_SETTINGS)這兩個權限還需要特殊設定,修改系統設定權限的授權 WRITE_SETTINGS,與其他權限不同是使用startActivityForResult來啟動系統設定的授權界面,讓使用者動态授權實作的,同時還需要在AndroidManifest.xml中添加如下

<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
           
/**
     * 申請權限
     */
    private void requestWriteSettings() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            //大于等于23 請求權限
            if (!Settings.System.canWrite(getApplicationContext())) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
                intent.setData(Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, REQUEST_CODE_WRITE_SETTINGS);
            }
        } else {
            //小于23直接設定
        }
    }
 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_WRITE_SETTINGS) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                //Settings.System.canWrite方法檢測授權結果
                if (Settings.System.canWrite(getApplicationContext())) {
                    Toast.makeText(MainActivity.this, "擷取了權限", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(MainActivity.this, "您拒絕了權限", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
           

如下圖所示,需使用者手動授權該權限。

詳解Android螢幕亮度和息屏的實作

權限申請成功後,就可以對 系統的亮度進行調節設定了,在2.1中我們提到通過getContentResolver()方法對系統應用的Settings.System.SCREEN_BRIGHTNESS對應的值進行擷取,同樣我們也可以通過該方式對該值進行指派操作。

在設定亮度值之前,我們需要先設定亮度模式,該模式包括以下兩種

  • SCREEN_BRIGHTNESS_MODE_AUTOMATIC=1 為自動調節螢幕亮度
  • SCREEN_BRIGHTNESS_MODE_MANUAL=0 為手動調節螢幕亮度

    隻有設定為手動調節模式時,才可以動态設定系統的亮度值,是以系統螢幕亮度的設定分為兩步:

  • 判斷是否為手動模式,如不是設定為手動模式;
  • 設定系統螢幕亮度
ContentResolver resolver = MyApplication.mContext.getContentResolver();
        try {
            if (Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL != (Settings.System.getInt(MyApplication.mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE))) {
                //設定為手動調節模式
                Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE,
                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
            }
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }
        //儲存到系統中
        Uri uri = android.provider.Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
        android.provider.Settings.System.putInt(resolver, Settings.System.SCREEN_BRIGHTNESS, brightness);
        resolver.notifyChange(uri, null);
           

3 亮屏與息屏

對于安卓螢幕亮屏與息屏的操作,有兩種方式,一種是通過WakeLock方法,通過鎖定和解鎖的方式控制螢幕的亮和滅;還有一種是通過設定FLAG_KEEP_SCREEN_ON方式實作。

對于螢幕亮度的熄滅都是針對于目前界面而言的,如切換界面後,螢幕的亮熄就受系統的設定的亮屏時間限制。

3.1 WakeLock方式

該方式需要申請WAKE_LOCK權限,且在使用時acquire()和release()需要成對出現,避免出現死鎖的情況。

<uses-permission android:name="android.permission.WAKE_LOCK"/>
           
PowerManager pm = (PowerManager) MyApplication.mContext.getSystemService(Context.POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "TAG");
        wakeLock.acquire();//保持螢幕常亮
         // wakeLock.acquire(30*1000);//保持螢幕常亮30s

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                wakeLock.release();//10s後息屏
            }
        },10000);
		
           

該方式的原理是,wakelock是一種鎖的機制,隻要有應用擷取到該鎖,CPU就無法進入休眠狀态,一直處于工作狀态。在通過newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, “TAG”)方式,第一個參數設定鎖的級别及标志位,可通過檢視PowerManager擷取需要參數值,第二個是設定應用的标志位,通過為類名。

設定成功後,通過 wakeLock.acquire()使其保持常亮狀态,或通過設定擁有時間(wakeLock.acquire(30*1000)),在時間結束後便自動釋放該鎖,即螢幕熄滅。也可通過 wakeLock.release()方式主動釋放。

3.2 設定FLAG方式

設定FLAG的方式的實作由兩種方式,一種是直接在該Activity的xml中設定,還有一種是在代碼中動态設定。

3.2.1 xml配置

該方式比較簡單,直接在使用的Activty的xml根目錄中添加keepScreenOn即可。

<android.support.constraint.ConstraintLayout
    .....
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:keepScreenOn="true"
    tools:context=".MainActivity">
   
           
3.2.2動态設定FLAG

該方式可以根據業務需要動态設定是否常亮或息屏,通過以下方式實作。

//保持常亮
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

//息屏
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
           

通過給當期的Window添加FLAG和清除FLAG的方式,實作螢幕熄滅。

3.3 設定系統息屏時間

除了以上簡單粗暴的方式外,我們還同樣可以參考2.1和2.3中亮度調節方案,通過getContentResolver()方法擷取系統螢幕息屏時間和設定該時間。實作原理基本類似,隻需替換key即可。如下所示。

//擷取息屏時間
 int result = 0;
        try {
            result = Settings.System.getInt(MyApplication.mContext.getContentResolver(),
                    Settings.System.SCREEN_OFF_TIMEOUT);
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }
      //設定息屏時間
      Settings.System.putInt(MyApplication.mContext.getContentResolver(),
                Settings.System.SCREEN_OFF_TIMEOUT, time);
        Uri uri = Settings.System
                .getUriFor(Settings.System.SCREEN_OFF_TIMEOUT);
        MyApplication.mContext.getContentResolver().notifyChange(uri, null);
           

需要注意的是該方式設定的 不是對于目前界面的息屏時間,而是設定系統的息屏時間,是以如獨立使用時仍然需要添加和申請系統權限(WRITE_SETTINGS)。

4 小結

本文主要講述了在安卓終端使用時對螢幕的常有兩種操作,即亮度和息屏操作。概括如下:

  1. 螢幕亮度或息屏時間的擷取可通過getContentResolver()擷取系統資料庫的值,且不需要申請權限,可參考2.1和3.3
  2. 如果是對于當期界面亮度或螢幕熄滅的操作,可直接通過修改WindowManager的LayoutParams方法實作對亮度或息屏操作,參考2.2、3.1和 3.2;
  3. 但對于系統的設定需要申請WRITE_SETTINGS權限,具體可參考2.3中權限申請的實作細節,對于系統屬性的修改是通過getContentResolver()方式實作,可參考2.3和3.3。

備注:本文的參考Demo的github下載下傳位址,歡迎star和fork。