Заставить логин Facebook работать с Android Webview

22

Я просто пытаюсь внедрить логин facebook в WebView на Android. Проблема заключается в том, что я нажимаю кнопку facebook на моей странице HTML и вставляю имя пользователя и пароль в диалоговое окно 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);

Это обычный API-интерфейс Facebook на моей странице HTML, и эта функция вызывается при нажатии кнопки 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? БЛАГОДАРНОСТЬ.

Теги:
facebook
webview

8 ответов

33

У меня была такая же проблема в моем приложении для Android. Причиной проблемы является вход в систему FB. Javascript открывает новую страницу в новом окне. Затем он пытается закрыть его и отправить некоторые коды авторизации 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"
/>

Веб-просмотр идентификатора "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.

  • 0
    Условие if должно быть host.equals("m.facebook.com") || host.equals("www.facebook.com") чтобы соответствовать случаю, когда он загружает www, прежде чем перенаправить на мобильную версию.
  • 0
    Я попробовал то же самое, но я все еще получаю пустую страницу, какие-либо решения?
Показать ещё 8 комментариев
2

Что касается лучшего ответа на этот вопрос, вам просто нужно реализовать метод onPageFinished для WebViewClient класс, который вы используете.

public void onPageFinished(WebView view, String url) {
    // First, get the URL that Facebook 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 redirecting you to.
        // If it is - that it - do what you want to after the logging process has finished.
        return;
    }

    super.onPageFinished(view, url);
} 

Это сработало для меня отлично. Надеюсь, это вам тоже поможет:)

2

Переопределите shouldOverrideUrlLoading() в WebViewClient. Найдите shouldOverrideUrlLoading здесь. Кроме того, есть параметр, который вы можете передать API входа в facebook; Я думаю, это redirect_uri. Это должно помочь вам узнать, когда логин будет успешным, а в вашем shouldOverrideUrlLoading() вам просто нужно будет обнаружить загружаемый URL и если вы указали redirect_uri, то просто верните true в этом методе и закройте веб-просмотр или что угодно хотите, чтобы логин был успешным.

  • 0
    спасибо, помогите мне
1

Выше ответ слишком старый, и он не работает с последней версией sdk для Facebook версии 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");
        }

    }

}
  • 0
    Можете ли вы объяснить /connection-compte.html ? Это куда вы отправляете своего пользователя после успешного входа в систему с Facebook?
  • 1
    это не работает для меня ... какие-либо обновления?
0

Вот пример Android-проекта: Github: Android_Popup_Webview_handler_example

Это проект Android Studio, показывающий, как обрабатывать всплывающие окна в Android Webview. Большинство браузеров с открытым исходным кодом не поддерживают всплывающие окна.

Всплывающие окна особенно важны для входа в OAuth, который используется во многих веб-сайтах (например, www.feedly.com). Всплывающие окна в этом проекте открываются в диалоговом окне и могут быть отброшены кнопкой закрытия или нажатием Назад или всплывающее окно закрывается (например, что происходит в большинстве потоков аутентификации входа).

  • 0
    Логин Facebook работает в этом случае. В логине Google запрещена проблема с пользовательским агентом.
  • 0
    @vivek Синха, это что-то, связанное с другой проблемой. Google прекратил поддержку входа в систему с веб-просмотра с апреля 2017 года.
0

Вероятно, это не всегда жизнеспособный ответ, но другой вариант заключается в том, чтобы переключиться с логина OAuth "popup then JS" в стиль OAUth без повтора "redirect_uri", где он отправляет их на страницу входа в систему, а затем после успеха/сбоя они отправляются на "some uri err other" (например: другая страница на вашем собственном веб-сайте), которая завершает аутентификацию. FWIW.

FWIW, где facebook говорит: "Если вы делаете WebView, перенаправляете их на https://www.facebook.com/connect/login_success.html" моя догадка такова, что для случая (только с одним WebView и) с использованием OAuth для входа в систему, поэтому они добавили бы некоторые параметры auth к login_success.html, которые вы могли бы затем почерпнуть, поэтому не обычный поток в сети...

Другая возможность может заключаться в переопределении функции javascript postMessage, чтобы вы могли захватить то, что должно было вернуться в родительское окно.

0

Мой ответ по существу похож на некоторых других здесь, поскольку я создаю второй WebView для размещения страницы входа в Facebook, вместо того, чтобы пытаться решить проблему с переадресацией. Однако я решил разместить login WebView в своем собственном Fragment и дать ему собственные выделенные подклассы WebViewClient и WebChromeClient. Я думаю, что это немного облегчает представление о том, какую роль играет каждый компонент, и какие объекты нуждаются в настройках и поведении.

Я также использую WebChromeClient.onCloseWindow() для обнаружения, когда Facebook JavaScript хочет закрыть окно входа в систему. Это гораздо более сильный, чем подход, который я изначально преследовал, от другого ответа.

В макете Activity у вас будет "первичный" WebView, на котором размещаются комментарии, и контейнер для FacebookWebLoginFragment. Вход Fragment создается "на лету", когда это необходимо, а затем удаляется, когда пользователь входа в систему Facebook запрашивает, чтобы его окно было закрыто.

Мой макет 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. Я использую шину событий 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. Обратите внимание, что он полагается на подкласс WebChromeClient для обнаружения, когда JavaScript-логин Facebook готов закрыть окно (т.е. Удалить фрагмент). Также обратите внимание, что между этим логином WebView и основным WebView, который содержит пользовательский интерфейс комментариев, нет прямой связи; токен аутентификации передается через сторонний файл cookie, поэтому вы должны обязательно включить стороннюю поддержку файлов cookie в своем основном WebView.

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

Вам не нужно вызывать setJavaScriptCanOpenWindowsAutomatically(true).

Посмотрев на некоторые другие ответы, вы можете подумать, что вам нужно обезьяну с WebViewClient, которая назначена вашему WebView, и переопределить shouldOverrideUrlLoading(). Это необязательно. Важно то, что WebChromeClient, которому необходимо переопределить onCreateWindow().

Итак... затем назначьте свой WebChromeClient подклассу <<20 > :

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 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(). У меня нет пуленепробиваемого подхода к определению этого, но вот что я делаю:

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

Еще одна вещь, которая вызывает некоторые люди, - это конфигурация "Действительных URI перенаправления OAuth" в настройках Facebook. Если вы видите такую ​​ошибку в ваших журналах:

URL Blocked: это перенаправление не удалось, потому что URI перенаправления не включен в настройки настроек клиента OAuth. Убедитесь, что включены учетные записи клиентов и веб-OAuth и добавлены все ваши домены приложений в качестве действительных URI-адресов перенаправления OAuth.

... тогда вы захотите проверить этот ответ: https://stackoverflow.com/questions/37001004/facebook-login-message-url-blocked-this-redirect-failed-because-the-redirect

Удачи! Сложное решение того, что кажется довольно простой проблемой. С положительной стороны, Android предоставил разработчикам массу контроля здесь.

0

Попробуйте переместить свой веб-просмотр в файл макета xml. Ошибка пустой страницы была вызвана из-за ошибки js script при перенаправлении имени входа в систему авторизации на авторизационную страницу авторизации. Вы можете преодолеть эту проблему, переместив веб-просмотр в xml-макет.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню