【Android】屏幕超時休眠
前言
屏幕超時休眠指的是在設備一段時間沒有操作后,自動關閉屏幕顯示以節省電量并防止誤觸。當屏幕進入休眠狀態時,通常會關閉屏幕背光,但設備可能仍在運行后臺進程。
正文
Settings應用相關
Settings應用的屏幕超時休眠界面相關代碼定位到:
packages/apps/Settings/res/xml/display_settings.xml
屏幕超時休眠的控件的key值為screen_timeout。屏幕超時休眠列表選項信息,根據key值找到控件,隨后根據android:entries和android:entryValues相關代碼定位到:
packages/apps/Settings/res/values/arrays.xml
相關Controller代碼定位到:
packages/apps/Settings/src/com/android/settings/display/TimeoutPreferenceController.java
@Override
public void updateState(Preference preference) {
final TimeoutListPreference timeoutListPreference = (TimeoutListPreference) preference;
final long currentTimeout = Settings.System.getLong(mContext.getContentResolver(),
SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE);//獲取到設置的屏幕超時休眠時間
timeoutListPreference.setValue(String.valueOf(currentTimeout));
final DevicePolicyManager dpm =
(DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
if (dpm != null) {
final RestrictedLockUtils.EnforcedAdmin admin =
RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(mContext);
final long maxTimeout =
dpm.getMaximumTimeToLock(null /* admin */, UserHandle.myUserId());
timeoutListPreference.removeUnusableTimeouts(maxTimeout, admin);
}
updateTimeoutPreferenceDescription(timeoutListPreference, currentTimeout);//更新屏幕超時休眠時間描述
EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
mContext, UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT,
UserHandle.myUserId());
if(admin != null) {
timeoutListPreference.removeUnusableTimeouts(0/* disable all*/, admin);
}
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
try {
int value = Integer.parseInt((String) newValue);//獲取到設置的新的屏幕超時休眠時間
Settings.System.putInt(mContext.getContentResolver(), SCREEN_OFF_TIMEOUT, value);//設置新的屏幕超時休眠時間
updateTimeoutPreferenceDescription((TimeoutListPreference) preference, value);//更新屏幕超時休眠時間描述
} catch (NumberFormatException e) {
Log.e(TAG, "could not persist screen timeout setting", e);
}
return true;
}
//更新屏幕超時休眠時間描述
private void updateTimeoutPreferenceDescription(TimeoutListPreference preference,
long currentTimeout) {
final String summary;
// 省略部分源代碼
preference.setSummary(summary);//設置描述信息
}
屬性值相關
屏幕超時休眠默認時間,定位到:
frameworks/base/packages/SettingsProvider/res/values/defaults.xml
<integer name="def_screen_off_timeout">15000</integer>
默認時間屬性值是寫在SQLite中,具體詳情見:
packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
屏幕超時休眠默認最低時間,定位到:
frameworks/base/core/res/res/values/config.xml
<!-- User activity timeout: Minimum screen off timeout in milliseconds.
Sets a lower bound for the {@link Settings.System#SCREEN_OFF_TIMEOUT} setting
which determines how soon the device will go to sleep when there is no
user activity.
This value must be greater than zero, otherwise the device will immediately
fall asleep again as soon as it is awoken.
-->
<integer name="config_minimumScreenOffTimeout">10000</integer>
由上述注釋信息,可知屏幕超時休眠默認最低時間需要設置在 \(0\) 以上。既然如此,我們如果設置的值是一個小于最低默認值的數值,甚至是一個小于等于 \(0\) 的數值又會發生什么事情呢?
在framework/base目錄下搜 \(screen\_off\_timeout\) 可以定位到:
core/java/android/provider/Settings.java
public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout";
private static final Validator SCREEN_OFF_TIMEOUT_VALIDATOR = NON_NEGATIVE_INTEGER_VALIDATOR;//屏幕超時休眠時間校驗器
//省略部分源代碼
static {
//省略部分源代碼
VALIDATORS.put(SCREEN_OFF_TIMEOUT, SCREEN_OFF_TIMEOUT_VALIDATOR);//添加校驗器
//省略部分源代碼
}
于是查看校驗器NON_NEGATIVE_INTEGER_VALIDATOR相關代碼,定位到:
framework/base/core/java/android/provider/SettingsValidators.java
public static final Validator NON_NEGATIVE_INTEGER_VALIDATOR = new Validator() {
@Override
public boolean validate(@Nullable String value) {
try {
return Integer.parseInt(value) >= 0;
} catch (NumberFormatException e) {
return false;
}
}
};
由上述校驗器代碼可知,若傳入的值是個負數,校驗器會對傳入的值進行異常拋出,保證代碼不崩潰。
項目實戰
修改休眠時間列表
根據Settings應用的xml界面的android:entries和android:entryValues相關代碼定位到:
packages/apps/Settings/res/values/arrays.xml
直接添加item即可。
若新增的item的value低于屏幕超時休眠默認最低時間,需要修改系統默認最低值
frameworks/base/core/res/res/values/config.xml
<integer name="config_minimumScreenOffTimeout">10000</integer>
修改系統默認屏幕超時休眠時間
修改defaults.xml下的def_screen_off_timeout屬性值即可。
frameworks/base/packages/SettingsProvider/res/values/defaults.xml
<integer name="def_screen_off_timeout">15000</integer>
三方app自定義屏幕超時休眠時間
首先,在Settings應用中添加一個廣播,在源代碼中添加一個action來接收即可,定位到路徑:
packages/apps/Settings/AndroidManifest.xml
<!-- 找到一個已有的receiver,或者新增一個receiver都是可行的,隨后聲明一個自定義ACTION -->
<receiver android:name=".SettingsInitialize">
<intent-filter>
<action android:name="自定義ACTION"/>
<action android:name="android.intent.action.USER_INITIALIZE"/>
<action android:name="android.intent.action.PRE_BOOT_COMPLETED"/>
</intent-filter>
</receiver>
在廣播接收器的類中實現接收的邏輯
packages/apps/Settings/src/com/android/settings/SettingsInitialize.java
@Override
public void onReceive(Context context, Intent broadcast) {
//begin:新增的代碼
String action = broadcast.getAction();
if (context.getString(自定義ACTION的字符串資源路徑).equals(action)) {
final long currentTimeout = Settings.System.getLong(context.getContentResolver(),
SCREEN_OFF_TIMEOUT, TimeoutPreferenceController.FALLBACK_SCREEN_TIMEOUT_VALUE);
int value = broadcast.getIntExtra("screen_off_timeout", (int)currentTimeout);
Settings.System.putInt(context.getContentResolver(), SCREEN_OFF_TIMEOUT, value);
return ;
}
//end:新增的代碼
final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
UserInfo userInfo = um.getUserInfo(UserHandle.myUserId());
final PackageManager pm = context.getPackageManager();
managedProfileSetup(context, pm, broadcast, userInfo);
webviewSettingSetup(context, pm, userInfo);
refreshExistingShortcuts(context);
}
在自己的三方應用中添加如下核心代碼
Intent screenTimeoutIntent = new Intent("自定義ACTION");
int value = 20000;//新定義的屏幕超時休眠時間
screenTimeoutIntent.putExtra("screen_off_timeout", value);
//若Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND找不到,就用0x01000000硬編碼替換
screenTimeoutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
sendBroadcast(screenTimeoutIntent);//發出廣播,通知更新屏幕超時休眠時間
若是希望可以自定義的屏幕超時休眠時間可以低于系統默認最低超時休眠時間,則需要連同系統默認休眠時間一起修改。
浙公網安備 33010602011771號