创建新的状态栏不适用于 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_PHONEWindowManager.LayoutParams.TYPE_SYSTEM_ALERTWindowManager.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

状态栏不适用于错误的 headerShown

透明状态栏不适用于 windowTranslucentNavigation="false"

反应本机状态栏不适用于android中的反应导航

React Native StatusBar:黑暗内容不适用于android

自动完成功能不适用于新的 SWIFT 文件/类