sociales redes personalizado example developers compartir boton javascript android facebook webview

javascript - redes - Hacer que el inicio de sesión de Facebook funcione con una vista web de Android



facebook developers (8)

Solo intento implementar el inicio de sesión de Facebook en un WebView en Android. El problema es después de hacer clic en el botón de Facebook en mi página HTML e insertar el nombre de usuario y la contraseña en el cuadro de diálogo de Facebook. La redirección de URL me está dando una página en negro.

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WebView webview = new WebView(this); webview.setWebChromeClient(new WebChromeClient()); webview.getSettings().setPluginState(PluginState.ON); webview.getSettings().setJavaScriptEnabled(true); webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); webview.setWebViewClient(new WebViewClient()); webview.loadUrl("http://peoplehunt.crowdscanner.com/hunt"); setContentView(webview);

Esta es la API de JavaScript regular de Facebook en mi página HTML y se llama a esta función cuando se hace clic en el botón de Facebook.

$("#login_facebook").click(function() { FB.login(function(response) { //This function should be called if (response.authResponse) { FB.api(''/me?fields=name,email,picture,id&type=large'', function(response) { //console.log("email "+response.email); $("#submitHandle").hide(); $("#loader").show(); //console.log(''Good to see you, '' + response.picture + ''.''); var theUsername = response.name; theUsername = theUsername.replace(/ /g, ''_'')+"_"+response.id+"@meetforeal.com"; //console.log(theUsername); $("input[name=email]").val(encodeURIComponent(response.email)); $("input[name=lastName]").val(encodeURIComponent(response.name)); $("input[name=avatarImage]").val(response.picture); $("input[name=userName]").val(encodeURIComponent(theUsername)); $("#msg_twitter").fadeIn("slow"); $("#submitHandle").show(); $("#loader").hide(); $("#user").attr("action","/crowdmodule/auth/registerattendeefacebook"); $("#user").submit(); }); } else { //console.log(''User cancelled login or did not fully authorize.''); } }, {scope: ''email''});

¿CUALQUIER idea sobre cómo recuperar la respuesta después de la redirección en la página de diálogo de Facebook? GRACIAS.


Aquí hay un ejemplo de proyecto de Android: Github: Android_Popup_Webview_handler_example

Este es un proyecto de Android Studio que muestra cómo manejar las ventanas emergentes en Android Webview. La mayoría de los navegadores de código abierto no admiten abrir ventanas emergentes.

Las ventanas emergentes son especialmente importantes en el inicio de sesión de OAuth utilizado en muchos sitios web (por ejemplo, www.feedly.com ). Las ventanas emergentes de este proyecto se abren en un cuadro de diálogo y se pueden descartar con un botón de cierre o presionando Atrás o si la ventana emergente se cierra sola (como sucede con la mayoría del flujo de autenticación de inicio de sesión).


Con respecto a la mejor respuesta a esta pregunta , solo necesita implementar el método onPageFinished de la clase WebViewClient que utiliza.

public void onPageFinished(WebView view, String url) { // First, get the URL that Facebook''s login button is actually redirecting you to. // It should be something simulator to https://www.facebook.com/dialog/return/arbiter?relation=opener&close=true String webUrl = webView.getUrl(); // Pass it to the LogCat so that you can then use it in the if statement below. Log.d.println(TAG, webUrl); if (url.startsWith("The url that you copied from the LogCat")) { // Check whether the current URL is the URL that Facebook''s redirecting you to. // If it is - that''s it - do what you want to after the logging process has finished. return; } super.onPageFinished(view, url); }

Funcionó muy bien para mí. Espero que te ayude también :)


Intenta mover tu vista web a un archivo de diseño xml. El error de la página en blanco se debió a un error en el script js al redirigir el inicio de sesión de oAuth a la página de aceptación de autorización. Puede solucionar este problema moviendo su vista web al formato xml.


La respuesta anterior es demasiado antigua y no funciona con la última versión de SDK de Facebook 2.7. Después de pasar 4 horas en él, he descubierto algunos cambios en él. El siguiente código funcionará bien con el último SDK.

A continuación se menciona el archivo de diseño XML.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#0099cc" tools:context=".MainActivity" android:id="@+id/webview_frame"> <WebView android:id="@+id/webView" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </FrameLayout>

Este es el fragmento de código de actividad de Android

public class MainActivity extends AppCompatActivity { private WebView webView; private WebView mWebviewPop; private FrameLayout mContainer; private Context mContext; private String url = "https://www.YourWebsiteAddress.com"; private String target_url_prefix = "www.YourWebsiteAddress.com"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Get outer container mContainer = (FrameLayout) findViewById(R.id.webview_frame); webView = (WebView)findViewById(R.id.webView); WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setDomStorageEnabled(true); webSettings.setAppCacheEnabled(true); webSettings.setJavaScriptCanOpenWindowsAutomatically(true); webSettings.setSupportMultipleWindows(true); //These two lines are specific for my need. These are not necessary if (Build.VERSION.SDK_INT >= 21) { webSettings.setMixedContentMode( WebSettings.MIXED_CONTENT_ALWAYS_ALLOW ); } //Cookie manager for the webview CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); webView.setWebViewClient(new MyCustomWebViewClient()); webView.setWebChromeClient(new UriWebChromeClient()); webView.loadUrl("https://www.YourWebsiteAddress.com"); mContext=this.getApplicationContext(); } @Override public void onBackPressed() { if(webView.isFocused() && webView.canGoBack()) { webView.goBack(); } else { super.onBackPressed(); } } private class MyCustomWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { String host = Uri.parse(url).getHost(); if( url.startsWith("http:") || url.startsWith("https:") ) { if(Uri.parse(url).getPath().equals("/connection-compte.html")) { Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.YourWebsiteAddress.com")); startActivity(browserIntent); return true ; } if (host.equals(target_url_prefix)) { if (mWebviewPop != null) { mWebviewPop.setVisibility(View.GONE); mContainer.removeView(mWebviewPop); mWebviewPop = null; } return false; } if (host.equals("m.facebook.com") || host.equals("www.facebook.com") || host.equals("facebook.com")) { return false; } // Otherwise, the link is not for a page on my site, so launch // another Activity that handles URLs Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); return true; } // Otherwise allow the OS to handle it else if (url.startsWith("tel:")) { Intent tel = new Intent(Intent.ACTION_DIAL, Uri.parse(url)); startActivity(tel); return true; } //This is again specific for my website else if (url.startsWith("mailto:")) { Intent mail = new Intent(Intent.ACTION_SEND); mail.setType("application/octet-stream"); String AdressMail = new String(url.replace("mailto:" , "")) ; mail.putExtra(Intent.EXTRA_EMAIL, new String[]{ AdressMail }); mail.putExtra(Intent.EXTRA_SUBJECT, ""); mail.putExtra(Intent.EXTRA_TEXT, ""); startActivity(mail); return true; } return true; } @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { Log.d("onReceivedSslError", "onReceivedSslError"); //super.onReceivedSslError(view, handler, error); } @Override public void onPageFinished(WebView view, String url) { if(url.startsWith("https://m.facebook.com/v2.7/dialog/oauth")){ if(mWebviewPop!=null) { mWebviewPop.setVisibility(View.GONE); mContainer.removeView(mWebviewPop); mWebviewPop=null; } view.loadUrl("https://www.YourWebsiteAddress.com"); return; } super.onPageFinished(view, url); } } private class UriWebChromeClient extends WebChromeClient { @Override public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) { mWebviewPop = new WebView(mContext); mWebviewPop.setVerticalScrollBarEnabled(false); mWebviewPop.setHorizontalScrollBarEnabled(false); mWebviewPop.setWebViewClient(new MyCustomWebViewClient()); mWebviewPop.getSettings().setJavaScriptEnabled(true); mWebviewPop.getSettings().setSavePassword(false); mWebviewPop.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); mContainer.addView(mWebviewPop); WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; transport.setWebView(mWebviewPop); resultMsg.sendToTarget(); return true; } @Override public void onCloseWindow(WebView window) { Log.d("onCloseWindow", "called"); } } }


Mi respuesta es esencialmente similar a otras aquí, ya que creo un segundo WebView para alojar la página de inicio de sesión de Facebook, en lugar de intentar resolver el problema con redirecciones. Sin embargo, elegí ubicar el WebView inicio de sesión en su propio Fragment , y le doy sus propias WebViewClient dedicadas WebViewClient y WebChromeClient . Creo que esto hace que sea un poco más fácil ver qué papel desempeña cada componente y qué objetos necesitan qué configuraciones y comportamientos.

También utilizo WebChromeClient.onCloseWindow() para detectar cuando el JavaScript de Facebook quiere cerrar la ventana de inicio de sesión. Esto es mucho más sólido que el enfoque que originalmente perseguía, desde una respuesta diferente.

En el diseño de su Activity , tendrá el WebView "principal", que aloja los comentarios, y un contenedor para FacebookWebLoginFragment . El Fragment inicio de sesión se crea sobre la marcha, cuando es necesario, y luego se elimina cuando JavaScript de inicio de sesión de Facebook solicita que se cierre su ventana.

El diseño de Mi Activity tiene este aspecto:

<include layout="@layout/toolbar_common" /> <FrameLayout android:id="@+id/main_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/web_view_fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" android:overScrollMode="never" /> <!-- Used for Facebook login associated with comments --> <FrameLayout android:id="@+id/facebook_web_login_fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" android:overScrollMode="never" android:visibility="gone" /> </FrameLayout>

Dentro de su Activity , necesitará un código para mostrar y ocultar el fragmento de inicio de sesión web de Facebook. Uso el bus de eventos Otto, así que tengo controladores de eventos como los que se muestran a continuación. (Aquí nada es específico de este problema, incluyo este código solo para darle una idea de cómo encaja el Fragment inicio de sesión en la estructura general).

@Subscribe public void onShowFacebookWebLoginEvent(ShowFacebookWebLoginEvent event) { FacebookWebLoginFragment existingFragment = getFacebookWebLoginFragment(); if (existingFragment == null) { mFacebookWebLoginFragmentContainer.setVisibility(View.VISIBLE); createFacebookWebLoginFragment(event); } } @Subscribe public void onHideFacebookWebLoginEvent(HideFacebookWebLoginEvent event) { FacebookWebLoginFragment existingFragment = getFacebookWebLoginFragment(); if (existingFragment != null) { mFacebookWebLoginFragmentContainer.setVisibility(View.GONE); FragmentManager fm = getSupportFragmentManager(); fm.beginTransaction() .remove(existingFragment) .commit(); } } @Nullable private FacebookWebLoginFragment getFacebookWebLoginFragment() { FragmentManager fm = getSupportFragmentManager(); return (FacebookWebLoginFragment) fm.findFragmentById(R.id.facebook_web_login_fragment_container); } private void createFacebookWebLoginFragment(ShowFacebookWebLoginEvent event) { FragmentManager fm = getSupportFragmentManager(); FacebookWebLoginFragment fragment = (FacebookWebLoginFragment) fm.findFragmentById(R.id.facebook_web_login_fragment_container); if (fragment == null) { fragment = FacebookWebLoginFragment.newInstance(event.getOnCreateWindowResultMessage()); fm.beginTransaction() .add(R.id.facebook_web_login_fragment_container, fragment) .commit(); } }

Mientras el FacebookWebLoginFragment esté cerca, se le debe dar autoridad para manejar las pulsaciones de los botones del dispositivo. Esto es importante porque el flujo de inicio de sesión de Facebook incluye la capacidad de navegar fuera de la página de inicio de sesión, y el usuario esperará que el botón Atrás los devuelva para iniciar sesión. Entonces, en mi Activity , tengo esto:

@Override public void onBackPressed() { boolean handled = false; FacebookWebLoginFragment facebookWebLoginFragment = getFacebookWebLoginFragment(); if (facebookWebLoginFragment != null) { handled = facebookWebLoginFragment.onBackPressed(); } if (!handled) { WebViewFragment fragment = getWebViewFragment(); if (fragment != null) { handled = fragment.onBackPressed(); } } if (!handled) { finish(); } }

El diseño de FacebookWebLoginFragment es extremadamente simple:

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/web_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>

Aquí está el código FacebookWebLoginFragment . Tenga en cuenta que se basa en una subclase de WebChromeClient para detectar cuando el JavaScript de inicio de sesión de Facebook está listo para cerrar la ventana (es decir, eliminar el fragmento). Tenga en cuenta también que no hay comunicación directa entre este WebView inicio de sesión y WebView principal, que contiene la interfaz de usuario de comentarios; el token de autenticación se transfiere a través de una cookie de un tercero, por lo que debe asegurarse de habilitar el soporte de cookies de terceros en su WebView principal.

import android.graphics.Bitmap; import android.net.Uri; import android.net.http.SslError; import android.os.Bundle; import android.os.Message; import android.support.annotation.Nullable; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.webkit.SslErrorHandler; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.FrameLayout; import butterknife.Bind; import butterknife.ButterKnife; /** * Hosts WebView used by Facebook web login. */ public class FacebookWebLoginFragment extends BaseFragment { private static final String LOGTAG = LogHelper.getLogTag(FacebookWebLoginFragment.class); @Bind(R.id.web_view) WebView mFacebookLoginWebView; private WebChromeClient mFacebookLoginWebChromeClient; private Message onCreateWindowResultMessage; public static FacebookWebLoginFragment newInstance(Message onCreateWindowResultMessage) { FacebookWebLoginFragment fragment = new FacebookWebLoginFragment(); fragment.onCreateWindowResultMessage = onCreateWindowResultMessage; return fragment; } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.frag_facebook_web_login, container, false); ButterKnife.bind(this, rootView); return rootView; } @Override public void onViewCreated(View v, @Nullable Bundle savedInstanceState) { super.onViewCreated(v, savedInstanceState); mFacebookLoginWebView.setVerticalScrollBarEnabled(false); mFacebookLoginWebView.setHorizontalScrollBarEnabled(false); mFacebookLoginWebView.setWebViewClient(new FacebookLoginWebViewClient()); mFacebookLoginWebView.getSettings().setJavaScriptEnabled(true); mFacebookLoginWebView.getSettings().setSavePassword(false); mFacebookLoginWebView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); mFacebookLoginWebChromeClient = makeFacebookLoginWebChromeClient(); mFacebookLoginWebView.setWebChromeClient(mFacebookLoginWebChromeClient); WebView.WebViewTransport transport = (WebView.WebViewTransport) onCreateWindowResultMessage.obj; transport.setWebView(mFacebookLoginWebView); onCreateWindowResultMessage.sendToTarget(); onCreateWindowResultMessage = null; // This seems to eliminate a mysterious crash } @Override public void onDestroy() { mFacebookLoginWebChromeClient = null; super.onDestroy(); } /** * Performs fragment-specific behavior for back button, and returns true if the back press * has been fully handled. */ public boolean onBackPressed() { if (mFacebookLoginWebView.canGoBack()) { mFacebookLoginWebView.goBack(); } else { closeThisFragment(); } return true; } private void closeThisFragment() { EventBusHelper.post(new HideFacebookWebLoginEvent()); } class FacebookLoginWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // Only allow content from Facebook Uri uri = Uri.parse(url); String scheme = uri.getScheme(); if (scheme != null && (TextUtils.equals(scheme, "http") || TextUtils.equals(scheme, "https"))) { if (UriHelper.isFacebookHost(uri)) { return false; } } return true; } } private WebChromeClient makeFacebookLoginWebChromeClient() { return new WebChromeClient() { @Override public void onCloseWindow(WebView window) { closeThisFragment(); } }; } }

Ahora, la parte más difícil es hacer los cambios necesarios para su WebView existente, ya que es probable que ya tenga una buena cantidad de código en su lugar, y tendrá que darle sentido a lo que debe cambiar.

En primer lugar, asegúrese de tener habilitado JavaScript y de que admite varias ventanas.

WebSettings webSettings = mWebView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setSupportMultipleWindows(true);

No necesita llamar a setJavaScriptCanOpenWindowsAutomatically(true) .

En cuanto a algunas de las otras respuestas, puede pensar que necesita WebViewClient el WebViewClient que está asignado a su WebView , y anular shouldOverrideUrlLoading() . Esto no es necesario. Lo que es importante es WebChromeClient , que debe reemplazar onCreateWindow() .

Entonces ... a continuación, asigne una subclase WebChromeClient personalizada a su WebView :

mWebView.setWebChromeClient(new WebChromeClient() { @Override public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) { String url = null; Message href = view.getHandler().obtainMessage(); if (href != null) { view.requestFocusNodeHref(href); url = href.getData().getString("url"); } LogHelper.d(LOGTAG, "onCreateWindow: " + url); // Unfortunately, url is null when "Log In to Post" button is pressed if (url == null || UriHelper.isFacebookHost(Uri.parse(url))) { // Facebook login requires cookies to be enabled, and on more recent versions // of Android, it''s also necessary to enable acceptance of 3rd-party cookies // on the WebView that hosts Facebook comments CookieHelper.setAcceptThirdPartyCookies(mWebView, true); EventBusHelper.post(new ShowFacebookWebLoginEvent(resultMsg)); } else { LogHelper.d(LOGTAG, "Ignoring request from js to open new window for URL: " + url); } return true; } });

Notarás que esta es la segunda llamada a UriHelper.isFacebookHost() . No tengo un enfoque a prueba de balas para determinar esto, pero esto es lo que hago:

public static boolean isFacebookHost(Uri uri) { if (uri != null && !TextUtils.isEmpty(uri.getHost())) { String host = uri.getHost().toLowerCase(); return host.endsWith("facebook.com") || host.endsWith("facebook.net"); } return false; }

También notará la llamada a CookieHelper.setAcceptThirdPartyCookies() . Aquí está el código para eso:

public static void setAcceptThirdPartyCookies(WebView webView, boolean accept) { CookieManager cookieManager = CookieManager.getInstance(); // This is a safeguard, in case you''ve disabled cookies elsewhere if (accept && !cookieManager.acceptCookie()) { cookieManager.setAcceptCookie(true); } if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { cookieManager.setAcceptThirdPartyCookies(webView, accept); } }

Una cosa más que hace que algunas personas se levanten es la configuración de "URI de redirección válida de OAuth" en la configuración de desarrollo de Facebook. Si ve un error como este en sus registros:

URL bloqueada: esta redirección falló debido a que el URI de redirección no está incluido en la lista blanca en la configuración de Client OAuth de la aplicación. Asegúrese de que el Inicio de sesión web de Cliente y OAuth esté activado y agregue todos los dominios de su aplicación como URI de redireccionamiento OAuth Válido.

... entonces querrá verificar esta respuesta: https://.com/a/37009374

¡Que te diviertas! Una solución complicada a lo que parece ser un problema bastante simple. En el lado positivo, Android ha dado a los desarrolladores un montón de control aquí.


Override shouldOverrideUrlLoading() en su WebViewClient . Busque shouldOverrideUrlLoading here . Además, hay un parámetro que puede pasar a la API de inicio de sesión de Facebook; Creo que es redirect_uri. Eso debería ayudarte a reconocer cuándo el inicio de sesión es exitoso y en tu shouldOVerrideUrlLoading() , solo tienes que detectar la URL que se está cargando y si es el redirect_uri que has especificado, entonces simplemente devuelve true en ese método y cierra la vista web o lo que sea querer cuando el inicio de sesión es exitoso.


Probablemente no sea una respuesta siempre viable, pero otra opción es cambiar de inicio de sesión de OAuth de estilo "popup then JS" al estilo OAUth "redirect_uri" no emergente, donde los envía a la página de inicio de sesión, luego de que se envían correctamente o no. a "algún uri err otro" (por ejemplo, otra página en su propio sitio web) que completa la autenticación. FWIW.

FWIW donde Facebook dice "si estás haciendo WebView redirigirlos a https://www.facebook.com/connect/login_success.html " mi corazonada es que eso es para el caso de (solo tener un solo WebView y) usar OAuth para inicie sesión, por lo que agregarían algunos parámetros de autenticación al login_success.html que luego podría recoger, para que no sea el flujo web normal ...

Otra posibilidad podría ser override la función javascript postMessage para que pueda capturar lo que estaba por regresar a la ventana principal.


Tuve el mismo problema en mi aplicación de Android. La causa del problema es el inicio de sesión de FB javascript abre una nueva página en una nueva ventana. Luego intenta cerrarlo y enviar algunos códigos de autenticación de javascript, luego del éxito de inicio de sesión. WebView es típicamente "solo ventana única" por lo que no tiene lugar al que volver, por lo tanto, la pantalla en blanco.

Por favor, sigue un ejemplo fluido de mis códigos de trabajo.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#0099cc" tools:context=".MyActivity" android:id="@+id/webview_frame"> <WebView android:id="@+id/webview" android:layout_width="fill_parent" android:layout_height="fill_parent" />

La vista web de id "webview" es la vista principal de mi contenido. A continuación están mis códigos de actividad.

public class MyActivity extends Activity { /* URL saved to be loaded after fb login */ private static final String target_url="http://www.example.com"; private static final String target_url_prefix="www.example.com"; private Context mContext; private WebView mWebview; private WebView mWebviewPop; private FrameLayout mContainer; private long mLastBackPressTime = 0; private Toast mToast; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_urimalo); // final View controlsView = // findViewById(R.id.fullscreen_content_controls); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); mWebview = (WebView) findViewById(R.id.webview); //mWebviewPop = (WebView) findViewById(R.id.webviewPop); mContainer = (FrameLayout) findViewById(R.id.webview_frame); WebSettings webSettings = mWebview.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setAppCacheEnabled(true); webSettings.setJavaScriptCanOpenWindowsAutomatically(true); webSettings.setSupportMultipleWindows(true); mWebview.setWebViewClient(new UriWebViewClient()); mWebview.setWebChromeClient(new UriChromeClient()); mWebview.loadUrl(target_url); mContext=this.getApplicationContext(); } private class UriWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { String host = Uri.parse(url).getHost(); //Log.d("shouldOverrideUrlLoading", url); if (host.equals(target_url_prefix)) { // This is my web site, so do not override; let my WebView load // the page if(mWebviewPop!=null) { mWebviewPop.setVisibility(View.GONE); mContainer.removeView(mWebviewPop); mWebviewPop=null; } return false; } if(host.equals("m.facebook.com")) { return false; } // Otherwise, the link is not for a page on my site, so launch // another Activity that handles URLs Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); return true; } @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { Log.d("onReceivedSslError", "onReceivedSslError"); //super.onReceivedSslError(view, handler, error); } } class UriChromeClient extends WebChromeClient { @Override public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) { mWebviewPop = new WebView(mContext); mWebviewPop.setVerticalScrollBarEnabled(false); mWebviewPop.setHorizontalScrollBarEnabled(false); mWebviewPop.setWebViewClient(new UriWebViewClient()); mWebviewPop.getSettings().setJavaScriptEnabled(true); mWebviewPop.getSettings().setSavePassword(false); mWebviewPop.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); mContainer.addView(mWebviewPop); WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; transport.setWebView(mWebviewPop); resultMsg.sendToTarget(); return true; } @Override public void onCloseWindow(WebView window) { Log.d("onCloseWindow", "called"); } } }

La clave para este problema es onCreateWindow. Se crea una nueva ventana que se inserta en el diseño del marco y se elimina cuando tiene éxito. Agregué la eliminación en shouldOverrideUrlLoading.