web-dev-qa-db-fra.com

Pour que la connexion à Facebook fonctionne avec une vue Web Android

J'essaie simplement d'implémenter la connexion à Facebook sur une WebView sous Android. Le problème est après que je clique sur le bouton facebook sur ma page HTML et insère le nom d'utilisateur et le mot de passe sur la boîte de dialogue Facebook. La redirection d'URL est en train de me donner une page noire.

   @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);

Il s'agit de l'API javascript normale de Facebook sur ma page HTML. Cette fonction est appelée lorsque l'utilisateur clique sur le bouton 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'});

Des idées sur la façon de récupérer la réponse après la redirection sur la page de dialogue Facebook? MERCI.

24
Adrian Avendano

J'avais le même problème sur mon application Android . La cause du problème est la connexion au FB javascript ouvre une nouvelle page dans une nouvelle fenêtre. Ensuite, il essaie de le fermer et de renvoyer des codes d'authentification javascript, une fois la connexion établie. WebView est généralement "fenêtre unique" et n'a donc aucun endroit où retourner, d'où son écran vide.

Veuillez suivre l'exemple de mes codes de travail.

<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 vue Web de l'ID "Webview" est la vue principale de mon contenu. Voici les codes de mes activités.

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 clé de ce problème est onCreateWindow. Une nouvelle fenêtre est créée et insérée dans la structure du cadre et supprimée en cas de succès. J'ai ajouté la suppression à shouldOverrideUrlLoading.

38
Ken You

Voici un exemple de projet Android: Github: Android_Popup_Webview_handler_example

Ceci est un projet Android Studio montrant comment gérer les fenêtres contextuelles dans Android Webview. La plupart des navigateurs Open Source ne prennent pas en charge l’ouverture des popups.

Les popups sont particulièrement importants dans la connexion OAuth utilisée dans de nombreux sites Web (par exemple, www.feedly.com ). Les popups de ce projet s’ouvrent dans une boîte de dialogue et peuvent être fermés par un bouton de fermeture ou en appuyant sur Retour ou si la fenêtre contextuelle se ferme (comme ce qui se passe sur la plupart des flux d’authentification de login).

3
Haider

Concernant la meilleure réponse à cette question , il vous suffit d’implémenter la méthode onPageFinished de la classe WebViewClient que vous utilisez.

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);
} 

Cela a bien fonctionné pour moi. J'espère que ça vous aide aussi :)

2
Yulian

Remplacez shouldOverrideUrlLoading() dans votre WebViewClient. Recherchez shouldOverrideUrlLoadinghere . En outre, il existe un paramètre que vous pouvez transmettre à l'API de connexion de Facebook; Je pense que c'est redirect_uri. Cela devrait vous aider à reconnaître que la connexion est réussie et que dans votre shouldOVerrideUrlLoading(), il vous suffira de détecter l’URL chargée et si c’est la redirect_uri que vous avez spécifiée, il vous suffit alors de retourner true dans cette méthode et de fermer la vue Web ou celle que vous voulez lorsque la connexion est réussie.

2
praneetloke

La réponse ci-dessus est trop ancienne et ne fonctionne pas avec la dernière version de Facebook sdk 2.7. Après avoir passé 4 heures dessus, j'ai découvert peu de changements. Le code suivant fonctionnera correctement avec le dernier SDK.

Ci-dessous, le fichier de mise en page 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>

Ceci est l'extrait de code d'activité 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");
        }

    }

}
1
Savitru

Ma réponse est essentiellement semblable à certaines autres ici, en ce sens que je crée une deuxième variable WebView pour héberger la page de connexion Facebook, plutôt que d'essayer de résoudre le problème avec les redirections. Cependant, j'ai choisi de placer l'identifiant WebView dans sa propre Fragment et de lui attribuer ses propres sous-classes dédiées WebViewClient et WebChromeClient. Je pense que cela facilite la tâche pour voir quel rôle joue chaque composant et quels objets ont besoin de quels paramètres et comportements.

J'utilise également WebChromeClient.onCloseWindow() pour détecter le moment où le code JavaScript de Facebook veut fermer la fenêtre de connexion. C'est beaucoup plus robuste que l'approche que j'avais initialement suivie, à partir d'une réponse différente.

Dans votre mise en page Activity, vous aurez la "principale" WebView, qui héberge les commentaires, ainsi qu'un conteneur pour la FacebookWebLoginFragment. Le login Fragment est créé à la volée, quand il le faut, puis supprimé lorsque JavaScript, le login de Facebook, demande à ce que sa fenêtre soit fermée.

Ma disposition Activity ressemble à ceci:

<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>

