it-swarm.com.de

Facebook-Login mit einem Android-Webview aktivieren

Ich versuche gerade, das Facebook-Login in einem WebView in Android zu implementieren. Das Problem ist, nachdem ich auf meiner HTML-Seite auf die Facebook-Schaltfläche geklickt und den Benutzernamen und das Kennwort in den Facebook-Dialog eingegeben habe. Die URL-Weiterleitung gibt mir nur eine schwarze Seite.

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

Dies ist die reguläre Javascript-API von Facebook auf meiner HTML-Seite. Diese Funktion wird aufgerufen, wenn der Facebook-Button angeklickt wird.

$("#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'});

Irgendwelche Ideen, wie Sie die Antwort nach der Weiterleitung auf der Facebook-Dialogseite zurückerhalten können? VIELEN DANK.

24
Adrian Avendano

Ich hatte das gleiche Problem in meiner Android-Anwendung ... Die Ursache des Problems ist, dass der FB-Login-Javascript eine neue Seite in einem neuen Fenster öffnet. Dann versucht es, es zu schließen und einige Javascript-Authentifizierungscodes nach dem erfolgreichen Login zurückzusenden. WebView ist in der Regel "nur ein Fenster", so dass es keinen Platz gibt, zu dem Sie zurückkehren können, daher der leere Bildschirm.

Bitte folgen Sie einem fließenden Beispiel aus meinen Arbeitsregeln.

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

Die Webansicht der ID "Webview" ist die Hauptansicht für meinen Inhalt . Nachfolgend finden Sie meine Aktivitätscodes.

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

}
}

Der Schlüssel für dieses Problem ist onCreateWindow. Ein neues Fenster wird erstellt, in das Rahmenlayout eingefügt und bei Erfolg entfernt. Ich habe die Entfernung bei shouldOverrideUrlLoading hinzugefügt.

38
Ken You

Hier ein Beispiel für ein Android-Projekt: Github: Android_Popup_Webview_handler_example

Dies ist ein Android Studio-Projekt, das zeigt, wie Popups in Android Webview behandelt werden. Die meisten Open Source-Browser unterstützen das Öffnen von Popups nicht.

Popups sind besonders wichtig beim OAuth-Login, das auf vielen Websites verwendet wird (z. B. www.feedly.com ). Die Popup-Fenster in diesem Projekt wurden in einem Dialogfeld geöffnet und können mit einer Schließen-Schaltfläche oder durch Drücken von Zurück oder durch Schließen des Popup-Fensters (wie bei den meisten Anmeldeversuchen) geschlossen werden.

3
Haider

In Bezug auf die beste Antwort auf diese Frage müssen Sie nur die onPageFinished-Methode der verwendeten WebViewClient-Klasse implementieren.

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

Es hat gut für mich funktioniert. Hoffe es hilft dir auch :)

2
Yulian

Überschreiben Sie shouldOverrideUrlLoading() in Ihrer WebViewClient. Suchen Sie nach shouldOverrideUrlLoadinghier . Es gibt auch einen Parameter, den Sie an die Login-API von Facebook übergeben können. Ich denke es ist redirect_uri. Dies sollte Ihnen dabei helfen, zu erkennen, wann die Anmeldung erfolgreich ist und Sie in Ihrer shouldOVerrideUrlLoading() nur die geladene URL erkennen müssen. Wenn es sich um die angegebene Weiterleitung handelt, geben Sie in dieser Methode true zurück und schließen Sie die Webansicht oder was immer Sie möchten wenn der Login erfolgreich ist.

2
praneetloke

Die obige Antwort ist zu alt und funktioniert nicht mit der neuesten Facebook-SDK-Version 2.7. Nachdem ich 4 Stunden damit verbracht hatte, habe ich einige Änderungen daran herausgefunden. Der folgende Code funktioniert gut mit dem neuesten SDK.

Unten ist die XML-Layoutdatei aufgeführt.

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

Dies ist der Android-Aktivitätscode-Ausschnitt

    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

Meine Antwort ist im Wesentlichen ähnlich wie bei anderen hier, da ich eine zweite WebView zum Hosten der Facebook-Anmeldeseite erstelle, anstatt zu versuchen, das Problem mit Weiterleitungen zu lösen. Ich entschied mich jedoch dafür, das Login WebView in seine eigene Fragment zu setzen, und gebe ihm eigene dedizierte WebViewClient- und WebChromeClient-Unterklassen. Ich denke, das macht es ein bisschen einfacher zu sehen, welche Rolle jede Komponente spielt und welche Objekte welche Einstellungen und Verhaltensweisen benötigen.

Ich nutze WebChromeClient.onCloseWindow() auch, um herauszufinden, wann das JavaScript von Facebook das Anmeldefenster schließen möchte. Dies ist viel robuster als der Ansatz, den ich ursprünglich verfolgte, aus einer anderen Antwort.

In Ihrem Activity-Layout haben Sie die "primäre" WebView, die die Kommentare hostet, und einen Container für die FacebookWebLoginFragment. Das Login Fragment wird bei Bedarf im laufenden Betrieb erstellt und dann entfernt, wenn das Login-JavaScript von Facebook das Schließen des Fensters anfordert.

Mein Activity-Layout sieht folgendermaßen aus:

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

