35

我只是想在 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 对话页面上重定向后获取响应的任何想法?谢谢。

4

9 回答 9

49

我在我的 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"
/>

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 添加了删除。

于 2013-09-28T14:37:48.080 回答
6

这是一个示例 Android 项目: Github:Android_Popup_Webview_handler_example

这是一个 Android Studio 项目,展示了如何在 Android Webview 中处理弹出窗口。大多数开源浏览器不支持打开弹出窗口。

弹出窗口在许多网站(例如www.feedly.com)中使用的 OAuth 登录中尤为重要。此项目中的弹出窗口在对话框中打开,可以通过关闭按钮或按 Back 或如果弹出窗口自行关闭(就像大多数登录身份验证流程中发生的情况一样)关闭。

于 2017-12-21T18:42:57.110 回答
3

关于这个问题的最佳答案,您只需要实现您使用的 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);
} 

它对我来说很好。希望它也能帮助你:)

于 2015-01-05T12:47:57.410 回答
2

覆盖shouldOverrideUrlLoading()你的WebViewClient. shouldOverrideUrlLoading 在这里搜索。此外,还有一个参数可以传递给 facebook 的登录 API;我认为它是redirect_uri。这应该可以帮助您识别登录成功的时间,并且在您的 中shouldOVerrideUrlLoading(),您只需要检测正在加载的 url,如果它是您指定的 redirect_uri,则只需在该方法中返回 true 并关闭 webview 或任何您想要的时间登录成功。

于 2012-12-24T18:29:26.537 回答
2

我的回答与这里的其他人基本相似,因为我创建了第二个WebView来托管 Facebook 登录页面,而不是尝试通过重定向来解决问题。但是,我选择将登录WebView放在它自己的Fragment,并给它自己的专用WebViewClientWebChromeClient子类。我认为这可以更容易地了解每个组件所扮演的角色,以及哪些对象需要哪些设置和行为。

我还利用它WebChromeClient.onCloseWindow()来检测 Facebook 的 JavaScript 何时想要关闭登录窗口。从不同的答案来看,这比我最初采用的方法要强大得多。

在您的Activity布局中,您将拥有WebView承载评论的 "primary" 和用于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 网络登录片段。我使用 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来检测 Facebook 登录 JavaScript 何时准备好关闭窗口(即,删除片段)。另请注意,此登录名与包含评论 UIWebView的主节点之间没有直接通信;WebView身份验证令牌通过第三方 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, 和 override进行猴子处理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(). 我没有确定这一点的万无一失的方法,但这就是我所做的:

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

让一些人感到困惑的另一件事是 Facebook 开发设置中“有效 OAuth 重定向 URI”的配置。如果您在日志中看到这样的错误:

URL 被阻止:此重定向失败,因为重定向 URI 未在应用的客户端 OAuth 设置中列入白名单。确保客户端和 Web OAuth 登录已打开,并将所有应用程序域添加为有效 OAuth 重定向 URI。

...然后你会想看看这个答案:https ://stackoverflow.com/a/37009374

玩得开心!一个看似非常简单的问题的复杂解决方案。积极的一面是,Android 为开发人员提供了大量的控制权。

于 2017-04-16T02:33:23.020 回答
2

上面的答案太旧了,它不适用于最新的 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");
        }

    }

}
于 2016-08-14T12:15:27.523 回答
1

这段代码对我有用!我的页面上有一个 LIKE、SHARE、Comments 按钮。

    private lateinit var myWebView: WebView;
private val target_url = "https://www.webkomph.com"
private val target_url_prefix = "webkomph.com"
private var mContext: Context? = null
private var mWebviewPop: WebView? = null
private var mContainer: ConstraintLayout? = null
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);
    val cookieManager = CookieManager.getInstance();
    cookieManager.setAcceptCookie(true)

    myWebView  = findViewById(R.id.webkom_site);
    mContainer = findViewById(R.id.webview_frame);
    val webkomBlue = Color.parseColor("#1c71bc")
    myWebView.setBackgroundColor(webkomBlue);
    myWebView.background
    val webSettings = myWebView.settings;
    webSettings.setJavaScriptEnabled(true);
    webSettings.setAppCacheEnabled(true);
    webSettings.javaScriptCanOpenWindowsAutomatically = true;
    webSettings.setSupportMultipleWindows(true)
    myWebView.setWebViewClient(UriWebViewClient())
    myWebView.setWebChromeClient(UriChromeClient())
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        cookieManager.setAcceptThirdPartyCookies(myWebView, true)
    }
    myWebView.loadUrl(target_url);
    mContext = this.applicationContext
}

