解决7.x版本 WindowManager$BadTokenException

本文详细介绍了如何改进ToastWidget中的Toast显示逻辑,解决在Android 7.x及以上版本中出现的WindowManager$BadTokenException问题,并通过避免多次反射提高了应用的稳定性。同时,文章还提供了确保Toast正确显示的代码实现细节。
public class ToastWiget {

    private static Toast mToast;

    //解决7.x WindowManager$BadTokenException
    //避免多次反射
    private static boolean isReflectedHandler = false;

    public static void makeText(CharSequence text, int duration) {
        View v = LayoutInflater.from(Sheng.getInstance()).inflate(R.layout.toast_wiget, null);
        TextView textView = (TextView) v.findViewById(R.id.content);
        textView.setText(text);
        if (mToast == null) {
            mToast = new Toast(Sheng.getInstance());
        }

        mToast.setDuration(duration);
        mToast.setView(v);
        int sdkInt = Build.VERSION.SDK_INT;
        if (sdkInt >= Build.VERSION_CODES.N && sdkInt < Build.VERSION_CODES.O && !isReflectedHandler) {
            reflectTNHandler(mToast);
            //这里为了避免多次反射,使用一个标识来限制
            isReflectedHandler = true;
        }
        mToast.show();
        //测试重现
//        try {
//            Thread.sleep(4000);
//        } catch (InterruptedException mE) {
//            mE.printStackTrace();
//        }

    }

    public static void makeText(CharSequence text) {
        makeText(text, Toast.LENGTH_SHORT);
    }

    public void setGravity(int gravity, int xOffset, int yOffset) {
        if (mToast != null) {
            mToast.setGravity(gravity, xOffset, yOffset);
        }
    }

    //--------
    public static class SafelyHandlerWarpper extends Handler {
        private Handler impl;

        public SafelyHandlerWarpper(Handler impl) {
            this.impl = impl;
        }
        @Override
        public void dispatchMessage(Message msg){
            try {
                super.dispatchMessage(msg);
            } catch (Exception ignored) {
            }
        }
        @Override
        public void handleMessage(Message msg) {
            impl.handleMessage(msg);//需要委托给原Handler执行
        }
    }


