android-popupWindow()方向更改:`android.view.WindowManager $ BadTokenException`

时间:2015-11-15 16:30:52

标签: android exception-handling android-orientation android-popupwindow

  

异常:   android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

我有一个popupWindow(),我点击一下按钮即可显示。我使用自己的方法initiatePopUpWindow(Activity)来显示弹出窗口(我从在线教程中获取代码)。我试图在orientation change上保存其状态,所以我使用布尔值popupWindowOpen来检查。但在方向改变期间,它给了我这个错误。有关如何解决此问题的任何帮助?

MainActivity.java

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    private PopupWindow pw;
    private volatile boolean popupWindowOpen = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aditi);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                initiatePopUpWindow(MainActivity.this);
            }
        });

        if(savedInstanceState != null) {
            popupWindowOpen = savedInstanceState.getBoolean("popupWindowOpen");
        }
    }

    @Override
    public void onResume() {
        super.onResume();

        if(popupWindowOpen) {
            initiatePopUpWindow(MainActivity.this);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putBoolean("popupWindowOpen", popupWindowOpen);
    }

    private void initiatePopUpWindow(final Activity context) {
        popupWindowOpen = true;

        try {
            if(!isFinishing()) {
                DisplayMetrics displayMetrics = new DisplayMetrics();
                getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
                int height = displayMetrics.heightPixels;
                int width = displayMetrics.widthPixels;
                LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                View layout = inflater.inflate(R.layout.email_popup_layout, (ViewGroup) findViewById(R.id.popup_window));
                pw = new PopupWindow(layout, (int)(1.0 * width), (int)(0.75 * height), true);
                pw.setAnimationStyle(R.anim.zoom_in);
                pw.showAtLocation(layout, Gravity.CENTER, 0, 0);

                Button click = (Button) layout.findViewById(R.id.pop_up_button);
                final EditText et = (EditText) layout.findViewById(R.id.pop_up_edittext);
                click.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                        String s = et.getText().toString();
                        popupWindowOpen = false;
                        pw.dismiss();

                        Snackbar.make(findViewById(R.id.drawer_layout), s, Snackbar.LENGTH_LONG).show();
                    }
                });
            }
            else {
                Toast.makeText(getBaseContext(), "isFinishing", Toast.LENGTH_LONG).show();
            }
        }
        catch (Exception e) {
            Snackbar.make(findViewById(R.id.drawer_layout), "Could not initiate Pop-up - " + e.toString(), Snackbar.LENGTH_INDEFINITE).show();
        }
    }
}

我该如何解决这个问题?请帮忙。 谢谢。

  

编辑:错误位于第pw.showAtLocation(layout, Gravity.CENTER, 0, 0);行。添加logcat输出

logcat output

11-15 22:30:24.188 14859-14859/com.onclavesystems.cestemoeducare E/[EGL-ERROR]: void __egl_platform_dequeue_buffer(egl_surface*):1618: failed to dequeue buffer from native window (0x77ded238); err = -19, buf = 0x0,max_allowed_dequeued_buffers 3
11-15 22:30:24.273 14859-14859/com.onclavesystems.cestemoeducare E/Qmage: onDecode : QmageDecodeFrame 20140421 Rev.6376 
11-15 22:30:24.273 14859-14859/com.onclavesystems.cestemoeducare E/Qmage: This is decoding
11-15 22:30:24.273 14859-14859/com.onclavesystems.cestemoeducare E/Qmage: decoding stream->hasLength()
11-15 22:30:24.273 14859-14859/com.onclavesystems.cestemoeducare E/Qmage: onDecode : QmageDecParseHeader call : QM
11-15 22:30:24.283 14859-14859/com.onclavesystems.cestemoeducare E/Qmage: Qmage parsing for decoding ok
11-15 22:30:24.283 14859-14859/com.onclavesystems.cestemoeducare E/Qmage: onDecode :  QmageHeader.NinePatched 0
11-15 22:30:24.283 14859-14859/com.onclavesystems.cestemoeducare E/Qmage: onDecode : QmageHeader Height() 72 Width() : 72 sampleSize : 1
11-15 22:30:24.283 14859-14859/com.onclavesystems.cestemoeducare E/Qmage: normal image decoding
11-15 22:30:24.283 14859-14859/com.onclavesystems.cestemoeducare E/Qmage: onDecode : QmageDecodeFrame call : QM
11-15 22:30:24.318 14859-14859/com.onclavesystems.cestemoeducare E/Qmage: onDecode : return true QM
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime: FATAL EXCEPTION: main
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime: Process: com.onclavesystems.cestemoeducare, PID: 14859
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime: java.lang.RuntimeException: Unable to resume activity {com.onclavesystems.cestemoeducare/com.onclavesystems.cestemoeducare.ADITI}: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3069)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3098)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2469)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4073)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread.access$1000(ActivityThread.java:172)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1314)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:146)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5653)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at java.lang.reflect.Method.invokeNative(Native Method)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:515)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at dalvik.system.NativeStart.main(Native Method)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:  Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.view.ViewRootImpl.setView(ViewRootImpl.java:771)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:278)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.widget.PopupWindow.invokePopup(PopupWindow.java:1071)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.widget.PopupWindow.showAtLocation(PopupWindow.java:895)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.widget.PopupWindow.showAtLocation(PopupWindow.java:859)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at com.onclavesystems.cestemoeducare.ADITI.initiatePopUpWindow(MainActivity.java:238)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at com.onclavesystems.cestemoeducare.ADITI.onResume(MainActivity.java:80)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1198)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.Activity.performResume(Activity.java:5618)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3059)
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3098) 
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2469) 
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4073) 
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread.access$1000(ActivityThread.java:172) 
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1314) 
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102) 
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:146) 
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5653) 
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at java.lang.reflect.Method.invokeNative(Native Method) 
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:515) 
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291) 
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107) 
11-15 22:30:24.383 14859-14859/com.onclavesystems.cestemoeducare E/AndroidRuntime:     at dalvik.system.NativeStart.main(Native Method)

第80行是pw.showAtLocation(layout, Gravity.CENTER, 0, 0);

1 个答案:

答案 0 :(得分:0)

我发现通过管理活动的配置更改而不是保存的实例状态来更容易解决这个问题。

所以在此活动的清单中:

<activity
    android:configChanges="orientation|screenSize"

然后在活动本身。不需要布尔值,(也不需要使用volatile,因为这里没有线程问题)。通过手动管理配置更改(屏幕方向更改),您每次都会阻止应用程序被销毁

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    fab = (Button) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            initiatePopUpWindow(MainActivity.this);
        }
    });


}


@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}

private void initiatePopUpWindow(final Activity context) {

    try {

            DisplayMetrics displayMetrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
            int height = displayMetrics.heightPixels;
            int width = displayMetrics.widthPixels;
            LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View layout = inflater.inflate(R.layout.email_popup_layout, (ViewGroup) null);
            pw = new PopupWindow(layout, (int)(1.0 * width), (int)(0.75 * height), true);

            pw.showAtLocation(layout, Gravity.CENTER, 0, 0);

            Button click = (Button) layout.findViewById(R.id.pop_up_button);
            final EditText et = (EditText) layout.findViewById(R.id.pop_up_edittext);
            click.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    String s = et.getText().toString();
                    pw.dismiss();

                    Toast.makeText(getBaseContext(), "Dismissed", Toast.LENGTH_LONG).show();
                }
            });


    }
    catch (Exception e) {
    Toast.makeText(getBaseContext(), e.toString(), Toast.LENGTH_LONG).show();
    }
}

无需担心已保存的实例状态,检查布尔值或管理您的onresume。