override fun onBackPressed() {
    if (myWebView.canGoBack()) {
        myWebView.goBack()
    } else {
        super.onBackPressed()
    }
}

inner class UriWebViewClient : WebViewClient() {
    override fun shouldOverrideUrlLoading(
        view: WebView,
        url: String
    ): Boolean {
        val host = Uri.parse(url).host
        //Log.d("shouldOverrideUrlLoading", url);
        if(host == null || host == 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 == "m.facebook.com" || host == "www.facebook.com" || url.contains("ret=login")) {
            return false
        }
        // Otherwise, the link is not for a page on my site, so launch
        // another Activity that handles URLs
        val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
        startActivity(intent)
        return true
    }

    override fun onPageFinished(view: WebView?, url: String) {
        // Facebook redirects to this url once a user has logged in, this is a blank page so we override this
        // http://www.facebook.com/connect/connect_to_external_page_widget_loggedin.php?............
        if (url.contains("plugins/close_popup.php?reload") || url.contains("dialog/close_window") || url.contains("facebook.com/dialog/plugin.optin?")) {

            if(mWebviewPop != null){
                mWebviewPop!!.visibility = View.GONE
                mContainer!!.removeView(mWebviewPop)
                mWebviewPop = null
                if(myWebView != null && (url.contains("dialog/close_window") || url.contains("facebook.com/dialog/plugin.optin?"))){
                    myWebView?.reload();
                }
            }


            return
        }
        super.onPageFinished(view, url)
    }
    override fun onReceivedSslError(
        view: WebView, handler: SslErrorHandler,
        error: SslError
    ) {
        Log.d("onReceivedSslError", "onReceivedSslError")
        //super.onReceivedSslError(view, handler, error);
    }
}

inner class UriChromeClient : WebChromeClient() {
    override fun onCreateWindow(
        view: WebView, isDialog: Boolean,
        isUserGesture: Boolean, resultMsg: Message
    ): Boolean {
        mWebviewPop = WebView(mContext)
        mWebviewPop!!.setVerticalScrollBarEnabled(false)
        mWebviewPop!!.setHorizontalScrollBarEnabled(false)
        mWebviewPop!!.setWebViewClient(UriWebViewClient())
        mWebviewPop!!.getSettings().setJavaScriptEnabled(true)
        mWebviewPop!!.getSettings().setSavePassword(false)
        mWebviewPop!!.layoutParams = FrameLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )
        mContainer?.addView(mWebviewPop)
        val transport = resultMsg.obj as WebViewTransport
        transport.webView = mWebviewPop
        resultMsg.sendToTarget()
        return true
    }

    override fun onCloseWindow(window: WebView) {
        Log.d("onCloseWindow", "called")
    }
}
于 2020-06-06T23:02:07.673 回答
0

可能不是一个总是可行的答案,但另一种选择是从“弹出然后 JS”样式 OAuth 登录切换到非弹出“redirect_uri”OAUth 样式,将它们发送到登录页面,然后在成功/失败后它们被发送到完成身份验证的“某些 uri err other”(例如:您自己网站上的另一个页面)。FWIW。

FWIW facebook 说“如果你正在做 WebView 将它们重定向到 https://www.facebook.com/connect/login_success.html ”我的直觉是(只有一个 WebView 和)使用 OAuth 的情况登录,所以他们会向 login_success.html 添加一些身份验证参数,然后您可以收集这些参数,而不是正常的网络流程......

另一种可能性可能是覆盖javascriptpostMessage函数,以便您可以捕获它将返回到父窗口的内容。

于 2017-10-11T06:46:46.243 回答
0

尝试将您的 webview 移动到 xml 布局文件。空白页错误是由于将 oAuth 登录重定向到授权接受页面时 js 脚本失败导致的。您可以通过将 webview 移动到 xml 布局来解决此问题。

于 2016-02-22T14:03:28.477 回答