Android WebView для кнопки «Мне нравится» в Facebook

Я пытаюсь сделать facebook похожей на функциональность в Android WebView (спецификация проекта не позволяет открывать браузер или выполнять какие-либо действия вне приложения).

Итак, ограничения заключаются в том, что это нужно делать в WebView. Мне удалось сделать это диалоговым окном, и после нажатия пользователем кнопки «Нравится» он (WebView) успешно перенаправляется (в том же представлении) на страницу входа в facebook. После успешной аутентификации WebView (в диалоге) перенаправляется на пустую страницу с заголовком facebook.

Интересно, что когда пользователь покидает пустой диалог и снова нажимает кнопку «Нравится», он работает идеально (как и в отличие от него) — он каким-то образом сохраняет активную аутентификацию. Чтобы разрешить пустую страницу, я пробовал/использовал следующее:

  • используя WebViewClient и shouldOverloadUrlForwarding, чтобы сохранить весь процесс в одном и том же диалоговом окне WebView.
  • использование WebChromeClient для правильного выполнения JavaScript - без него после входа в систему невозможно поставить лайк/не понравиться.
  • пытался использовать setUserAgentString() для имитации других браузеров, таких как Chrome или Firefox
  • попробовал обработку сертификата SSL Error (на уровне API 8) (на WebViewClient)

    @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { handler.proceed(); }

  • используя (и все возможные комбинации из них)

    webView.getSettings().setAppCacheEnabled(true); webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);

  • Пробовал также сохранять файлы cookie с помощью CookieSyncManager, CookieManager и вручную.

Все это было безрезультатно. Я очень ценю любую помощь!


person Stefan    schedule 24.02.2011    source источник
comment
Привет. Не могли бы вы поделиться небольшим фрагментом кода для упомянутых функций. Мне удалось сделать его диалоговым, и после нажатия пользователем кнопки «Нравится» он (WebView) успешно перенаправляется   -  person Dinesh Prajapati    schedule 18.10.2011
comment
Стефан, не могли бы вы помочь мне с этой проблемой. Я столкнулся с конкретной ситуацией. Мой вопрос опубликован в stackoverflow.com/questions/11208427/   -  person Chandra Sekhar    schedule 28.06.2012
comment
проверьте этот пост, есть хорошо сформированная библиотека для решения этой проблемы: stackoverflow.com/a/23853937/1891118   -  person Oleksii K.    schedule 12.06.2014


Ответы (4)


Чтобы пройти пустую страницу, вы делаете это:

 webview.setWebViewClient(new LikeWebviewClient(this));

 private class LikeWebviewClient extends WebViewClient {        
    @Override
    public void onPageFinished(WebView view, String url) {
        Log.d(TAG, "onPageFinished url: " +url);
        // 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.startsWith("http://www.facebook.com/connect/connect_to_external_page_widget_loggedin.php")){
            String redirectUrl = getFacebookLikeUrl();
            view.loadUrl(redirectUrl);
            return;
        }
        super.onPageFinished(view, url);
    }
}
person Blundell    schedule 22.08.2011
comment
Это сработало для меня. Но есть еще одна проблема. Обычно веб-представление может сохранять свое состояние и не перезагружаться при изменении ориентации, используя webView.saveState() и webView.restoreState(), но представленное здесь решение представляет собой своего рода «двойную загрузку» и как бы побеждает код состояния сохранения/восстановления изменения ориентации. У кого-нибудь есть решение/обходной путь? - person Tyler Collier; 26.10.2011
comment
Чтобы ответить на мой вопрос, я использовал onConfigurationChanged(). См.: stackoverflow.com/questions/1002085 / - person Tyler Collier; 27.10.2011
comment
@Blundell- Не могли бы вы сказать мне, что возвращает getFacebookLikeUrl(): это просто URL-адрес, который хотел понравиться пользователю? - person Abhijit; 28.12.2011
comment
@Abhijit Да, это просто URL-адрес facebook из их API, чтобы «лайкнуть» сообщение. - person Blundell; 02.01.2012
comment
может ли кто-нибудь опубликовать пример того, что возвращает getFacebookLikeUrl()? Я полностью озадачен тем, что это за URL или где его взять. - person Yevgeny Simkin; 15.02.2012
comment
@Blundell Я столкнулся с точно такой же ситуацией. Усердно пытаемся найти решение. Не могли бы вы помочь мне понять, что такое метод getFacebookLikeUrl()? Является ли он определенным пользователем или из какой-либо библиотеки. Я разместил вопрос на stackoverflow.com/questions/11208427/, пожалуйста, помогите мне. - person Chandra Sekhar; 28.06.2012
comment
@ChandraSekhar Точно не помню, но сам определил cantremember.com - person Blundell; 28.06.2012
comment
@ Бланделл, я этого не нашел. Пожалуйста, поделитесь конкретным uri - person Chandra Sekhar; 28.06.2012

У меня была такая же проблема в моем приложении для Android. Причина проблемы в том, что javascript входа в FB открывает новую страницу в новом окне. Затем он пытается закрыть его после успешного входа в систему. Пожалуйста, следуйте примеру из моих рабочих кодов.

<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 идентификатора «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.

person Ken You    schedule 28.09.2013

Мне пришлось решить эту почти ту же проблему на iPhone. Что мне нужно было сделать, так это перехватить запрос, который веб-просмотр делает на «пустую страницу», которую вы описали выше, и вместо этого указать веб-просмотру загрузить аналогичный URL-адрес.

person Logan    schedule 31.03.2011
comment
как вы перехватываете запрос веб-просмотра и перенаправляете его? - person ir2pid; 11.07.2011
comment
@ user838355, посмотри мой ответ :-) - person Blundell; 22.08.2011

У меня не сработало :(, но из наблюдения я понимаю, что неправильная перенаправленная ссылка начинается с

url.startsWith("http://m.facebook.com/a/profile.php?fan&id"))
person Jozic    schedule 22.05.2012