android - 创建新的状态栏不适用于 targetSdkVersion 30
问题描述
我需要覆盖我的一个应用程序的状态栏。
以前,当我使用targetSdkVersion
21 时,代码块运行良好,但当我切换targetSdkVersion
到 30 时,它崩溃并出现以下错误:
2021-08-16 17:50:40.920 6309-6309/myapp.com E/AndroidRuntime: FATAL EXCEPTION: main
Process: myapp.com, PID: 6309
java.lang.RuntimeException: Unable to create application myapp.com.App: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@47a3c01 -- permission denied for this window type
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6325)
at android.app.ActivityThread.access$1800(ActivityThread.java:222)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1862)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7230)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@47a3c01 -- permission denied for this window type
at android.view.ViewRootImpl.setView(ViewRootImpl.java:878)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:337)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:109)
at myapp.com.App.showCustomStatusBar(App.java:144)
at myapp.com.App.onCreate(App.java:67)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1037)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6322)
at android.app.ActivityThread.access$1800(ActivityThread.java:222)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1862)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7230)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
下面是显示状态栏的代码:
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
if(customToolbar == null) {
customToolbar = new CustomToolbar(getBaseContext());
}
int viewType;
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
getStatusBarHeight(),
// Allows the view to be on top of the StatusBar
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
// Keeps the button presses from going to the background window
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
// Enables the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.OPAQUE);
layoutParams.gravity = Gravity.TOP|Gravity.CENTER;
windowManager.addView(customToolbar, layoutParams); //Crashes on this line
我尝试使用:
int viewType;
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
viewType = WindowManager.LayoutParams.TYPE_PHONE;
} else {
viewType = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
}
代替 :
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR
但它以同样的方式崩溃。
我还添加Permissions
到清单:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
解决方案
我尝试了多个选项(WindowManager.LayoutParams.TYPE_PHONE
和WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
)WindowManager.LayoutParams.TYPE_APPLICATION_PANEL
,但它们都不起作用,所以当我WindowManager.LayoutParams.TYPE_TOAST
在我的 API 21 手机上使用时,它不再抛出错误并开始工作,但我还必须在那里进行 if 切换。
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
if(customToolbar == null) {
customToolbar = new CustomToolbar(getBaseContext());
}
int viewType;
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
viewType = WindowManager.LayoutParams.TYPE_TOAST;
} else {
viewType = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
}
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
getStatusBarHeight(),
// Allows the view to be on top of the StatusBar
viewType,
// Keeps the button presses from going to the background window
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
// Enables the notification to receive touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.OPAQUE);
layoutParams.gravity = Gravity.TOP|Gravity.CENTER;
windowManager.addView(customToolbar, layoutParams);
推荐阅读
- laravel-5 - 错误的方法调用异常 Laravel
- javascript - 如果数据单元格在 React 中有省略号,如何显示工具提示
- django - Django Channels - 无法在断开连接时发送消息
- ios - UIPickerview 选择在 Swift 中更新标签和下一个选择器视图选择
- php - 如何使用 PHP 和 MySQL 解决 FizzBuzz 问题?
- scikit-learn - np.zeros(self.shape,dtype=self.dtype,order=order)
- javascript - 仅在threejs中检测WebGL Canvas上的触摸
- python - 在python中显示不同时间的节点连接
- html - 如何在堆叠图标内居中元素
- ios - 如何打开watchos的网址