2013-08-16 4 views
18

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

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() в первую очередь).

ответ

22

Если 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 проверки, если обратный вызов поступил в shouldOverrideUrlLoading метод

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

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

это не мое дело –

+0

Это не сработало –

2

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

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

+1

не могли бы вы помочь мне в том же случае, я нахожусь в крайнем сроке –

0

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

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

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

stack trace #1 stack 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 при попытке возобновить последнюю просматриваемую страницу.