Android 7.1 导航栏增加按键, 关机菜单增加休眠选项

简介: Android 7.1 导航栏增加按键, 关机菜单增加休眠选项

平台


rk3288 + Android 7.1


需求说明


1. 导航栏增加电源按键, 点击后打开关机菜单
2. 关机菜单项增加休眠项, 点击后进休眠


相关文件


//修改
  modified:   frameworks/base/core/java/android/view/WindowManagerPolicy.java
  modified:   frameworks/base/core/res/res/values/config.xml
  modified:   frameworks/base/core/res/res/values/strings.xml
  modified:   frameworks/base/core/res/res/values/symbols.xml
  modified:   frameworks/base/packages/SystemUI/res/values-sw600dp/config.xml
  modified:   frameworks/base/packages/SystemUI/res/values-sw900dp/config.xml
  modified:   frameworks/base/packages/SystemUI/res/values/config.xml
  modified:   frameworks/base/packages/SystemUI/res/values/strings.xml
  modified:   frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
  modified:   frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
  modified:   frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
  modified:   frameworks/base/services/core/java/com/android/server/policy/GlobalActions.java
  modified:   frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
  modified:   frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
//新增
  frameworks/base/core/res/res/drawable/ic_sleep.xml
  frameworks/base/packages/SystemUI/res/drawable-nodpi/ic_sysbar_power.png
  frameworks/base/packages/SystemUI/res/layout/power.xml


实现


导航栏增加按键

准备好对应的图标和相关的字符:

frameworks/base/packages/SystemUI/res/drawable-nodpi/ic_sysbar_power.png

|-- frameworks/base/packages/SystemUI/res/values/strings.xml


<string name="accessibility_power" translatable="false">Power</string>


增加按键layout.

|-- frameworks/base/packages/SystemUI/res/layout/power.xml


<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"
    android:src="@drawable/ic_sysbar_power"
    systemui:keyCode="0"
    android:scaleType="center"
    android:contentDescription="@string/accessibility_power"
    android:paddingStart="@dimen/navigation_key_padding"
    android:paddingEnd="@dimen/navigation_key_padding"
    />


其中, keyCode是按键值, 若不想处理为按键, 则置为0


|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java


public static final String POWER = "power";
//加载按键
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        inflateChildren();
        clearViews();
        inflateLayout(getDefaultLayout());
    }
//默认按键
    protected String getDefaultLayout() {
        return mContext.getString(R.string.config_navBarLayout);
    }
    protected void inflateLayout(String newLayout) {
        mCurrentLayout = newLayout;
        if (newLayout == null) {
            newLayout = getDefaultLayout();
        }
        String[] sets = newLayout.split(GRAVITY_SEPARATOR, 3);
        String[] start = sets[0].split(BUTTON_SEPARATOR);
        String[] center = sets[1].split(BUTTON_SEPARATOR);
        String[] end = sets[2].split(BUTTON_SEPARATOR);
        // Inflate these in start to end order or accessibility traversal will be messed up.
        inflateButtons(start, (ViewGroup) mRot0.findViewById(R.id.ends_group), isRot0Landscape);
        inflateButtons(start, (ViewGroup) mRot90.findViewById(R.id.ends_group), !isRot0Landscape);
        LinearLayout centerLayout = (LinearLayout)mRot0.findViewById(R.id.center_group);
        mIsReverseInflateRot0 = !isRot0Landscape && !isSw600Dp() && mCurrentOrientation == Configuration.ORIENTATION_LANDSCAPE;
        if(mIsReverseInflateRot0)
            centerLayout.setOrientation(LinearLayout.VERTICAL);
        inflateButtons(center, centerLayout, isRot0Landscape);
        mIsReverseInflateRot0 = false;
        centerLayout = (LinearLayout)mRot90.findViewById(R.id.center_group);
        mIsReverseInflateRot90 = !isRot0Landscape && !isSw600Dp() && mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT;
        if(mIsReverseInflateRot90)
            centerLayout.setOrientation(LinearLayout.HORIZONTAL);
        inflateButtons(center, centerLayout, !isRot0Landscape);
        mIsReverseInflateRot90 = false;
        addGravitySpacer((LinearLayout) mRot0.findViewById(R.id.ends_group));
        addGravitySpacer((LinearLayout) mRot90.findViewById(R.id.ends_group));
        inflateButtons(end, (ViewGroup) mRot0.findViewById(R.id.ends_group), isRot0Landscape);
        inflateButtons(end, (ViewGroup) mRot90.findViewById(R.id.ends_group), !isRot0Landscape);
    }