In Ihrer Activity benötigen Sie Code, um das Facebook-Web-Login-Fragment anzuzeigen und auszublenden. Ich benutze den Otto-Event-Bus, daher habe ich Event-Handler wie die unten. (Nichts ist spezifisch für dieses Problem; ich füge diesen Code nur ein, um Ihnen ein Gefühl dafür zu geben, wie das Login Fragment in die Gesamtstruktur passt.)

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

Während der FacebookWebLoginFragment sollte es befugt sein, das Drücken der Rücktasten des Geräts auszuführen. Dies ist wichtig, da der Facebook-Anmeldungsfluss die Möglichkeit beinhaltet, von der Anmeldeseite weg zu navigieren, und der Benutzer erwartet, dass die Zurück-Schaltfläche sie zur Anmeldung zurückgibt. Also habe ich in meiner Activity folgendes:

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

Das Layout für FacebookWebLoginFragment ist extrem einfach:

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

Hier ist der FacebookWebLoginFragment-Code. Beachten Sie, dass es auf einer Unterklasse von WebChromeClient basiert, um zu erkennen, wann das Facebook-Login-JavaScript zum Schließen des Fensters bereit ist (d. H. Das Fragment entfernen). Beachten Sie auch, dass keine direkte Kommunikation zwischen dieser Anmeldung WebView und der primären WebView vorhanden ist, die die Benutzeroberfläche der Kommentare enthält. Das Auth-Token wird über ein Drittanbieter-Cookie weitergegeben. Aus diesem Grund müssen Sie die Drittanbieter-Cookie-Unterstützung für Ihre primäre WebView aktivieren.

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

Das Schwierigste ist nun, die notwendigen Änderungen an Ihrer vorhandenen WebView vorzunehmen, da wahrscheinlich bereits eine ganze Menge Code vorhanden ist und Sie verstehen müssen, was sich ändern muss.

Stellen Sie zunächst sicher, dass Sie JavaScript aktiviert haben und dass es mehrere Fenster unterstützt.

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

Sie müssen notsetJavaScriptCanOpenWindowsAutomatically(true) aufrufen.

Wenn Sie einige der anderen Antworten betrachten, denken Sie möglicherweise, dass Sie mit der WebViewClient, die Ihrer WebView zugewiesen ist, einen Affen machen und shouldOverrideUrlLoading() überschreiben müssen. Dies ist nicht erforderlich. Wichtig ist die WebChromeClient, die onCreateWindow() überschreiben muss.

Als nächstes weisen Sie Ihrer WebChromeClient eine benutzerdefinierte WebView-Unterklasse zu:

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

Sie werden feststellen, dass dies der zweite Aufruf von UriHelper.isFacebookHost() ist. Ich habe keinen kugelsicheren Ansatz, um dies festzustellen, aber ich mache Folgendes:

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

Sie werden auch den Aufruf von CookieHelper.setAcceptThirdPartyCookies() bemerken. Hier ist der Code dafür:

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

Eine weitere Sache, die einige Leute auslöst, ist die Konfiguration von "Gültigen OAuth-Weiterleitungs-URIs" in den Facebook-Dev-Einstellungen. Wenn Sie einen solchen Fehler in Ihren Protokollen sehen:

URL blockiert: Diese Umleitung ist fehlgeschlagen, da der Umleitungs-URI nicht in den Client-OAuth-Einstellungen der App aufgeführt ist. Stellen Sie sicher, dass Client und Web OAuth Login aktiviert sind, und fügen Sie alle Ihre Anwendungsdomänen als gültige OAuth-Weiterleitungs-URIs hinzu.

... dann sollten Sie diese Antwort überprüfen: https://stackoverflow.com/a/37009374

Habe Spaß! Eine komplizierte Lösung für ein scheinbar einfaches Problem. Positiv ist zu vermerken, dass Android den Entwicklern hier eine Menge Kontrolle gibt.

1
Mark McClelland

Verschieben Sie Ihre Webansicht in eine XML-Layoutdatei. Der Fehler der leeren Seite wurde verursacht, weil das Skript js beim Umleiten der Anmeldung von oAuth auf die Seite zur Berechtigungsannahme fehlgeschlagen ist. Sie können dieses Problem überwinden, indem Sie Ihre Webansicht in das XML-Layout verschieben.

0
Prakhs

Wahrscheinlich keine immer praktikable Antwort, aber eine andere Möglichkeit besteht darin, vom "Popup" -, dann im JS-Stil-OAuth-Login auf den nicht-Popup-Typ "redirect_uri" OAUth umzuschalten, wo er sie an die Anmeldeseite sendet und dann nach Erfolg/Misserfolg gesendet wird auf "some uri err other" (zB eine andere Seite Ihrer eigenen Website), die die Authentifizierung abschließt. FWIW.

FWIW, wo Facebook sagt: "Wenn Sie WebView verwenden, leiten Sie diese an https://www.facebook.com/connect/login_success.html ". Meiner Meinung nach ist das für den Fall (nur ein einziges WebView und ) Sie verwenden OAuth, um sich anzumelden. Sie fügen also der login_success.html einige Auth-Parameter hinzu, die Sie dann lesen können, also nicht den normalen Webfluss.

Eine andere Möglichkeit könnte sein: override die Javascript postMessage-Funktion, so dass Sie erfassen können, was war, damit zum übergeordneten Fenster zurückkehrt.

0
rogerdpack