android9.0在设置里添加开关控件去隐藏或显示导航栏
前言:基于高通平台定制android系统。在自己每次接触新的技术需求时,总是会出现很多低级或不懂的问题,因为第一次搞欠缺经验,所以只能花费很多时间和各种方法去尝试。例如这次设置里添加虚拟按键开关,就用了一个多星期去解决问题,主要是发送广播不成功问题。话不多说,进入正题:首先看一下原始界面:一、广播实现1.定义广播内容frameworks/base/core/java/android/content
前言:
基于高通平台定制android系统。在自己每次接触新的技术需求时,总是会出现很多低级或不懂的问题,因为第一次搞欠缺经验,所以只能花费很多时间和各种方法去尝试。例如这次设置里添加虚拟按键开关,就用了一个多星期去解决问题,主要是发送广播不成功问题。话不多说,进入正题:
首先看一下原始界面:
一、广播实现
1.定义广播内容
frameworks/base/core/java/android/content/Intent.java
public static final String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";
+ public static final String ACTION_NAVIGATION_SHOW = "android.intent.action.NAVIGATION_SHOW";
+ public static final String ACTION_NAVIGATION_HIDE = "android.intent.action.NAVIGATION_HIDE";
2.动态注册广播
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_NAVIGATION_SHOW);
+ filter.addAction(Intent.ACTION_NAVIGATION_HIDE);
3.广播接收处理
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -909,7 +910,9 @@ public class StatusBar extends SystemUI implements DemoMode,
boolean showNav = mWindowManagerService.hasNavigationBar();
if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
if (showNav) {
- createNavigationBar();
+ if(1==Settings.System.getInt(mContext.getContentResolver(), Settings.System.HIDE_NAVIGATION, 1)){
+ createNavigationBar();
+ }
}
} catch (RemoteException ex) {
// no window manager? good luck with that
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.v(TAG, "onReceive: " + intent);
String action = intent.getAction();
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
KeyboardShortcuts.dismiss();
if (mRemoteInputManager.getController() != null) {
mRemoteInputManager.getController().closeRemoteInputs();
}
if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) {
int flags = CommandQueue.FLAG_EXCLUDE_NONE;
String reason = intent.getStringExtra("reason");
if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
}
animateCollapsePanels(flags);
}
}
else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
finishBarAnimations();
resetUserExpandedStates();
}
else if (DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG.equals(action)) {
mQSPanel.showDeviceMonitoringDialog();
}
else if (Intent.ACTION_NAVIGATION_HIDE.equals(action)){
removeBar();
Settings.System.putInt(mContext.getContentResolver(), Settings.System.HIDE_NAVIGATION, 1);
Log.d(TAG, "android.intent.action.NAVIGATION_HIDE");
}
else if(Intent.ACTION_NAVIGATION_SHOW.equals(action)){
addBarInside();
Settings.System.putInt(mContext.getContentResolver(), Settings.System.HIDE_NAVIGATION, 0);
Log.d(TAG, "android.intent.action.NAVIGATION_SHOW");
}
}
};
二、设置到数据库
1.添加key到数据库中
frameworks/base/core/java/android/provider/Settings.java
public static final Uri DEFAULT_NOTIFICATION_URI = getUriFor(NOTIFICATION_SOUND);
+ /**
+ * add by wuxb
+ * Whether hide navigation
+ * 0 = no
+ * 1 = yes
+ */
+ public static final String HIDE_NAVIGATION = "hide_navigation";
+ public static final Uri HIDE_NAVIGATION_URI = getUriFor(HIDE_NAVIGATION);
+ private static final Validator HIDE_NAVIGATION_VALIDATOR = URI_VALIDATOR;
@@ -4163,6 +4173,7 @@ public final class Settings {
RINGTONE,
LOCK_TO_APP_ENABLED,
NOTIFICATION_SOUND,
+ HIDE_NAVIGATION,
ACCELEROMETER_ROTATION,
SHOW_BATTERY_PERCENT,
NOTIFICATION_VIBRATION_INTENSITY,
@@ -4218,6 +4229,7 @@ public final class Settings {
PUBLIC_SETTINGS.add(VOLUME_BLUETOOTH_SCO);
PUBLIC_SETTINGS.add(RINGTONE);
PUBLIC_SETTINGS.add(NOTIFICATION_SOUND);
+ PUBLIC_SETTINGS.add(HIDE_NAVIGATION);
PUBLIC_SETTINGS.add(ALARM_ALERT);
PUBLIC_SETTINGS.add(TEXT_AUTO_REPLACE);
PUBLIC_SETTINGS.add(TEXT_AUTO_CAPS);
@@ -4315,6 +4327,7 @@ public final class Settings {
VALIDATORS.put(HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
VALIDATORS.put(RINGTONE, RINGTONE_VALIDATOR);
VALIDATORS.put(NOTIFICATION_SOUND, NOTIFICATION_SOUND_VALIDATOR);
+ VALIDATORS.put(HIDE_NAVIGATION,HIDE_NAVIGATION_VALIDATOR);
VALIDATORS.put(ALARM_ALERT, ALARM_ALERT_VALIDATOR);
VALIDATORS.put(TEXT_AUTO_REPLACE, TEXT_AUTO_REPLACE_VALIDATOR);
VALIDATORS.put(TEXT_AUTO_CAPS, TEXT_AUTO_CAPS_VALIDATOR);
2.设置默认值
frameworks/base/packages/SettingsProvider/res/values/defaults.xml
+ <!-- hide navigation -->
+ <integer name="def_hide_navigation">1</integer>
<bool name="def_bluetooth_on">false</bool>
3.将默认值添加到数据库
frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
//set hide navigation
loadIntegerSetting(stmt, Settings.System.HIDE_NAVIGATION,
R.integer.def_hide_navigation);
三、设置开关显示
1.支持中英文标题
packages/apps/Settings/res/values-zh-rCN/strings.xml
<string name="navigation_settings_title">"虚拟按键"</string>
packages/apps/Settings/res/values/strings.xml
<string name="navigation_settings_title">Navigation settings</string>
2.开关布局UI显示
packages/apps/Settings/res/xml/display_settings.xml
<SwitchPreference
android:key="navigation"
android:title="@string/navigation_settings_title"
android:persistent="false"
settings:controller="com.android.settings.display.OperateNavigationPreferenceController" />
由于qualcomm平台不同mtk平台,并不是把代码都直接加在DisplaySettings.java文件里的,而是单独写一个实现类的方法
1.packages/apps/Settings/src/com/android/settings/display$ vim OperateNavigationPreferenceController.java
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
try {
boolean isOpen = (boolean)newValue;
if (isOpen) {
mContext.sendBroadcast(new Intent(Intent.ACTION_NAVIGATION_SHOW));
}else {
mContext.sendBroadcast(new Intent(Intent.ACTION_NAVIGATION_HIDE));
}
Log.i(TAG, "onPreferenceChange isOpen="+isOpen);
} catch (Exception e) {
Log.e(TAG, "could not persist night mode setting", e);
return false;
}
return true;
}
第一次编译烧写后,发现点击开关没有反应,然后验证自己的广播是否有问题,adb发送广播是没有问题,因为 这个问题,尝试了很多方法,以为是哪个地方没有添加到,然后没有编译到这个文件,因为看log都没有信息。或者是不是系统权限问题,或是packages目录下的广播发送在frameworks目录下接收不到;陆续编译了十几次都是失败的,之前走的弯路都是错误的;最后找到问题所在:对于不同的版本,API的接口是有差异的(难怪一开始仿照系统其它开关控件不行,因为系统调节音量、亮度都有专门的API);如下图所示:
解决方法:
@Override
public boolean isChecked() {
return Settings.System.getInt(mContext.getContentResolver(), HIDE_NAVIGATION, 1) == 1;
}
@Override
public boolean setChecked(boolean isChecked) {
Log.i(TAG, "onPreferenceChange isChecked="+isChecked);
if (isChecked) {
mContext.sendBroadcast(new Intent(Intent.ACTION_NAVIGATION_SHOW));
}else {
mContext.sendBroadcast(new Intent(Intent.ACTION_NAVIGATION_HIDE));
}
Settings.System.putInt(mContext.getContentResolver(), HIDE_NAVIGATION, isChecked ? 1 : 0);
return true;
}
调试过程中还有一个有趣问题,就是开关实现广播发送时却出现只有一半的作用,即能开显示不能关隐藏或者能关隐藏不能开显示,但是按下面操作就没有问题:
sendBroadcast要发Intent.ACTION_NAVIGATION_HIDE不发android.intent.action.NAVIGATION_HIDE
adb发广播要发android.intent.action.NAVIGATION_HIDE不发android.intent.action.NAVIGATION_HIDE
最终实现的效果:
2020-07-30 Navigation
更多推荐
所有评论(0)