Android11.0隐藏状态栏及导航栏

Android11.0隐藏状态栏及导航栏

  • 隐藏状态栏及导航栏
    • 添加全局状态保存配置
    • 设备-显示中添加隐藏状态栏及隐藏导航栏开关
    • 定义隐藏状态栏及导航栏的广播字串
    • SystemUI中处理广播隐藏状态栏及导航栏

隐藏状态栏及导航栏

本文描述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

  1. 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";
        
  //********省略代码******
}
  1. 添加开关默认值,修改路径 /frameworks/base/packages/SettingsProvider/res/values/defaults.xml;
<resources>
//********省略代码******
    <integer name="def_hide_navigation">0</integer>
    <integer name="def_hide_statusbar">0</integer>
//********省略代码******
</resources>
  1. 添加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 ];
    }

//********省略代码******
  1. 开关默认值加载,修改路径 /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);

}

//********省略代码******
  1. 修改路径 /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);

//********省略代码******

设备-显示中添加隐藏状态栏及隐藏导航栏开关

  1. 定义开关名称文字 修改路径 /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>

//********省略代码******
  1. 布局中添加开关 修改路径 /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" />

//********省略代码******
  1. 添加开关的控制器类 路径:/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;
    }
}

定义隐藏状态栏及导航栏的广播字串

  1. 定义广播字串 修改路径 /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";

//********省略代码******
  1. 添加权限 修改路径 /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中处理广播隐藏状态栏及导航栏

  1. 修改路径 /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();
        }
    }

//********省略代码******

你可能感兴趣的:(Android11.0,android)