web-dev-qa-db-ja.com

Android WebviewでFacebookログインを機能させる

AndroidのWebViewでFacebookログインを実装しようとしています。問題は、HTMLページでFacebookボタンをクリックして、Facebookダイアログでユーザー名とパスワードを挿入した後です。 URLリダイレクトは、私に黒いページを与えているだけです。

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

これはHTMLページ上のFacebookの通常のJavaScript APIであり、この関数は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'});

Facebookのダイアログページでリダイレクト後に応答を取得する方法についてのアイデアはありますか?ありがとう。

26
Adrian Avendano

Androidアプリケーションで同じ問題が発生しました。問題の原因は、FBログインjavascriptが新しいウィンドウで新しいページを開くことです。 、ログイン成功後WebViewは通常「単一ウィンドウのみ」であるため、戻る場所がないため、空白の画面になります。

私の作業コードから流れる例をフォローしてください。

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

Id "webview"のWebviewは、私のコンテンツのメインビューです。以下は私の活動コードです。

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

}
}

この問題の鍵はonCreateWindowです。新しいウィンドウが作成され、フレームレイアウトに挿入され、成功すると削除されます。 shouldOverrideUrlLoadingで削除を追加しました。

40
Ken You

Androidプロジェクトの例を次に示します。 Github:Android_Popup_Webview_handler_example

これは、Android Webviewでポップアップを処理する方法を示すAndroid St​​udioプロジェクトです。ほとんどのオープンソースブラウザは、ポップアップを開くことをサポートしていません。

ポップアップは、多くのWebサイトで使用されるOAuthログインで特に重要です(例: www.feedly.com )。このプロジェクトのポップアップはダイアログで開かれ、閉じるボタンまたは[戻る]を押すか、ポップアップウィンドウが閉じた場合(ほとんどのログイン認証フローで発生するような)で閉じることができます。

3
Haider

ベストアンサー から この質問 に関しては、使用するWebViewClientクラスのonPageFinishedメソッドを実装するだけです。

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

私にとってはうまくいきました。それがあなたにも役立つことを願っています:)

2
Yulian

WebViewClientshouldOverrideUrlLoading()をオーバーライドします。 shouldOverrideUrlLoadinghere を検索します。また、facebookのログインAPIに渡すことができるパラメーターがあります。私はそれがredirect_uriだと思います。これは、ログインが成功し、shouldOVerrideUrlLoading()で認識されるのに役立つはずです。ロードされるURLを検出し、指定したredirect_uriであれば、そのメソッドでtrueを返し、ログインが成功したときにwebviewまたは何でもしたい。

2
praneetloke

上記の答えは古すぎて、最新のFacebook SDKバージョン2.7では機能しません。それに4時間を費やした後、私はそれでいくつかの変更を発見しました。次のコードは、最新のSDKで正常に機能します。

以下は、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>

これは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

Webビューをxmlレイアウトファイルに移動してみてください。空白ページエラーは、oAuth=承認受け入れページへのログイン中にjsスクリプトが失敗するために発生しました。この問題は、webviewをxmlレイアウトに移動することで解決できます。

0
Prakhs

おそらく常に実行可能な答えではないかもしれませんが、別のオプションは「ポップアップとJS」スタイルOAuth非ポップアップ「redirect_uri」OAUthスタイルへのログインログインページに送信し、成功/失敗後に「some uri err other」(例:自分のWebサイトの別のページ)に送信され、認証が完了します。

Facebookで「WebViewを使用している場合、それらを https://www.facebook.com/connect/login_success.html "にリダイレクトします」というFWIWは、単一のWebViewおよび)OAuth=を使用してログインするため、通常のWebフローではなく収集できるlogin_success.htmlに認証パラメーターを追加します...

別の可能性としては、 オーバーライド javascript postMessage関数を使用して、それが何であったかをキャプチャできるようにしますabout to親ウィンドウに戻ります。

0
rogerdpack

