需求:关机和重启按钮点击后,去掉正在关机的动画和tips,改为一张图片实现。
修改点
修改点如下:
涉及到的修改文件
修改:
\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\globalactionsGlobalActionsDialogLite.java
新增:
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\layout\dialog_fullscreen_tip.xml
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\layout-land\dialog_fullscreen_tip.xml
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\drawable-xxhdpi\reboot_fullscreen_port_bg.png
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\drawable-xxhdpi\reboot_fullscreen_land_bg.png
备注:drawable 中的reboot_fullscreen_port_bg.png reboot_fullscreen_land_bg.png 图片以客户提供的横竖屏图片为准
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
实现效果如下
mtk Android12 关机、重启 全屏图片显示
代码分析
找到关机相关内容 ->->关机的实际操作位置:ShutDownAction
@VisibleForTesting
final class ShutDownAction extends SinglePressAction implements LongPressAction {
ShutDownAction() {
super(R.drawable.ic_lock_power_off,
R.string.global_action_power_off);
}
@Override
public boolean onLongPress() {
mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_LONG_PRESS);
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
// (true);
return true;
}
return false;
}
@Override
public boolean showDuringKeyguard() {
return true;
}
@Override
public boolean showBeforeProvisioning() {
return true;
}
@Override
public void onPress() {
mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_PRESS);
// shutdown by making sure radio and power are handled accordingly.
mWindowManagerFuncs.shutdown();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
往里层追代码,如下:
- onLongPress()-》 (true); 暂不分析,安全模式逻辑去了
- onPress()->()->
GlobalActionsComponent shutdown() ->Service shutdown 关机流程
-> -> reboot方法
retoot 相关源码如下:
/**
* Allows the status bar to reboot the device.
*/
@Override
public void reboot(boolean safeMode) {
enforceStatusBarService();
String reason = safeMode
? PowerManager.REBOOT_SAFE_MODE
: PowerManager.SHUTDOWN_USER_REQUESTED;
ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
final long identity = Binder.clearCallingIdentity();
try {
mNotificationDelegate.prepareForPossibleShutdown();
mHandler.post(() -> {
// ShutdownThread displays UI, so give it a UI context.
if (safeMode) {
ShutdownThread.rebootSafeMode(getUiContext(), true);
} else {
ShutdownThread.reboot(getUiContext(), reason, false);
}
});
} finally {
Binder.restoreCallingIdentity(identity);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
-> ->reboot方法
/**
* Request a clean shutdown, waiting for subsystems to clean up their
* state etc. Must be called from a Looper thread in which its UI
* is shown.
*
* @param context Context used to display the shutdown progress dialog. This must be a context
* suitable for displaying UI (aka Themable).
* @param reason code to pass to the kernel (. "recovery"), or null.
* @param confirm true if user confirmation is needed before shutting down.
*/
public static void reboot(final Context context, String reason, boolean confirm) {
mReboot = true;
mRebootSafeMode = false;
mRebootHasProgressBar = false;
mReason = reason;
shutdownInner(context, confirm);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
往外层追
- createActionItems() 方法
mPowerItems.add(shutdownAction);
mPowerItems.add(restartAction);
- 1
- 2
- mPowerItems 对应的adapter MyPowerOptionsAdapter
MyPowerOptionsAdapter 对应item 点击事件:view.setOnClickListener(v -> onClickItem(position));
private void onClickItem(int position) {
Action item = getItem(position);
if (!(item instanceof SilentModeTriStateAction)) {
if (mDialog != null) {
mDialog.dismiss();
} else {
Log.w(TAG, "Action clicked while mDialog is null.");
}
item.onPress();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 分析2中的 (); 和 ();方法
对于:mDialog.dismiss()
@Override
public void dismiss() {
dismissWithAnimation(() -> {
dismissInternal();
});
}
protected void dismissInternal() {
mContainer.setTranslationX(0);
ObjectAnimator alphaAnimator =
ObjectAnimator.ofFloat(mContainer, "alpha", 1f, 0f);
alphaAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
alphaAnimator.setDuration(233);
alphaAnimator.addUpdateListener((animation) -> {
float animatedValue = 1f - animation.getAnimatedFraction();
int alpha = (int) (animatedValue * mScrimAlpha * 255);
mBackgroundDrawable.setAlpha(alpha);
});
float xOffset = mGlobalActionsLayout.getAnimationOffsetX();
ObjectAnimator xAnimator =
ObjectAnimator.ofFloat(mContainer, "translationX", 0f, xOffset);
xAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
xAnimator.setDuration(350);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(alphaAnimator, xAnimator);
animatorSet.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
completeDismiss();
}
});
animatorSet.start();
// close first, as popup windows will not fade during the animation
dismissOverflow(false);
dismissPowerOptions(false);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
上面代码分析可以看出,关机其实就是执行了一个动画旋转进度条,如果弹出一个全屏界面,那么去掉这个动画,或者弹出一个全屏Dialog 出来,正好覆盖当前显示的进度条的dialog 。
();
item 就是上面分析的 view集合mPowerItems的子元素,这里是:shutdownAction
- 1
- 2
final class ShutDownAction extends SinglePressAction implements LongPressAction {
ShutDownAction() {
super(R.drawable.ic_lock_power_off,
R.string.global_action_power_off);
}
@Override
public boolean onLongPress() {
mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_LONG_PRESS);
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
mWindowManagerFuncs.reboot(true);
return true;
}
return false;
}
@Override
public boolean showDuringKeyguard() {
return true;
}
@Override
public boolean showBeforeProvisioning() {
return true;
}
@Override
public void onPress() {
mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_PRESS);
// shutdown by making sure radio and power are handled accordingly.
Log.d(MYTAG,"ShutDownAction onPress:");
mWindowManagerFuncs.shutdown();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
代码看出,这里 onPress 方法调用的是 ();-》回到了 前面往底层追的部分流程。
总结
总结:从上面分析流程可以看到,实现点击关机【重启一样的逻辑】,弹出一个界面的需求,实现方式:
1)去掉关机、重启的dialog的 dismiss方法,();【也可以不去,全屏界面会盖住】
2)在关闭实现全屏界面,这里用全屏dialog 实现。
//();
Dialog fullScreenDialog = new Dialog(mContext); // context是你的Activity或者其他Context
fullScreenDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置没有标题
fullScreenDialog.setContentView(com.android.systemui.R.layout.dialog_fullscreen_tip); // 设置你的布局文件
fullScreenDialog.setCancelable(false); // 设置是否可以通过点击背景取消Dialog
// 设置全屏
Window window = fullScreenDialog.getWindow();
if (window != null) {
window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY);
//(.FLAG_ALT_FOCUSABLE_IM);
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); // 设置背景透明
}
fullScreenDialog.show(); // 显示Dialog
//wangfangchen end
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
所有修改内容资源源码链接地址
Android CodeSearch
关机流程参考一
Android12 关机 重启参考流程二
Android关机流程参考三