I have an app with PopupWindow containing WebView that opens Facebook's page, any context menu like: the Autocomplete on text fields in the WebView or even the Long Press that should display options for the user to copy/paste/cut crashes the app right away with the follow error:
FATAL EXCEPTION: main
android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRootImpl$W@418cdab0 is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:700)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:345)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149)
at android.view.Window$LocalWindowManager.addView(Window.java:554)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:1013)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:856)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:820)
at android.webkit.WebViewClassic$PastePopupWindow.show(WebViewClassic.java:971)
at android.webkit.WebViewClassic.showPasteWindow(WebViewClassic.java:7037)
at android.webkit.WebViewClassic.access$10300(WebViewClassic.java:235)
at android.webkit.WebViewClassic$PrivateHandler.handleMessage(WebViewClassic.java:11376)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4921)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
at dalvik.system.NativeStart.main(Native Method)
Notice: my understanding of the problem is that the context menu/window are shown actually in the scope of the app itself not inside the WebView using another PopWindow (Auto generated by the Core WebView Class) this class references the context incorrectly.
My Code is as follows:
Main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/openpopup"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Open Popup Window" />
</LinearLayout>
Popup.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/background_light"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="1dp"
android:background="@android:color/darker_gray"
android:orientation="vertical" >
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="20dp"
android:orientation="vertical" >
<WebView
xmlns:ptr="http://schemas.android.com/apk/res-auto"
android:id="@+id/webviewActionView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:minHeight="200dp"
android:minWidth="200dp"
android:scrollbars="none" >
</WebView>
<Button
android:id="@+id/dismiss"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Dismiss" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
MainActivity.java
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.PopupWindow;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Button btnOpenPopup = (Button) findViewById(R.id.openpopup);
btnOpenPopup.setOnClickListener(new Button.OnClickListener() {
@SuppressLint("NewApi")
@Override
public void onClick(View arg0) {
LayoutInflater layoutInflater = (LayoutInflater) getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE);
View popupView = layoutInflater.inflate(R.layout.popup, null);
final PopupWindow popupWindow = new PopupWindow(popupView,
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
popupWindow.setTouchable(true);
popupWindow.setFocusable(true);
WebView popupWebview = (WebView) popupView.findViewById(R.id.webviewActionView);
popupWebview.loadUrl("https://m.facebook.com");
Button btnDismiss = (Button) popupView
.findViewById(R.id.dismiss);
btnDismiss.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
popupWindow.dismiss();
}
});
popupWindow.showAsDropDown(btnOpenPopup, 50, -30);
}
});
}
}
As commented above in my answer you can use Custom dialog for your requirement.. i have created a sample PopupDialog.. please check and let me know..if it solve your purpose.. Autocomplete and ContextMenus will work as expected..
MyActivity.java
package com.example.testapp;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Button btnOpenPopup = (Button) findViewById(R.id.openpopup);
btnOpenPopup.setOnClickListener(new Button.OnClickListener() {
@SuppressLint("NewApi")
@Override
public void onClick(View arg0) {
final PopupDialog popupDialog = new PopupDialog(MyActivity.this);
popupDialog.setContentView(R.layout.popup);
WebView popupWebview = (WebView) popupDialog.findViewById(R.id.webviewActionView);
popupWebview.setWebChromeClient(new WebChromeClient());
popupWebview.setWebViewClient(new WebViewClient());
popupWebview.loadUrl("http://m.facebook.com");
Button btnDismiss = (Button) popupDialog
.findViewById(R.id.dismiss);
btnDismiss.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
popupDialog.dismiss();
}
});
// popupDialog.showAtLocation(50,50);
popupDialog.showAsDropDown(findViewById(R.id.openpopup));
}
});
}
}
PopupDialog.java
package com.example.testapp;
import android.app.Dialog;
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
public class PopupDialog extends Dialog{
private final Context mContext;
public PopupDialog(Context context) {
super(context);
mContext=context;
requestWindowFeature(Window.FEATURE_NO_TITLE);
}
public void showAtLocation(int x,int y)
{
WindowManager.LayoutParams wmlp = getWindow().getAttributes();
wmlp.gravity = Gravity.TOP | Gravity.LEFT;
wmlp.x = x;
wmlp.y = y;
show();
}
public void showAsDropDown(View view)
{
float density = mContext.getResources().getDisplayMetrics().density;
WindowManager.LayoutParams wmlp = getWindow().getAttributes();
int[] location = new int[2];
view.getLocationInWindow(location);
wmlp.gravity = Gravity.TOP | Gravity.LEFT;
wmlp.x = location[0]+(int)(view.getWidth()/density);
wmlp.y = location[1]+(int)(view.getHeight()/density);
show();
}
}
edit: added popup.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:minHeight="400dp"
android:minWidth="200dp"
android:background="@android:color/background_light"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="1dp"
android:background="@android:color/darker_gray"
android:orientation="vertical" >
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="20dp"
android:orientation="vertical" >
<WebView
xmlns:ptr="http://schemas.android.com/apk/res-auto"
android:id="@+id/webviewActionView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="200dp"
android:minWidth="200dp"
android:scrollbars="none" >
</WebView>
<Button
android:id="@+id/dismiss"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Dismiss" />
</LinearLayout>
</LinearLayout>
yes i think you should use your activity name in place of "getBaseContext()". i am just created one demo with your code. its working fine in my pc. and when you are getting this exception?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With