Javascript 使用Android网络视图登录facebook
我只是想在Android的网络视图上实现facebook登录。问题是在我点击HTML页面上的facebook按钮并在facebook对话框中插入用户名和密码之后。url重定向只是给了我一个黑色页面Javascript 使用Android网络视图登录facebook,javascript,android,facebook,webview,Javascript,Android,Facebook,Webview,我只是想在Android的网络视图上实现facebook登录。问题是在我点击HTML页面上的facebook按钮并在facebook对话框中插入用户名和密码之后。url重定向只是给了我一个黑色页面 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WebView webview = new WebView(this);
@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对话页面上重定向后,如何获得回复?谢谢。在您的
WebViewClient
中重写应该重写的URL()。搜索应覆盖以下内容
。此外,还有一个参数可以传递到facebook的登录API;我想这是我的错。这将有助于您识别登录成功的时间,在您的shouldOVerrideUrlLoading()
中,您只需检测正在加载的url,如果它是您指定的重定向uri,然后在该方法中返回true,并在登录成功后关闭webview或任何您想要的内容。我的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"
/>
这个问题的关键是onCreateWindow。将创建一个新窗口,并将其插入框架布局,成功后将其删除。我在shouldOverrideUrlLoading中添加了删除操作。关于,您只需要实现您使用的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);
}
这对我来说很好。希望它也能帮助您:)尝试将您的Web视图移动到xml布局文件。空白页错误是由于JS脚本失败而导致OAuthLogin重定向到授权接受页面。您可以通过将webview移动到xml布局中来解决此问题。以上答案太旧,并且不适用于最新的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>
我的答案与这里的其他一些答案基本相似,因为我创建了第二个WebView
来托管Facebook登录页面,而不是试图解决重定向问题。但是,我选择将登录名WebView
放在它自己的片段中,并给它自己的WebViewClient
和WebChromeClient
子类。我认为这样可以更容易地看到每个组件所扮演的角色,以及哪些对象需要哪些设置和行为
我还利用WebChromeClient.onCloseWindow()
来检测Facebook的JavaScript何时想要关闭登录窗口。从一个不同的答案来看,这比我最初采用的方法要稳健得多
在活动
布局中,您将有一个“主”WebView
,它承载注释,以及一个用于facebook weblogin片段的容器。登录片段是在需要时动态创建的,然后在Facebook的登录JavaScript请求关闭窗口时删除
我的活动
布局如下所示:
当FacebookWebLoginFragment
存在时,应该授予它处理设备后退按钮的权限。这一点很重要,因为Facebook的登录流包含了从登录页面导航出去的功能,用户希望通过返回按钮返回登录。因此,在我的活动中
,我有以下几点:
@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>
现在,最棘手的一点是对现有的WebView
进行必要的更改,因为您可能已经在它周围准备了大量的代码,并且您需要了解需要更改的内容
首先,确保启用了JavaScript,并且它支持多个窗口
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportMultipleWindows(true);
您不需要调用setJavaScriptCanOpenWindowsAutomatically(true)
查看其他一些答案,您可能认为需要使用分配给WebView
的WebViewClient
,并覆盖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
。。。然后,您将要查看以下答案:
玩得开心!一个看似简单问题的复杂解决方案。从积极的一面来看,Android给了开发者大量的控制权。可能不是一个总是可行的答案,但另一个选择是从“弹出然后JS”风格的OAuth登录切换到非弹出的“重定向uri”OAuth风格,在那里它将他们发送到登录页面,然后在成功/失败后,他们被发送到“某个uri错误其他”(例如:你自己网站上的另一个页面)
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();
}
};
}
}
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportMultipleWindows(true);
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;
}
});
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;
}
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);
}
}