//加入导航栏
    @Nullable
    protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape) {
        LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
        float size = extractSize(buttonSpec);
        String button = extractButton(buttonSpec);
        View v = null;
        if (HOME.equals(button)) {
            v = inflater.inflate(R.layout.home, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
        } else if (BACK.equals(button)) {
            v = inflater.inflate(R.layout.back, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
        } else if (RECENT.equals(button)) {
            v = inflater.inflate(R.layout.recent_apps, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
        } else if (SCREENSHOT.equals(button)) {
            v = inflater.inflate(R.layout.screenshot, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
//下面增加POWER按键, layout.power.xml也是在这里使用
        }else if (POWER.equals(button)) {
            v = inflater.inflate(R.layout.power, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
        } else if (VOLUME_ADD.equals(button)) {
            v = inflater.inflate(R.layout.volume_add, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
        } else if (VOLUME_SUB.equals(button)) {
            v = inflater.inflate(R.layout.volume_sub, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
        } else if (MENU_IME.equals(button)) {
            v = inflater.inflate(R.layout.menu_ime, parent, false);
        } else if (NAVSPACE.equals(button)) {
            v = inflater.inflate(R.layout.nav_key_space, parent, false);
        } else if (CLIPBOARD.equals(button)) {
            v = inflater.inflate(R.layout.clipboard, parent, false);
        } else if (button.startsWith(KEY)) {
            String uri = extractImage(button);
            int code = extractKeycode(button);
            v = inflater.inflate(R.layout.custom_key, parent, false);
            ((KeyButtonView) v).setCode(code);
            if (uri != null) {
                ((KeyButtonView) v).loadAsync(uri);
            }
        } else {
            return null;
        }
        if (size != 0) {
            ViewGroup.LayoutParams params = v.getLayoutParams();
            params.width = (int) (params.width * size);
        }
        if(mIsReverseInflateRot0 || mIsReverseInflateRot90){
            setupVerticalButton(v);
        }
        parent.addView(v);
        addToDispatchers(v);
        View lastView = landscape ? mLastLandscape : mLastPortrait;
        if (lastView != null) {
            v.setAccessibilityTraversalAfter(lastView.getId());
        }
        if (landscape) {
            mLastLandscape = v;
        } else {
            mLastPortrait = v;
        }
        return v;
    }


默认按键布局config_navBarLayout定义:


frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java:        return mContext.getString(R.string.config_navBarLayout);
  frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java:            navLayout = context.getString(R.string.config_navBarLayout);
  frameworks/base/packages/SystemUI/res/values/config.xml:    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot;menu_ime</string>
  frameworks/base/packages/SystemUI/res/values-sw600dp/config.xml:    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot;menu_ime</string>
  frameworks/base/packages/SystemUI/res/values-sw900dp/config.xml:    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot;menu_ime</string>


增加power的个改:


diff --git a/frameworks/base/packages/SystemUI/res/values-sw600dp/config.xml b/frameworks/base/packages/SystemUI/res/values-sw600dp/config.xml
old mode 100644
new mode 100755
index aa03ab2..ef41fee
--- a/frameworks/base/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/frameworks/base/packages/SystemUI/res/values-sw600dp/config.xml
@@ -34,7 +34,7 @@
     <bool name="config_keyguardUserSwitcher">true</bool>
     <!-- Nav bar button default ordering/layout -->
-    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot;menu_ime</string>
+    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot,power;menu_ime</string>
     <!-- Animation duration when using long press on recents to dock -->
     <integer name="long_press_dock_anim_duration">290</integer>
diff --git a/frameworks/base/packages/SystemUI/res/values-sw900dp/config.xml b/frameworks/base/packages/SystemUI/res/values-sw900dp/config.xml
old mode 100644
new mode 100755
index 016f7e5..c992349
--- a/frameworks/base/packages/SystemUI/res/values-sw900dp/config.xml
+++ b/frameworks/base/packages/SystemUI/res/values-sw900dp/config.xml
@@ -19,6 +19,6 @@
 <resources>
     <!-- Nav bar button default ordering/layout -->
-    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot;menu_ime</string>
+    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot,power;menu_ime</string>
 </resources>
diff --git a/frameworks/base/packages/SystemUI/res/values/config.xml b/frameworks/base/packages/SystemUI/res/values/config.xml
old mode 100644
new mode 100755
index da5f4bf..59e7161
--- a/frameworks/base/packages/SystemUI/res/values/config.xml
+++ b/frameworks/base/packages/SystemUI/res/values/config.xml
@@ -280,7 +280,7 @@
     <string name="config_systemUIFactoryComponent" translatable="false">com.android.systemui.SystemUIFactory</string>
     <!-- Nav bar button default ordering/layout -->
-    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot;menu_ime</string>
+    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot,power;menu_ime</string>
     <bool name="quick_settings_show_full_alarm">false</bool>


添加触摸事件设置按键可见:

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java


//点击处理:
  private View.OnClickListener mPowerClickListener = new View.OnClickListener(){
  public void onClick(View v){
    Intent intent = new Intent("android.intent.action.POWER_MENU");
    mContext.sendBroadcast(intent);
  }
  };
  private void prepareNavigationBarView() {
        mNavigationBarView.reorient();
        ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();
        recentsButton.setOnClickListener(mRecentsClickListener);
        recentsButton.setOnTouchListener(mRecentsPreloadOnTouchListener);
        recentsButton.setLongClickable(true);
        recentsButton.setOnLongClickListener(this::handleLongPressBackRecents);
        ButtonDispatcher backButton = mNavigationBarView.getBackButton();
        backButton.setLongClickable(true);
        backButton.setOnLongClickListener(this::handleLongPressBackRecents);
        ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
        homeButton.setOnTouchListener(mHomeActionListener);
        homeButton.setOnLongClickListener(mLongPressHomeListener);
        ButtonDispatcher screenshotButton=mNavigationBarView.getScreenshotButton();
        screenshotButton.setOnClickListener(mScreenshotClickListener);
        screenshotButton.setOnTouchListener(mScreenshotTouchListener);
        screenshotButton.setVisibility(View.VISIBLE);
        boolean isShow=Settings.System.getInt(mContext.getContentResolver(), Settings.System.SCREENSHOT_BUTTON_SHOW, 1)==1;
        if(isShow){
            screenshotButton.setVisibility(View.VISIBLE);
        }else{
            screenshotButton.setVisibility(View.GONE);
        }
//添加监听并使用按键可见.
  ButtonDispatcher powerButton=mNavigationBarView.getPowerButton();
        powerButton.setOnClickListener(mPowerClickListener);
        //powerButton.setOnTouchListener(mPowerTouchListener);
        powerButton.setVisibility(View.VISIBLE);
  ...
  }


|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java


public NavigationBarView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mDisplay = ((WindowManager) context.getSystemService(
                Context.WINDOW_SERVICE)).getDefaultDisplay();
        mVertical = false;
        mShowMenu = false;
        mGestureHelper = new NavigationBarGestureHelper(context);
        mConfiguration = new Configuration();
        mConfiguration.updateFrom(context.getResources().getConfiguration());
        updateIcons(context, Configuration.EMPTY, mConfiguration);
        mBarTransitions = new NavigationBarTransitions(this);
        mButtonDisatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
        mButtonDisatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
        mButtonDisatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
        mButtonDisatchers.put(R.id.menu, new ButtonDispatcher(R.id.menu));
        mButtonDisatchers.put(R.id.ime_switcher, new ButtonDispatcher(R.id.ime_switcher));
        mButtonDisatchers.put(R.id.screenshot, new ButtonDispatcher(R.id.screenshot));
//添加到集合.
        mButtonDisatchers.put(R.id.power, new ButtonDispatcher(R.id.power));
        mButtonDisatchers.put(R.id.volume_add, new ButtonDispatcher(R.id.volume_add));
        mButtonDisatchers.put(R.id.volume_sub, new ButtonDispatcher(R.id.volume_sub));
    }
//供外部调用
    public ButtonDispatcher getPowerButton() {
        return mButtonDisatchers.get(R.id.power);
    }


至此, 按键添加完成, 在点击后, 会发送广播 android.intent.action.POWER_MENU


效果图:


image.png


关机菜单增加休眠项

准备资源:

frameworks/base/core/res/res/drawable/ic_sleep.xml

|-- frameworks/base/core/res/res/values/strings.xml


diff --git a/frameworks/base/core/res/res/values/strings.xml b/frameworks/base/core/res/res/values/strings.xml
old mode 100644
new mode 100755
index 4172864..89d45d7
--- a/frameworks/base/core/res/res/values/strings.xml
+++ b/frameworks/base/core/res/res/values/strings.xml
@@ -496,6 +496,9 @@
     <!-- label for item that turns off power in phone options dialog -->
     <string name="global_action_power_off">Power off</string>
+       
+       <string name="global_action_sleep">Sleep</string>
     <!-- label for item that restarts phone in phone options dialog -->
     <!-- TODO: promote to separate string-->


frameworks/base/core/res/res/values/symbols.xml


diff --git a/frameworks/base/core/res/res/values/symbols.xml b/frameworks/base/core/res/res/values/symbols.xml
old mode 100644
new mode 100755
index 81d06af..02815a2
--- a/frameworks/base/core/res/res/values/symbols.xml
+++ b/frameworks/base/core/res/res/values/symbols.xml
@@ -1607,6 +1607,7 @@
   <java-symbol type="string" name="faceunlock_multiple_failures" />
   <java-symbol type="string" name="global_action_power_off" />
   <java-symbol type="string" name="global_action_restart" />
+  <java-symbol type="string" name="global_action_sleep" />
   <java-symbol type="string" name="global_actions_airplane_mode_off_status" />
   <java-symbol type="string" name="global_actions_airplane_mode_on_status" />
   <java-symbol type="string" name="global_actions_toggle_airplane_mode" />
@@ -2734,6 +2735,7 @@
   <java-symbol type="array" name="config_defaultFirstUserRestrictions" />
   <java-symbol type="drawable" name="ic_restart" />
+  <java-symbol type="drawable" name="ic_sleep" />


frameworks/base/core/res/res/values/config.xml


diff --git a/frameworks/base/core/res/res/values/config.xml b/frameworks/base/core/res/res/values/config.xml
old mode 100644
new mode 100755
index e4839d7..935110a
--- a/frameworks/base/core/res/res/values/config.xml
+++ b/frameworks/base/core/res/res/values/config.xml
@@ -2209,6 +2209,7 @@
     <string-array translatable="false" name="config_globalActionsList">
         <item>power</item>
         <item>restart</item>
+               <item>sleep</item>
         <item>bugreport</item>
         <item>users</item>
     </string-array>


删除生成中间文件:

rm -rf out/target/product/rk3288/system/framework/framework-res.apk out/target/product/rk3288/obj/APPS/framework-res_intermediates out/target/product/rk3288/obj/NOTICE_FILES/src/system/framework/framework-res.apk.txt out/target/product/rk3288/obj/PACKAGING/target_files_intermediates/rk3288-target_files-eng.anson/SYSTEM/framework/framework-res.apk out/target/common/obj/APPS/framework-res_intermediates

重新编译

mmm frameworks/base/core/res/ -j4


增加sleep接口

|-- frameworks/base/core/java/android/view/WindowManagerPolicy.java


public interface WindowManagerFuncs {
        public static final int LID_ABSENT = -1;
        public static final int LID_CLOSED = 0;
        public static final int LID_OPEN = 1;
        public static final int CAMERA_LENS_COVER_ABSENT = -1;
        public static final int CAMERA_LENS_UNCOVERED = 0;
        public static final int CAMERA_LENS_COVERED = 1;
        /**
         * Ask the window manager to re-evaluate the system UI flags.
         */
        public void reevaluateStatusBarVisibility();
        /**
         * Add a input consumer which will consume all input events going to any window below it.
         */
        public InputConsumer addInputConsumer(Looper looper,
                InputEventReceiver.Factory inputEventReceiverFactory);
        /**
         * Returns a code that describes the current state of the lid switch.
         */
        public int getLidState();
        /**
         * Lock the device now.
         */
        public void lockDeviceNow();
        /**
         * Returns a code that descripbes whether the camera lens is covered or not.
         */
        public int getCameraLensCoverState();
        /**
         * Switch the input method, to be precise, input method subtype.
         *
         * @param forwardDirection {@code true} to rotate in a forward direction.
         */
        public void switchInputMethod(boolean forwardDirection);
        public void shutdown(boolean confirm);
        public void reboot(boolean confirm);
        public void rebootSafeMode(boolean confirm);
//增加
  public void sleep();
  }


实现sleep:

|-- frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java


public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
  ...
    // Called by window manager policy.  Not exposed externally.
    @Override
    public void shutdown(boolean confirm) {
        ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
    }
    // Called by window manager policy.  Not exposed externally.
    @Override
    public void reboot(boolean confirm) {
        ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
    }
    // Called by window manager policy.  Not exposed externally.
    @Override
    public void rebootSafeMode(boolean confirm) {
        ShutdownThread.rebootSafeMode(mContext, confirm);
    }
//实现sleep, 调用PowerManager.goToSleep.
  @Override
  public void sleep(){
  mPowerManager.goToSleep(SystemClock.uptimeMillis());
  }
  ...
}


增加sleep项

|-- frameworks/base/services/core/java/com/android/server/policy/GlobalActions.java


private static final String GLOBAL_ACTION_KEY_RESTART = "restart";
//增加sleep
  private static final String GLOBAL_ACTION_KEY_SLEEP = "sleep";
    private GlobalActionsDialog createDialog() {
  ...
//从xml中加载config_globalActionsList字符数组
        mItems = new ArrayList<Action>();
        String[] defaultActions = mContext.getResources().getStringArray(
                com.android.internal.R.array.config_globalActionsList);
        ArraySet<String> addedKeys = new ArraySet<String>();
        for (int i = 0; i < defaultActions.length; i++) {
            String actionKey = defaultActions[i];
            if (addedKeys.contains(actionKey)) {
                // If we already have added this, don't add it again.
                continue;
            }
            if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {
                mItems.add(new PowerAction());
            } else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {
                mItems.add(mAirplaneModeOn);
            } else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) {
                if (Settings.Global.getInt(mContext.getContentResolver(),
                        Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner()) {
                    mItems.add(new BugReportAction());
                }
            } else if (GLOBAL_ACTION_KEY_SILENT.equals(actionKey)) {
                if (mShowSilentToggle) {
                    mItems.add(mSilentModeAction);
                }
            } else if (GLOBAL_ACTION_KEY_USERS.equals(actionKey)) {
                if (SystemProperties.getBoolean("fw.power_user_switcher", false)) {
                    addUsersToMenu(mItems);
                }
            } else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
                mItems.add(getSettingsAction());
            } else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {
                mItems.add(getLockdownAction());
            } else if (GLOBAL_ACTION_KEY_VOICEASSIST.equals(actionKey)) {
                mItems.add(getVoiceAssistAction());
            } else if (GLOBAL_ACTION_KEY_ASSIST.equals(actionKey)) {
                mItems.add(getAssistAction());
            } else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) {
                mItems.add(new RestartAction());
//创建并添加SleepAction
    } else if (GLOBAL_ACTION_KEY_SLEEP.equals(actionKey)){
    mItems.add(new SleepAction());
            } else {
                Log.e(TAG, "Invalid global action key " + actionKey);
            }
            // Add here so we don't add more than one.
            addedKeys.add(actionKey);
        }
        if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {
            mItems.add(getEmergencyAction());
        }
        mAdapter = new MyAdapter();
        AlertParams params = new AlertParams(mContext);
        params.mAdapter = mAdapter;
  ...
  }
//增加SleepAction.
  private final class SleepAction extends SinglePressAction implements LongPressAction {
        private SleepAction() {
            super(R.drawable.ic_sleep, R.string.global_action_sleep);
        }
        @Override
        public boolean onLongPress() {
            return false;
        }
        @Override
        public boolean showDuringKeyguard() {
            return true;
        }
        @Override
        public boolean showBeforeProvisioning() {
            return true;
        }
        @Override
        public void onPress() {
//调用新增sleep函数
            mWindowManagerFuncs.sleep();
        }
    }


接收从SystemUI发送过来的广播并调起GlobalActions.

|-- frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java


/** {@inheritDoc} */
    @Override
    public void init(Context context, IWindowManager windowManager,
            WindowManagerFuncs windowManagerFuncs) {
        mContext = context;
        mWindowManager = windowManager;
        mWindowManagerFuncs = windowManagerFuncs;
  ...
        // register for dream-related broadcasts
        filter = new IntentFilter();
        filter.addAction(Intent.ACTION_DREAMING_STARTED);
        filter.addAction(Intent.ACTION_DREAMING_STOPPED);
        context.registerReceiver(mDreamReceiver, filter);
        filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SHUTDOWN);
        context.registerReceiver(mShutdownanimationReceiver, filter);
        // register for multiuser-relevant broadcasts
        filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
        context.registerReceiver(mMultiuserReceiver, filter);
//注册广播监听: android.intent.action.POWER_MENU
  IntentFilter ifPower = new IntentFilter("android.intent.action.POWER_MENU");
  context.registerReceiver(new BroadcastReceiver(){
    @Override
    public void onReceive(Context context, Intent intent) {
    //show global actions dialog
    showGlobalActionsInternal();
    }
  }, ifPower);
  }


完成, 上图:

image.png

相关文章
|
6月前
|
Android开发
Android Mediatek 增加Recovery模式下读cmdline的强制工厂重置选项
Android Mediatek 增加Recovery模式下读cmdline的强制工厂重置选项
62 0
|
3月前
|
XML API Android开发
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
本文介绍了如何使用androidx.preference库快速创建具有一级和二级菜单的Android设置界面的步骤和示例代码。
125 1
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
|
5月前
|
XML Java Android开发
34. 【Android教程】菜单:Menu
34. 【Android教程】菜单:Menu
115 2
|
5月前
|
开发工具 Android开发 开发者
Android Studio中两个让初学者崩溃菜单
Android Studio中两个让初学者崩溃菜单
56 0
|
6月前
|
Android开发
定制Android关机界面
定制Android关机界面
95 0
|
6月前
|
XML Android开发 数据格式
android 12 添加菜单
android 12 添加菜单
41 0
|
6月前
|
Java Android开发 开发者
Android10 修改开发者选项中动画缩放默认值
Android10 修改开发者选项中动画缩放默认值
195 0
|
3月前
|
Java Android开发
全志 Android 11:实现响应全局按键
本文介绍了在全志平台Android 11上实现响应全局按键的方法,通过修改`TvWindowManager.java`来全局拦截特定的热键事件,并在`FocusActivity`中处理这些事件以启动调焦界面和控制步进电机调整焦距。
35 2
|
3月前
|
API Android开发
Android使用AlertDialog实现弹出菜单
本文分享了在Android开发中使用AlertDialog实现弹出菜单的方法,并通过代码示例和错误处理,展示了如何避免因资源ID找不到导致的crash问题。
67 1
|
3月前
|
API Android开发 开发者
Android经典实战之用WindowInsetsControllerCompat方便的显示和隐藏状态栏和导航栏
本文介绍 `WindowInsetsControllerCompat` 类,它是 Android 提供的一种现代化工具,用于处理窗口插入如状态栏和导航栏的显示与隐藏。此类位于 `androidx.core.view` 包中,增强了跨不同 Android 版本的兼容性。主要功能包括控制状态栏与导航栏的显示、设置系统窗口行为及调整样式。通过 Kotlin 代码示例展示了如何初始化并使用此类,以及如何设置系统栏的颜色样式。
205 2