Android11在导航栏中添加软关机按钮
一、配置文件准备:
1.准备一张power按钮的图片:
Android11和以往又有不同,不再是用png格式的图片,用的是矢量图。可以阿里巴巴矢量图库里面招图片,再用as转成xml文件,内容如下:
packages/SystemUI/res/drawable/ic_sysbar_power.xml
<?xml version="1.0" encoding="utf-8"?>"24dp" android:viewportHeight="1024" android:viewportWidth="1024" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> "#FFFFFF" android:pathData="M705.6,124.9c-5.3,-2.7 -11.6,1.2 -11.6,7.2v64.2c0,5.5 2.9,10.6 7.5,13.6 22.4,14.1 43.2,30.7 62.2,49.8 32.7,32.8 58.4,70.9 76.3,113.3 18.5,43.9 27.9,90.5 27.9,138.7 0,48.1 -9.4,94.8 -27.9,138.7 -17.9,42.4 -43.6,80.5 -76.3,113.3 -32.7,32.8 -70.8,58.5 -113.2,76.4 -43.8,18.6 -90.5,28 -138.5,28s-94.7,-9.4 -138.5,-28c-42.4,-17.9 -80.5,-43.6 -113.2,-76.4 -32.7,-32.8 -58.4,-70.9 -76.3,-113.3 -18.5,-43.9 -27.9,-90.5 -27.9,-138.7 0,-48.1 9.4,-94.8 27.9,-138.7 17.9,-42.4 43.6,-80.5 76.3,-113.3 19,-19 39.8,-35.6 62.2,-49.8 4.7,-2.9 7.5,-8.1 7.5,-13.6V132c0,-6 -6.3,-9.8 -11.6,-7.2C178.5,195.2 82,339.3 80,506.3 77.2,745.1 272.5,943.5 511.2,944c239,0.5 432.8,-193.3 432.8,-432.4 0,-169.2 -97,-315.7 -238.4,-386.7z"/> "#FFFFFF" android:pathData="M480,560h64c4.4,0 8,-3.6 8,-8V88c0,-4.4 -3.6,-8 -8,-8h-64c-4.4,0 -8,3.6 -8,8v464c0,4.4 3.6,8 8,8z"/>
2.添加按键布局:
diff --git a/packages/SystemUI/res/layout/power.xml b/packages/SystemUI/res/layout/power.xml new file mode 100755 index 0000000..013577f --- /dev/null +++ b/packages/SystemUI/res/layout/power.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> + +<com.android.systemui.statusbar.policy.KeyButtonView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:systemui="http://schemas.android.com/apk/res-auto" + android:id="@+id/power" + android:layout_width="@dimen/navigation_key_width" + android:layout_height="match_parent" + android:layout_weight="0" + systemui:keyCode="0" + android:scaleType="center" + android:contentDescription="@string/accessibility_power" + android:paddingStart="@dimen/navigation_key_padding" + android:paddingEnd="@dimen/navigation_key_padding" + /> +
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml old mode 100644 new mode 100755 index 174f5c7..34c65af --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -302,6 +302,8 @@ <string name="accessibility_back">Backstring> <string name="accessibility_home">Homestring> + + <string name="accessibility_power">Powerstring> <string name="accessibility_menu">Menustring>
3.修改config文件:
diff --git a/packages/SystemUI/res/values-sw400dp/config.xml b/packages/SystemUI/res/values-sw400dp/config.xml old mode 100644 new mode 100755 index de33fb5..1a70147 --- a/packages/SystemUI/res/values-sw400dp/config.xml +++ b/packages/SystemUI/res/values-sw400dp/config.xml @@ -22,6 +22,6 @@- <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot;rightstring> + <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot,power;rightstring> diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml old mode 100644 new mode 100755 index 3c0ee9f..a434084 --- a/packages/SystemUI/res/values-sw600dp/config.xml +++ b/packages/SystemUI/res/values-sw600dp/config.xml @@ -27,7 +27,7 @@"quick_settings_user_time_settings_tile_span">1 - <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot;rightstring> + <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot,power;rightstring>"long_press_dock_anim_duration">290 diff --git a/packages/SystemUI/res/values-sw720dp/config.xml b/packages/SystemUI/res/values-sw720dp/config.xml old mode 100644 new mode 100755 index b850aef..b28e749 --- a/packages/SystemUI/res/values-sw720dp/config.xml +++ b/packages/SystemUI/res/values-sw720dp/config.xml @@ -27,6 +27,6 @@"keyguard_max_notification_count">5 - <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot;rightstring> + <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot,power;rightstring> diff --git a/packages/SystemUI/res/values-sw900dp/config.xml b/packages/SystemUI/res/values-sw900dp/config.xml old mode 100644 new mode 100755 index f957d6e..1adb097 --- a/packages/SystemUI/res/values-sw900dp/config.xml +++ b/packages/SystemUI/res/values-sw900dp/config.xml @@ -19,6 +19,6 @@- <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot;rightstring> + <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot,power;rightstring> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml old mode 100644 new mode 100755 index eedfe31..9c659ae --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -341,7 +341,7 @@ string-array> - <string name="config_navBarLayout" translatable="false">left[.5W];volume_sub,back,home,recent,volume_add,screenshot;right[.5W]string> + <string name="config_navBarLayout" translatable="false">left[.5W];volume_sub,back,home,recent,volume_add,screenshot,power;right[.5W]string> <string name="config_navBarLayoutQuickstep" translatable="false">back[1.7WC];home;contextual[1.7WC]string> <string name="config_navBarLayoutHandle" translatable="false">back[40AC];home_handle;ime_switcher[40AC]string>
二、java代码实现
1.添加按钮:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java old mode 100644 new mode 100755 index 7014673..94dd1c1 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java @@ -67,6 +67,7 @@ public class NavigationBarInflaterView extends FrameLayout public static final String SCREENSHOT = "screenshot"; public static final String VOLUME_ADD = "volume_add"; public static final String VOLUME_SUB = "volume_sub"; + public static final String POWER = "power"; public static final String GRAVITY_SEPARATOR = ";"; public static final String BUTTON_SEPARATOR = ","; @@ -405,6 +406,8 @@ public class NavigationBarInflaterView extends FrameLayout v = inflater.inflate(R.layout.volume_add, parent, false); } else if (VOLUME_SUB.equals(button)) { v = inflater.inflate(R.layout.volume_sub, parent, false); + } else if (POWER.equals(button)) { + v = inflater.inflate(R.layout.power, parent, false); } else if (button.startsWith(KEY)) { String uri = extractImage(button); int code = extractKeycode(button); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java old mode 100644 new mode 100755 index 6b4a157..1679e89 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -125,6 +125,7 @@ public class NavigationBarView extends FrameLayout implements private KeyButtonDrawable mVolumeAddIcon; private KeyButtonDrawable mVolumeSubIcon; private KeyButtonDrawable mScreenshotIcon; + private KeyButtonDrawable mPowerIcon; private EdgeBackGestureHandler mEdgeBackGestureHandler; private final DeadZone mDeadZone; @@ -335,6 +336,7 @@ public class NavigationBarView extends FrameLayout implements mButtonDispatchers.put(R.id.screenshot, new ButtonDispatcher(R.id.screenshot)); mButtonDispatchers.put(R.id.volume_add, new ButtonDispatcher(R.id.volume_add)); mButtonDispatchers.put(R.id.volume_sub, new ButtonDispatcher(R.id.volume_sub)); + mButtonDispatchers.put(R.id.power, new ButtonDispatcher(R.id.power)); mDeadZone = new DeadZone(this); mNavColorSampleMargin = getResources() @@ -491,6 +493,10 @@ public class NavigationBarView extends FrameLayout implements return mButtonDispatchers.get(R.id.volume_sub); } + public ButtonDispatcher getPowerButton() { + return mButtonDispatchers.get(R.id.power); + } + public RotationContextButton getRotateSuggestionButton() { return (RotationContextButton) mButtonDispatchers.get(R.id.rotate_suggestion); } @@ -539,6 +545,7 @@ public class NavigationBarView extends FrameLayout implements mVolumeAddIcon = getDrawable(R.drawable.ic_sysbar_volume_add_button); mVolumeSubIcon = getDrawable(R.drawable.ic_sysbar_volume_sub_button); mScreenshotIcon = getDrawable(R.drawable.ic_sysbar_capture_button); + mPowerIcon = getDrawable(R.drawable.ic_sysbar_power); } public KeyButtonDrawable getBackDrawable() { @@ -695,6 +702,7 @@ public class NavigationBarView extends FrameLayout implements getVolumeAddButton().setImageDrawable(mVolumeAddIcon); getVolumeSubButton().setImageDrawable(mVolumeSubIcon); getScreenshotButton().setImageDrawable(mScreenshotIcon); + getPowerButton().setImageDrawable(mPowerIcon); updateRecentsIcon();
2.点击按键时动作处理:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/ android/systemui/statusbar/phone/NavigationBarFragment.java old mode 100644 new mode 100755 index 95a9eda..3ef4c3a --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java @@ -1049,6 +1049,24 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback volumeAddButton.setVisibility(View.GONE); volumeSubButton.setVisibility(View.GONE); } + + ButtonDispatcher powerButton = mNavigationBarView.getPowerButton(); + powerButton.setOnClickListener(this:: powerClick); + powerButton.setOnTouchListener(this:: powerTouch); + + } + + private boolean powerTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP) { + Intent intent=new Intent("com.xzy.systemui.poweroff"); + getContext().sendBroadcast(intent); + } + return false; + } + + private void powerClick(View v) { + Intent intent=new Intent("com.xzy.systemui.poweroff"); + getContext().sendBroadcast(intent); } private boolean onHomeTouch(View v, MotionEvent event) {
点击按钮,发出关机消息的广播。
3.关机弹框的实现:
注册广播,接受到广播后弹出关机重启选择的弹框
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index d966f36..4671c2f 100755 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -2020,6 +2020,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { filter = new IntentFilter(); filter.addAction(Intent.ACTION_DREAMING_STARTED); filter.addAction(Intent.ACTION_DREAMING_STOPPED); + filter.addAction("com.xzy.systemui.poweroff"); context.registerReceiver(mDreamReceiver, filter); // register for multiuser-relevant broadcasts @@ -4494,6 +4495,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mKeyguardDelegate != null) { mKeyguardDelegate.onDreamingStopped(); } + } else if("com.xzy.systemui.poweroff".equals(intent.getAction())) { + + Slog.v(TAG, "wmc...Receive a soft poweroff broadcast."); + showGlobalActionsInternal(); } } };
showGlobalActionsInternal这个方法是调出关机弹框的。
但此时发现弹框是这样的:
经过了解,发现Android 原生的关机界面有两种,一种是LegacyGlobalActions(以上图片)中的dialog,另一种是SystemUI中的GlobalActionsDialog。
继续看弹框的代码流程:
void showGlobalActionsInternal() { if (mGlobalActions == null) { mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs); } final boolean keyguardShowing = isKeyguardShowingAndNotOccluded(); mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned()); // since it took two seconds of long press to bring this up, // poke the wake lock so they have some time to see the dialog. mPowerManager.userActivity(SystemClock.uptimeMillis(), false); }
showGlobalActionsInternal->mGlobalActions.showDialog
services/core/java/com/android/server/policy/GlobalActions.java
public void showDialog(boolean keyguardShowing, boolean deviceProvisioned) { if (DEBUG) Slog.d(TAG, "showDialog " + keyguardShowing + " " + deviceProvisioned); if (mGlobalActionsProvider != null && mGlobalActionsProvider.isGlobalActionsDisabled()) { return; } mKeyguardShowing = keyguardShowing; mDeviceProvisioned = deviceProvisioned; mShowing = true; if (mGlobalActionsAvailable && !"box".equals(SystemProperties.get("ro.target.product","unkonw"))) { mHandler.postDelayed(mShowTimeout, 5000); mGlobalActionsProvider.showGlobalActions(); } else { // SysUI isn't alive, show legacy menu. ensureLegacyCreated(); mLegacyGlobalActions.showDialog(mKeyguardShowing, mDeviceProvisioned); } }
在这里就能找到原因了,编译的系统ro.target.product不是box的,所以流程走的是mLegacyGlobalActions.showDialog,即前面调出的图片。
这样修改一下即可:
index ecd1eab..31250a9 100755 --- a/services/core/java/com/android/server/policy/GlobalActions.java +++ b/services/core/java/com/android/server/policy/GlobalActions.java @@ -65,7 +65,7 @@ class GlobalActions implements GlobalActionsProvider.GlobalActionsListener { mKeyguardShowing = keyguardShowing; mDeviceProvisioned = deviceProvisioned; mShowing = true; - if (mGlobalActionsAvailable && !"box".equals(SystemProperties.get("ro.target.product","unkonw"))) { + if (mGlobalActionsAvailable && !"tablet".equals(SystemProperties.get("ro.target.product","unkonw"))) { mHandler.postDelayed(mShowTimeout, 5000); mGlobalActionsProvider.showGlobalActions(); } else {
此时弹框图片:
参考:https://blog.csdn.net/An_Times/article/details/122043152