Android11.0隐藏状态栏及导航栏
隐藏状态栏及导航栏
本文描述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
- Settings中添加全局变量,修改路径 /frameworks/base/core/java/android/provider/Settings.java;
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";
//********省略代码******
}
- 添加开关默认值,修改路径 /frameworks/base/packages/SettingsProvider/res/values/defaults.xml;
<resources>
//********省略代码******
<integer name="def_hide_navigation">0</integer>
<integer name="def_hide_statusbar">0</integer>
//********省略代码******
</resources>
- 添加proto,修改路径 /frameworks/base/core/proto/android/providers/settings/global.proto;
//********省略代码******
message Display {
//********省略代码******
optional SettingProto hide_navigation_on = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto hide_statusbar_on = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
//********省略代码******
- 开关默认值加载,修改路径 /frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java;
//********省略代码******
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);
}
//********省略代码******
- 修改路径 /frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java;
//********省略代码******
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);
//********省略代码******
设备-显示中添加隐藏状态栏及隐藏导航栏开关
- 定义开关名称文字 修改路径 /packages/app/Settings/res/values/strings.xml
//********省略代码******
<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>
//********省略代码******
- 布局中添加开关 修改路径 /packages/app/Settings/res/xml/display_settings.xml
//********省略代码******
<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" />
//********省略代码******
- 添加开关的控制器类 路径:/packages/app/Settings/src/com/android/settings/display/HideStatusBarPreferenceController.java
/packages/app/Settings/src/com/android/settings/display/HideNavigationPreferenceController.java
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;
}
}
定义隐藏状态栏及导航栏的广播字串
- 定义广播字串 修改路径 /frameworks/base/core/java/android/content/Intent.java
//********省略代码******
/**
* 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";
//********省略代码******
- 添加权限 修改路径 /frameworks/base/core/res/AndroidManifest.xml(如果不添加,发送广播时,会报Sending non-protected broadcast xxxxxxx from system xxxxxxxxxx错误,但不影响程序执行)
//********省略代码******
<protected-broadcast android:name="android.intent.action.HIDE_STATUSBAR" />
<protected-broadcast android:name="android.intent.action.HIDE_NAVIGATION" />
//********省略代码******
SystemUI中处理广播隐藏状态栏及导航栏
- 修改路径 /frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
说明:网上很多都是调用createNavigationBar(result)显示导航栏,removeNavigationBar()隐藏导航栏,当在设置-显示界面隐藏导航栏在显示时,导航栏按钮图标会不是暗色模式,会与背景分不清楚,所以使用隐藏导航栏view的方式实现。
//********省略代码******
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();
}
}
//********省略代码******