Я просто пытаюсь внедрить логин 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? БЛАГОДАРНОСТЬ.
У меня была такая же проблема в моем приложении для 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.
Что касается лучшего ответа на этот вопрос, вам просто нужно реализовать метод 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);
}
Это сработало для меня отлично. Надеюсь, это вам тоже поможет:)
Переопределите shouldOverrideUrlLoading()
в WebViewClient
. Найдите shouldOverrideUrlLoading
здесь. Кроме того, есть параметр, который вы можете передать API входа в facebook; Я думаю, это redirect_uri. Это должно помочь вам узнать, когда логин будет успешным, а в вашем shouldOverrideUrlLoading()
вам просто нужно будет обнаружить загружаемый URL и если вы указали redirect_uri, то просто верните true в этом методе и закройте веб-просмотр или что угодно хотите, чтобы логин был успешным.
Выше ответ слишком старый, и он не работает с последней версией 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");
}
}
}
/connection-compte.html
? Это куда вы отправляете своего пользователя после успешного входа в систему с Facebook?
Вот пример Android-проекта: Github: Android_Popup_Webview_handler_example
Это проект Android Studio, показывающий, как обрабатывать всплывающие окна в Android Webview. Большинство браузеров с открытым исходным кодом не поддерживают всплывающие окна.
Всплывающие окна особенно важны для входа в OAuth, который используется во многих веб-сайтах (например, www.feedly.com). Всплывающие окна в этом проекте открываются в диалоговом окне и могут быть отброшены кнопкой закрытия или нажатием Назад или всплывающее окно закрывается (например, что происходит в большинстве потоков аутентификации входа).
Вероятно, это не всегда жизнеспособный ответ, но другой вариант заключается в том, чтобы переключиться с логина 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
, чтобы вы могли захватить то, что должно было вернуться в родительское окно.
Мой ответ по существу похож на некоторых других здесь, поскольку я создаю второй 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 предоставил разработчикам массу контроля здесь.
Попробуйте переместить свой веб-просмотр в файл макета xml. Ошибка пустой страницы была вызвана из-за ошибки js script при перенаправлении имени входа в систему авторизации на авторизационную страницу авторизации. Вы можете преодолеть эту проблему, переместив веб-просмотр в xml-макет.
if
должно бытьhost.equals("m.facebook.com") || host.equals("www.facebook.com")
чтобы соответствовать случаю, когда он загружает www, прежде чем перенаправить на мобильную версию.