一、配置文件准备:
1.准备一张power按钮的图片:
Android11和以往又有不同,不再是用png格式的图片,用的是矢量图。可以阿里巴巴矢量图库里面招图片,再用as转成xml文件,内容如下:
packages/SystemUI/res/drawable/ic_sysbar_power.xml
<?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2018 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <vector android:height="24dp" android:viewportHeight="1024" android:viewportWidth="1024" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillColor="#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"/> <path android:fillColor="#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"/> </vector>
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"?> +<!-- Copyright (C) 2016 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<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">Back</string> <!-- Content description of the home button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_home">Home</string> + <!-- Content description of the power button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_power">Power</string> <!-- Content description of the menu button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_menu">Menu</string> <!-- Content description of the accessibility button in the navigation bar (not shown on the screen). [CHAR LIMIT=NONE] -->
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 @@ <resources> <!-- Nav bar button default ordering/layout --> - <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot;right</string> + <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot,power;right</string> </resources> 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 @@ <integer name="quick_settings_user_time_settings_tile_span">1</integer> <!-- Nav bar button default ordering/layout --> - <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot;right</string> + <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot,power;right</string> <!-- Animation duration when using long press on recents to dock --> <integer name="long_press_dock_anim_duration">290</integer> 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 @@ <integer name="keyguard_max_notification_count">5</integer> <!-- Nav bar button default ordering/layout --> - <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot;right</string> + <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot,power;right</string> </resources> 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 @@ <resources> <!-- Nav bar button default ordering/layout --> - <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot;right</string> + <string name="config_navBarLayout" translatable="false">left;volume_sub,back,home,recent,volume_add,screenshot,power;right</string> </resources> 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> <!-- Nav bar button default ordering/layout --> - <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