本文描述Android11系统设置-显示中添加隐藏状态栏及导航栏开关及功能实现。
在M(Android5.0)版本之前,SettingsProvider中系统设置是存储在settings.db数据库中;但是在L(Android6.0)之后,SettingsProvider中系统设置改为由xml存储在data分区,路径为 /data/system/users/0/:
settings_global.xml
settings_secure.xml
settings_system.xml
public static final class Global extends NameValueTable{
//********省略代码******
/**
* Hide Navigation.
*
* @hide
*/
public static final String HIDE_NAVIGATION = "hide_navigation";
/**
* Hide StatusBar.
*
* @hide
*/
public static final String HIDE_STATUSBAR = "hide_statusbar";
//********省略代码******
}
<resources>
//********省略代码******
<integer name="def_hide_navigation">0</integer>
<integer name="def_hide_statusbar">0</integer>
//********省略代码******
</resources>
//********省略代码******
message Display {
//********省略代码******
optional SettingProto hide_navigation_on = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto hide_statusbar_on = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
//********省略代码******
//********省略代码******
private void loadGlobalSettings(SQLiteDatabase db){
loadIntegerSetting(stmt, Settings.Global.HIDE_NAVIGATION, R.integer.def_hide_navigation);
loadIntegerSetting(stmt, Settings.Global.HIDE_STATUSBAR, R.integer.def_hide_statusbar);
}
//********省略代码******
//********省略代码******
final long displayToken = p.start(GlobalSettingsProto.DISPLAY);
//********省略代码******
dumpSetting(s, p,
Settings.Global.HIDE_NAVIGATION,
GlobalSettingsProto.Display.HIDE_NAVIGATION_ON);
dumpSetting(s, p,
Settings.Global.HIDE_STATUSBAR,
GlobalSettingsProto.Display.HIDE_STATUSBAR_ON);
p.end(displayToken);
//********省略代码******
//********省略代码******
<string name="hide_navigation">Hide Navigation</string>
<string name="hide_statusbar">Hide StatusBar</string>
//********省略代码******
修改路径 /packages/app/Settings/res/values-zh-rCN/strings.xml
//********省略代码******
<string name="hide_navigation">隐藏导航栏</string>
<string name="hide_statusbar">隐藏状态栏</string>
//********省略代码******
//********省略代码******
<SwitchPreference
android:key="hide_navigation"
android:title="@string/hide_navigation"
settings:controller="com.android.settings.display.HideNavigationPreferenceController" />
<SwitchPreference
android:key="hide_statusbar"
android:title="@string/hide_statusbar"
settings:controller="com.android.settings.display.HideStatusBarPreferenceController" />
//********省略代码******
package com.android.settings.display;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import com.android.settings.core.TogglePreferenceController;
import static android.content.Intent.ACTION_HIDE_STATUSBAR;
public class HideStatusBarPreferenceController extends TogglePreferenceController {
private Context mContext;
public HideStatusBarPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mContext = context;
}
@Override
public boolean isChecked() {
return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.HIDE_STATUSBAR, 0) == 1 ? true : false;
}
@Override
public boolean setChecked(boolean isChecked) {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.HIDE_STATUSBAR, isChecked ? 1 : 0);
mContext.sendBroadcast(new Intent(ACTION_HIDE_STATUSBAR));
return true;
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
}
package com.android.settings.display;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import com.android.settings.core.TogglePreferenceController;
import static android.content.Intent.ACTION_HIDE_NAVIGATION;
public class HideNavigationPreferenceController extends TogglePreferenceController {
private Context mContext;
public HideNavigationPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mContext = context;
}
@Override
public boolean isChecked() {
return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.HIDE_NAVIGATION, 0) == 1 ? true : false;
}
@Override
public boolean setChecked(boolean isChecked) {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.HIDE_NAVIGATION, isChecked ? 1 : 0);
mContext.sendBroadcast(new Intent(ACTION_HIDE_NAVIGATION));
return true;
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
}
//********省略代码******
/**
* hide statusbar.
*
* @hide
*/
public static final String ACTION_HIDE_STATUSBAR =
"android.intent.action.HIDE_STATUSBAR";
/**
* hide navigation.
*
* @hide
*/
public static final String ACTION_HIDE_NAVIGATION =
"android.intent.action.HIDE_NAVIGATION";
//********省略代码******
//********省略代码******
<protected-broadcast android:name="android.intent.action.HIDE_STATUSBAR" />
<protected-broadcast android:name="android.intent.action.HIDE_NAVIGATION" />
//********省略代码******
//********省略代码******
private static final int MSG_HIDE_STATUSBAR = 10001;
private static final int MSG_HIDE_NAVIGATION = 10002;
protected class H extends Handler {
@Override
public void handleMessage(Message m) {
switch (m.what) {
//********省略代码******
//新增
case MSG_HIDE_STATUSBAR:
changeStatusBar();
break;
case MSG_HIDE_NAVIGATION:
changeNavigationBar();
break;
}
}
}
@VisibleForTesting
protected void registerBroadcastReceiver() {
//********省略代码******
filter.addAction(Intent.ACTION_HIDE_STATUSBAR);
filter.addAction(Intent.ACTION_HIDE_NAVIGATION);
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.v(TAG, "onReceive: " + intent);
//********省略代码******
else if (Intent.ACTION_HIDE_STATUSBAR.equals(action)) {
mHandler.removeMessages(MSG_HIDE_STATUSBAR);
mHandler.sendEmptyMessageDelayed(MSG_HIDE_STATUSBAR, 350);
} else if (Intent.ACTION_HIDE_NAVIGATION.equals(action)) {
mHandler.removeMessages(MSG_HIDE_NAVIGATION);
mHandler.sendEmptyMessageDelayed(MSG_HIDE_NAVIGATION, 350);
}
}
};
protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
//********省略代码******
//更新状态栏及导航栏
refreshStatusBarAndNavigation();
}
private void changeStatusBar() {
boolean isShow = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.HIDE_STATUSBAR, 0) == 0;
mPhoneStatusBarWindow.setVisibility(isShow ? VISIBLE : GONE);
}
private void changeNavigationBar() {
boolean isShow = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.HIDE_NAVIGATION, 0) == 0;
getNavigationBarView().getRootView().setVisibility(isShow ? VISIBLE : GONE);
}
private void refreshStatusBarAndNavigation() {
changeStatusBar();
boolean isShow = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.HIDE_NAVIGATION, 0) == 0;
if (!isShow) {
new Thread() {
@Override
public void run() {
while (true) {
if (null != getNavigationBarView()) {
mHandler.post(() -> changeNavigationBar());
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
//********省略代码******