创建新的状态栏不适用于 targetSdkVersion 30
Posted
技术标签:
【中文标题】创建新的状态栏不适用于 targetSdkVersion 30【英文标题】:Creating new status bar not working with targetSdkVersion 30 【发布时间】:2021-10-20 07:20:01 【问题描述】:我需要覆盖我的一个应用程序的状态栏。
以前,当我使用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" />
【问题讨论】:
你检查了这个答案吗? - ***.com/questions/32224452/… 【参考方案1】:我尝试了多个选项(WindowManager.LayoutParams.TYPE_PHONE
、WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
和 WindowManager.LayoutParams.TYPE_APPLICATION_PANEL
),但它们都不起作用,所以当我在 API 21 手机上使用 WindowManager.LayoutParams.TYPE_TOAST
时,它不再抛出错误并开始工作,但我还必须在那里进行 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);
【讨论】:
以上是关于创建新的状态栏不适用于 targetSdkVersion 30的主要内容,如果未能解决你的问题,请参考以下文章
iOS 8:状态栏不适用于 UIImagePickerController
透明状态栏不适用于 windowTranslucentNavigation="false"