    private static void reflectTNHandler(Toast toast) {
        try {
            Field tNField = toast.getClass().getDeclaredField("mTN");
            if (tNField == null) {
                return;
            }
            tNField.setAccessible(true);
            Object TN = tNField.get(toast);
            if (TN == null) {
                return;
            }
            Field handlerField = TN.getClass().getDeclaredField("mHandler");
            if (handlerField == null) {
                return;
            }
            handlerField.setAccessible(true);
            handlerField.set(TN, new ProxyTNHandler(TN));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private static class ProxyTNHandler extends Handler {
        private Object tnObject;
        private Method handleShowMethod;
        private Method handleHideMethod;

        ProxyTNHandler(Object tnObject) {
            this.tnObject = tnObject;
            try {
                this.handleShowMethod = tnObject.getClass().getDeclaredMethod("handleShow", IBinder.class);
                this.handleShowMethod.setAccessible(true);
                this.handleHideMethod = tnObject.getClass().getDeclaredMethod("handleHide");
                this.handleHideMethod.setAccessible(true);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0: {
                    //SHOW
                    IBinder token = (IBinder) msg.obj;
                    if (handleShowMethod != null) {
                        try {
                            handleShowMethod.invoke(tnObject, token);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        } catch (WindowManager.BadTokenException e) {
                            //显示Toast时添加BadTokenException异常捕获
                            e.printStackTrace();
                        }
                    }
                    break;
                }

                case 1: {
                    //HIDE
                    if (handleHideMethod != null) {
                        try {
                            handleHideMethod.invoke(tnObject);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                }
                case 2: {
                    //CANCEL
                    if (handleHideMethod != null) {
                        try {
                            handleHideMethod.invoke(tnObject);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                }

            }
            super.handleMessage(msg);
        }
    }
}
07-20 19:57:33.402 2248 2248 I BurialPointService1: Failed to show presentation on display: Display id 1: DisplayInfo{"内置屏幕", displayId 1, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS, FLAG_TRUSTED, real 1920 x 720, largest app 1920 x 1920, smallest app 720 x 720, appVsyncOff 1000000, presDeadline 16666666, mode 2, defaultMode 2, modes [{id=2, width=1920, height=720, fps=60.000004}], hdrCapabilities HdrCapabilities{mSupportedHdrTypes=[], mMaxLuminance=500.0, mMaxAverageLuminance=500.0, mMinLuminance=0.0}, minimalPostProcessingSupported false, rotation 0, state ON, type INTERNAL, uniqueId "local:130", app 1920 x 720, density 160 (167.013 x 167.779) dpi, layerStack 1, colorMode 0, supportedColorModes [0], address {port=130}, deviceProductInfo null, removeMode 0}, DisplayMetrics{density=1.0, width=1920, height=720, scaledDensity=1.0, xdpi=167.013, ydpi=167.779}, isValid=true 07-20 19:57:33.402 2248 2248 I BurialPointService1: android.view.WindowManager$InvalidDisplayException: Unable to add window android.view.ViewRootImpl$W@a379ee3 -- the specified display can not be found 07-20 19:57:33.402 2248 2248 I BurialPointService1: at android.view.ViewRootImpl.setView(ViewRootImpl.java:1099) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:409) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:109) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at android.app.Dialog.show(Dialog.java:342) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at android.app.Presentation.show(Presentation.java:257) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at com.adayo.aaop_deviceservice.service.BurialPointService.y(Unknown Source:48) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at com.adayo.aaop_deviceservice.service.BurialPointService.B(Unknown Source:53) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at com.adayo.aaop_deviceservice.service.BurialPointService.onCreate(Unknown Source:10) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at android.app.ActivityThread.handleCreateService(ActivityThread.java:4209) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at android.app.ActivityThread.access$1600(ActivityThread.java:238) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1955) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at android.os.Handler.dispatchMessage(Handler.java:106) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at android.os.Looper.loop(Looper.java:223) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at android.app.ActivityThread.main(ActivityThread.java:7731) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at java.lang.reflect.Method.invoke(Native Method) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 07-20 19:57:33.402 2248 2248 I BurialPointService1: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) private void createBackgroundToQnx() { int displayId = 1; DisplayManager dm = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE); Display display = dm.getDisplay(displayId); if (display == null || !display.isValid()) { Log.e(TAG, "Invalid display: " + displayId); return; } try { Context displayContext = getApplicationContext().createDisplayContext(display); Presentation presentation = new Presentation(displayContext, display); View view = new View(this); view.setBackgroundColor(Color.BLACK); presentation.setContentView(view); presentation.show(); } catch (WindowManager.InvalidDisplayException e) { Log.i(TAG, "Failed to show presentation on display: " + display, e); } }
最新发布
08-08
分析以下代码的报错信息:------------------------- PROCESS STARTED (7432) for package com.example.myapplication ---------------------------- 2025-07-09 13:27:09.041 7432-7432 e.myapplicatio com.example.myapplication W ClassLoaderContext classpath size mismatch. expected=0, found=1 (PCL[] | PCL[/data/data/com.example.myapplication/code_cache/.overlay/base.apk/classes3.dex*4250602868]) 2025-07-09 13:27:09.042 7432-7432 e.myapplicatio com.example.myapplication W Found duplicate classes, falling back to extracting from APK : /data/app/~~dh0o8WK_fXecSV_JJz78RQ==/com.example.myapplication-RE5zX8NpQzXhviy1xPMobA==/base.apk 2025-07-09 13:27:09.042 7432-7432 e.myapplicatio com.example.myapplication W NOTE: This wastes RAM and hurts startup performance. 2025-07-09 13:27:09.042 7432-7432 e.myapplicatio com.example.myapplication W Found duplicated class when checking oat files: 'Lcom/example/myapplication/ListActivity$1;' in /data/data/com.example.myapplication/code_cache/.overlay/base.apk/classes3.dex and /data/app/~~dh0o8WK_fXecSV_JJz78RQ==/com.example.myapplication-RE5zX8NpQzXhviy1xPMobA==/base.apk!classes3.dex 2025-07-09 13:27:09.172 7432-7432 NetworkSecurityConfig com.example.myapplication D No Network Security Config specified, using platform default 2025-07-09 13:27:09.173 7432-7432 NetworkSecurityConfig com.example.myapplication D No Network Security Config specified, using platform default 2025-07-09 13:27:09.201 7432-7456 libEGL com.example.myapplication D loaded /vendor/lib/egl/libEGL_emulation.so 2025-07-09 13:27:09.202 7432-7456 libEGL com.example.myapplication D loaded /vendor/lib/egl/libGLESv1_CM_emulation.so 2025-07-09 13:27:09.204 7432-7456 libEGL com.example.myapplication D loaded /vendor/lib/egl/libGLESv2_emulation.so 2025-07-09 13:27:09.246 7432-7432 AppCompatDelegate com.example.myapplication D Checking for metadata for AppLocalesMetadataHolderService : Service not found 2025-07-09 13:27:09.305 7432-7432 e.myapplicatio com.example.myapplication W Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed) 2025-07-09 13:27:09.305 7432-7432 e.myapplicatio com.example.myapplication W Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed) 2025-07-09 13:27:09.397 7432-7454 HostConnection com.example.myapplication D HostConnection::get() New Host Connection established 0xe9a68250, tid 7454 2025-07-09 13:27:09.403 7432-7454 HostConnection com.example.myapplication D HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_sync_buffer_data ANDROID_EMU_vulkan_async_qsri ANDROID_EMU_read_color_buffer_dma GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_2 2025-07-09 13:27:09.404 7432-7454 OpenGLRenderer com.example.myapplication W Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without... 2025-07-09 13:27:09.411 7432-7454 EGL_emulation com.example.myapplication D eglCreateContext: 0xe9a68170: maj 2 min 0 rcv 2 2025-07-09 13:27:09.414 7432-7454 EGL_emulation com.example.myapplication D eglMakeCurrent: 0xe9a68170: ver 2 0 (tinfo 0xe9db64d0) (first time) 2025-07-09 13:27:09.438 7432-7454 Gralloc4 com.example.myapplication I mapper 4.x is not supported 2025-07-09 13:27:09.439 7432-7454 HostConnection com.example.myapplication D createUnique: call 2025-07-09 13:27:09.439 7432-7454 HostConnection com.example.myapplication D HostConnection::get() New Host Connection established 0xe9a6acc0, tid 7454 2025-07-09 13:27:09.467 7432-7454 HostConnection com.example.myapplication D HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_sync_buffer_data ANDROID_EMU_vulkan_async_qsri ANDROID_EMU_read_color_buffer_dma GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_2 2025-07-09 13:27:10.478 7432-7432 AndroidRuntime com.example.myapplication D Shutting down VM 2025-07-09 13:27:10.479 7432-7432 AndroidRuntime com.example.myapplication E FATAL EXCEPTION: main Process: com.example.myapplication, PID: 7432 android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running? at android.view.ViewRootImpl.setView(ViewRootImpl.java:1068) at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:409) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:109) at android.app.Dialog.show(Dialog.java:340) at android.app.AlertDialog$Builder.show(AlertDialog.java:1131) at com.example.myapplication.MyBaseAdapter$1.onClick(MyBaseAdapter.java:55) at android.view.View.performClick(View.java:7448) at android.view.View.performClickInternal(View.java:7425) at android.view.View.access$3600(View.java:810) at android.view.View$PerformClick.run(View.java:28305) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7656) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 2025-07-09 13:27:10.509 7432-7432 Process com.example.myapplication I Sending signal. PID: 7432 SIG: 9 ---------------------------- PROCESS ENDED (7432) for package com.example.myapplication ----------------------------
07-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值