Dans votre Activity, vous aurez besoin d'un code pour afficher et masquer le fragment de connexion Web de Facebook. J'utilise le bus d'événement Otto, j'ai donc des gestionnaires d'événements comme ceux ci-dessous. (Rien ici n'est spécifique à ce problème; j'inclus ce code simplement pour vous donner une idée de la manière dont l'identifiant Fragment s'intègre dans la structure globale.)

@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();
    }
}

Tant que FacebookWebLoginFragment est présent, vous devez avoir le droit de gérer les pressions sur les boutons arrière du périphérique. Ceci est important car le flux de connexion Facebook inclut la possibilité de quitter la page de connexion et que l'utilisateur s'attend à ce que le bouton Précédent lui renvoie à la connexion. Donc, dans ma Activity, j'ai ceci:

@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();
    }
}

La mise en page de FacebookWebLoginFragment est extrêmement 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>

Voici le code FacebookWebLoginFragment. Notez qu’il s’appuie sur une sous-classe de WebChromeClient pour détecter le moment où le code de connexion Facebook est prêt à fermer la fenêtre (c’est-à-dire supprimer le fragment). Notez également qu'il n'y a pas de communication directe entre cette connexion WebView et la variable primaire WebView, qui contient l'interface utilisateur des commentaires; le jeton d'authentification est transmis via un cookie tiers. C'est pourquoi vous devez vous assurer que le support des cookies tiers est activé sur votre WebView principale.

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();
            }
        };
    }
}

Maintenant, le plus délicat est d’apporter les modifications nécessaires à votre WebView existante, car il est probable que vous disposiez déjà d’une bonne quantité de code et que vous deviez comprendre ce qui doit changer.

Tout d'abord, assurez-vous que JavaScript est activé et qu'il prend en charge plusieurs fenêtres.

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

Vous n'avez pas besoin d'appeler setJavaScriptCanOpenWindowsAutomatically(true).

En regardant certaines des autres réponses, vous pourriez penser que vous devez utiliser le paramètre WebViewClient attribué à votre WebView et remplacer le paramètre shouldOverrideUrlLoading(). Ce n'est pas nécessaire Ce qui est important, c’est la WebChromeClient, qui doit remplacer onCreateWindow().

Alors ... ensuite, affectez une sous-classe WebChromeClient personnalisée à votre 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;
    }
});

Vous remarquerez qu'il s'agit du deuxième appel à UriHelper.isFacebookHost(). Je n'ai pas d'approche à toute épreuve pour déterminer cela, mais voici ce que je fais:

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;
}

Vous remarquerez également l'appel à CookieHelper.setAcceptThirdPartyCookies(). Voici le code pour cela:

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);
    }
}

Une autre chose qui interpelle certaines personnes est la configuration de "URI de redirection OAuth valides" dans les paramètres de développement de Facebook. Si vous voyez une erreur comme celle-ci dans vos journaux:

URL bloquée: cette redirection a échoué car l’URI de redirection n’apparaît pas dans la liste blanche des paramètres OAuth client de l’application Assurez-vous que les connexions Client et Web OAuth sont activées et ajoutez tous vos domaines d'application en tant qu'URI de redirection OAuth valide.

... alors vous voudrez vérifier cette réponse: https://stackoverflow.com/a/37009374

S'amuser! Une solution compliquée à ce qui semble être un problème assez simple. Sur le plan positif, Android a donné aux développeurs une tonne de contrôle ici.

1
Mark McClelland

Essayez de déplacer votre vue Web vers un fichier de présentation XML. Cette erreur de page vierge est due à l'échec du script js lors de la redirection du login oAuth vers la page d'acceptation des autorisations. Vous pouvez résoudre ce problème en déplaçant votre vue Web dans la présentation XML.

0
Prakhs

Probablement pas une réponse toujours viable, mais une autre option consiste à basculer de la connexion OAuth de style "popup then JS" au style non popup "redirect_uri" OAUth, où il les envoie à la page de connexion, puis après succès/échec, ils sont envoyés à "quelque uri err autre" (ex: une autre page sur votre propre site web) qui complète l'authentification. FWIW.

FWIW où facebook indique "si vous exécutez WebView, redirigez-les vers https://www.facebook.com/connect/login_success.html " Mon intuition est que c’est le cas de (ne posséder qu’un seul WebView et ) en utilisant OAuth pour se connecter, afin d’ajouter quelques paramètres auth au fichier login_success.html que vous pourrez ensuite glaner, donc pas le flux Web normal ...

Une autre possibilité pourrait être de remplacer la fonction javascript postMessage afin que vous puissiez capturer ce que c'était sur le point de retourner à la fenêtre parente.

0
rogerdpack