私の答えは、リダイレクトに関する問題を解決しようとするのではなく、Facebookログインページをホストするために2番目のWebViewを作成するという点で、ここの他のいくつかと本質的に似ています。ただし、ログインWebViewを独自のFragmentに配置し、専用のWebViewClientおよびWebChromeClientサブクラスにすることを選択しました。これにより、各コンポーネントがどのような役割を果たし、どのオブジェクトがどの設定と動作を必要とするかが少しわかりやすくなると思います。

また、WebChromeClient.onCloseWindow()を使用して、FacebookのJavaScriptがログインウィンドウを閉じたいときを検出します。これは、別の答えから私が最初に追求したアプローチよりもはるかに堅牢です。

Activityレイアウトには、コメントをホストする「プライマリ」_WebViewと、FacebookWebLoginFragmentのコンテナがあります。ログインFragmentは必要なときにオンザフライで作成され、FacebookのログインJavaScriptがウィンドウのクローズを要求したときに削除されます。

私のActivityレイアウトは次のようになります。

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

Activity内で、Facebook Webログインフラグメントを表示および非表示にするコードが必要です。 Ottoイベントバスを使用しているため、以下のようなイベントハンドラーがあります。 (ここではこの問題に特化したものはありません。ログインFragmentが全体の構造にどのように適合するかを示すために、このコードを含めています。)

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

FacebookWebLoginFragmentが存在する間、デバイスのバックボタンの押下を処理する権限を付与する必要があります。 Facebookのログインフローにはログインページから移動する機能が含まれており、ユーザーは[戻る]ボタンでログインに戻ることが期待されるため、これは重要です。だから、私のActivityには、これがあります:

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

FacebookWebLoginFragmentのレイアウトは非常に簡単です。

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

これがFacebookWebLoginFragmentコードです。 FacebookログインJavaScriptがウィンドウを閉じる(つまり、フラグメントを削除する)準備ができたことを検出するために、WebChromeClientのサブクラスに依存していることに注意してください。また、このログインWebViewとコメントUIを含むプライマリWebViewの間には直接通信がないことに注意してください。認証トークンはサードパーティのCookieを介して渡されるため、プライマリWebViewでサードパーティのCookieサポートを有効にする必要があります。

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

さて、既存のWebViewに必要な変更を行うのが最も難しいのは、既にかなりの量のコードが適切に配置されている可能性があるためです。変化する。

まず、JavaScriptが有効になっており、複数のウィンドウをサポートしていることを確認してください。

_WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportMultipleWindows(true);
_

あなたはnotsetJavaScriptCanOpenWindowsAutomatically(true)を呼び出す必要があります。

他のいくつかの答えを見ると、WebViewClientに割り当てられているWebViewを使用して、shouldOverrideUrlLoading()をオーバーライドする必要があると思うかもしれません。これは必要ありません。重要なのはWebChromeClientです。これはonCreateWindow()をオーバーライドする必要があります。

それで...次に、カスタムWebChromeClientサブクラスを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;
    }
});
_

これはUriHelper.isFacebookHost()の2番目の呼び出しであることに気付くでしょう。私はこれを決定するための防弾アプローチを持っていませんが、ここで私がやっていることは次のとおりです。

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

CookieHelper.setAcceptThirdPartyCookies()の呼び出しにも気付くでしょう。そのためのコードは次のとおりです。

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

一部の人々をつまずかせるもう1つのことは、Facebook開発設定の「有効なOAuth=リダイレクトURI」の設定です。ログに次のようなエラーが表示された場合:

URLのブロック:リダイレクトURIがアプリのクライアントにホワイトリストに登録されていないため、このリダイレクトは失敗しましたOAuth設定。クライアントとWebを確認してくださいOAuth有効なOAuthリダイレクトURI。

...次に、この答えを確認してください。 https://stackoverflow.com/a/37009374

楽しんで!非常に単純な問題のように見えるものに対する複雑な解決策。良い面として、Androidは開発者にここで多くの制御を与えました。

0
Mark McClelland