Подтвердить что ты не робот

Android-Webview onPageFinished Called Twice

У меня есть активность, которая делает аутентификацию OAuth, перехватывая URL-адрес перенаправления, когда он появляется в веб-просмотре. Однако функция onPageFinished почему-то вызвана дважды по какой-то причине, что действительно испортило мое приложение. Здесь код:

public class WebViewActivity extends Activity {
private WebView gWebView;
final String REDIRECT_URI = "https://localhost:5000/receive_code";
final String CLIENT_ID = "can't post it here";
final String CLIENT_SECRET = "can't post it here";
final String SCOPE = "basic names genomes analyses";
Hashtable<String, String> riskPairs;

public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.webview);

    gWebView = (WebView) findViewById(R.id.webView1);

    gWebView.loadUrl("https://api.23andme.com/authorize/?redirect_uri="
            + REDIRECT_URI + "&response_type=code&client_id=" + CLIENT_ID
            + "&scope=" + SCOPE);

    Log.d("WEBVIEW", "got to webpage");

    gWebView.setWebViewClient(new WebViewClient() {

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            if (url.startsWith(REDIRECT_URI)) {
                Log.d("WEBVIEW", "onpagefinished is called");
                System.out.println("got to override");
                if (url.indexOf("code=") != -1) {
                    //if the query contains code
                    String queryString = null;
                    try {
                        queryString = new URL(url).getQuery();
                    } catch (MalformedURLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(queryString);
                    String[] params = queryString.split("&");
                    String code = null;
                    for (String param : params) {
                        if (param.startsWith("code=")) {
                            code = param.substring(param.indexOf('=') + 1);
                        }
                    }
                    gWebView.setVisibility(View.GONE);
                    new PostRequest().execute(code);
                    // don't go to redirectUri
                }
            }
        }
    });


}
class PostRequest extends AsyncTask<String,Void,String>{ code getting client data...}

P.S. Пожалуйста, не отмечайте это как дубликат... Я прочитал аналогичный вопрос в StackOverflow и вызвал ShouldOverrideUrlLoading для меня не работает (именно поэтому я использовал onPageFinished() в первую очередь).

4b9b3361

Ответ 1

Если URL-адрес в порядке после того, как метод onPageStarted запущен onPageFinished, но если URL-адрес перенаправлен после onPageStarted запускает shouldOverrideUrlLoading, а затем onPageFinished. Вы должны просто проверить, перенаправлен ли URL загрузки или нет.

private boolean isRedirected;

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {   

  if (!isRedirected) {      
    //Do something you want when starts loading
  }

  isRedirected = false;
}

Если URL-адрес перенаправлен, обратный вызов запускает эту функцию

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {

  view.loadUrl(url);
  isRedirected = true;
  return true;
}

Прежде чем делать что-то в onPageFinished, проверьте, был ли обратный вызов введен в метод toOverrideUrlLoading

@Override
public void onPageFinished(WebView view, String url) {

  if (!isRedirected) {
    //Do something you want when finished loading 
  }
}

Ответ 2

Android почему-то вызывает onPageFinished() дважды (и onPageStarted() три раза!), когда загруженный URL-адрес не работает. Временное решение изменяет redirect_uri на URL рабочего веб-сайта; в этом случае я изменил его на https://www.google.com/ (lol, извините Google). onPageFinished затем вызывается только один раз.

НО. Я все еще хочу получить ответы на вопрос о том, почему webview ведет себя по-другому, когда загруженный URL-адрес не является рабочим, и что является лучшим решением, чем изменение redirect_uri на google.com.

Ответ 3

Я просматриваю событие, когда m.yotube.com запускает два события onPageFinished, но это не похоже на перенаправление для меня. После некоторых исследований я обнаружил, что есть еще один дополнительный параметр onPageFinished, инициированный didFinishNavigation, до того, как был вызван didStopLoading, который также получает другие страницы.

stack trace #1stack trace #2

См. также:

https://chromium.googlesource.com/chromium/src.git/+/master/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java

    @Override
    public void didFinishNavigation(final String url, boolean isInMainFrame, boolean isErrorPage,
            boolean hasCommitted, boolean isSameDocument, boolean isFragmentNavigation,
            Integer pageTransition, int errorCode, String errorDescription, int httpStatusCode) {
        ...
        if (client != null && isFragmentNavigation) {
            client.getCallbackHelper().postOnPageFinished(url);
        }
    }

    @Override
    public void didStopLoading(String validatedUrl) {
        if (validatedUrl.length() == 0) validatedUrl = ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL;
            AwContentsClient client = getClientIfNeedToFireCallback(validatedUrl);
        if (client != null && validatedUrl.equals(mLastDidFinishLoadUrl)) {
            client.getCallbackHelper().postOnPageFinished(validatedUrl);
        mLastDidFinishLoadUrl = null;
        }
    }

В другом экземпляре я получаю дополнительные onPageFinished звонки (даже до onPageStarted!), когда я использую webview.restoreState() в фрагментах. он запускает два события onPageFinished при попытке возобновить последнюю просматриваемую страницу.

Ответ 4

Этот трюк помогает мне (не рекомендуется, но помогает)

private boolean alreadyEvaluated = false;

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {

        Logger.d(TAG, "onPageStarted");

        super.onPageStarted(view, url, favicon);
    }

    @Override
    public void onPageFinished(WebView view, String url) {

        Logger.d(TAG, "onPageFinished");

        if (!alreadyEvaluated) {
            alreadyEvaluated = true;
            view.loadUrl("javascript:window.MyJavaScript.getPageText(document.getElementsByTagName('body')[0].innerText);");
        } else {
            alreadyEvaluated = false;
        }

        super.onPageFinished(view, url);
    }