Android- Webview onPageFinished被称为两次

时间:2013-08-16 22:12:24

标签: android android-webview

我有一项活动通过在网页浏览中显示重定向网址时拦截重定向网址来执行OAuth身份验证。但是,由于某种原因,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()的原因)。

7 个答案:

答案 0 :(得分:28)

如果在onPageStarted方法启动onPageFinished后url是OK,但是如果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中执行某些操作之前,请检查回调是否已输入shouldOverrideUrlLoading方法

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

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

答案 1 :(得分:6)

也许可以帮助某人。

我遇到了一些问题-方法onPageFinished调用了两次。

webView.getProgress();

在第一次执行时webView.getProgress()== 89,在第二次执行== 100。 100表示​​页面加载完成。

答案 2 :(得分:4)

因此,以上答案均未提供解决方案,因为我的问题不是重定向,因此Webview在同一网页上仅调用了onPageFinished 3次。 我的解决方案如下,主要思想是只对同一网址执行一次功能。

private String urlFinished = " ";

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

    Logger.d(TAG, "onPageFinished");

    if (!urlFinished.equals(url)) {
      //Place your code here
    }

    urlFinished = url;

    super.onPageFinished(view, url);
}

答案 3 :(得分:2)

Android由于某种原因调用onPageFinished()两次(和onPageStarted()三次!)当加载的url不是工作的时。临时解决方案是将redirect_uri更改为工作网站的URL;在这种情况下,我将其更改为https://www.google.com/(哈哈,对不起谷歌)。然后只调用onPageFinished一次。

但是我仍然想要了解当加载的网址不是工作网页时webview的行为有何不同的答案,以及比将redirect_uri更改为google.com更好的解决方案。

答案 4 :(得分:1)

这个技巧对我有帮助(不推荐但有帮助)

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

答案 5 :(得分:1)

我正在研究m.yotube.com触发两个onPageFinished事件的事件,但它似乎不是由重定向引起的。经过一些研究后,我发现在didSinLoading触发的didFinishNavigation之前还有一个额外的onPageFinished,其他页面也接收到了。

stack trace #1 stack trace #2

另见:

URL / UTF8 encoded value

    @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之前!)是我在Fragments中使用webview.restoreState()的时候。尝试恢复上次查看的页面时,它会触发两个onPageFinished事件。

答案 6 :(得分:0)

由于onPageFinished被多次调用,因此您可以在进一步执行任何操作之前简单地检查该方法是否已经被调用。

@Override
public void onPageFinished(WebView view, String url) {
     if (loaded) {
          return;
     }

     // Do something...

     loaded = true;
}