2013-08-16 15 views
18

Mam działanie, które uwierzytelnia OAuth przechwytując adres URL przekierowania, gdy pojawi się w widoku webowym. Jednak funkcja onPageFinished jest w jakiś sposób wywoływana dwa razy z jakiegoś powodu, co naprawdę zakłóca moją aplikację. Oto kod: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. Proszę nie oznaczać tego jako duplikatu ... Czytałem podobne pytanie na StackOverflow i wywołanie metody ShouldOverrideUrlLoading nie działa dla mnie (dlatego użyłem na pierwszej stroniePageFinished()).

Odpowiedz

22

Jeśli adres URL jest prawidłowy po rozpoczęciu metody onPageStarted na stronie StronaFinished, ale jeśli adres URL jest przekierowywany po na stronie StartStarted, należy wykonaćOverrideUrlLoading, a następnie onPageFinished. Trzeba po prostu sprawdzić, czy adres URL ładowanie jest przekierowywane lub nie

private boolean isRedirected; 

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

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

    isRedirected = false; 
} 

Jeśli adres URL jest przekierowywane wywołania zwrotnego uruchamia tę funkcję

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

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

Przedtem coś onPageFinished sprawdzenia czy zwrotna zawarł shouldOverrideUrlLoading metoda

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

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

to nie mój przypadek –

+0

To nie działało w ogóle –

2

Android z jakiegoś powodu dzwoni onPageFinished() dwa razy (i onPageStarted() trzy razy!), Gdy załadowany URL nie jest działający. Tymczasowym rozwiązaniem jest zmiana redirect_uri na adres URL działającej strony internetowej; w tym przypadku zmieniłem go na https://www.google.com/ (lol, przepraszam, Google). onPageFinished jest wtedy wywoływany tylko raz.

ALE - nadal chcę odpowiedzi na pytanie, dlaczego przeglądanie stron internetowych zachowuje się inaczej, gdy załadowany adres URL nie działa, a co jest lepszym rozwiązaniem niż zmiana adresu redirect_uri na google.com.

+1

czy możesz mi pomóc w tej samej sprawie, jestem w terminie –

0

Ta sztuczka pomaga mi (nie zalecane, ale pomaga)

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

Czekam na imprezie gdzie m.yotube.com wyzwala dwa onPageFinished wydarzeń, ale nie wydaje się spowodowane przez przekierowanie do mnie. Po kilku badaniach stwierdziłem, że istnieje dodatkowa funkcja onPageFinished wywołana przez didFinishNavigation przed wywołaniem metody didStopLoading, która również otrzymuje inne strony.

stack trace #1 stack trace #2

Patrz także:

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

Innym przykładem mogę otrzymać dodatkowe połączenia onPageFinished (! Nawet przed onPageStarted) jest to, kiedy wykorzystują webview.restoreState() we fragmentach . uruchamia dwa zdarzenia onPageFinished podczas próby wznowienia ostatnio oglądanej strony.