2013-08-16 33 views
18

Tôi có một hoạt động xác thực OAuth bằng cách chặn url chuyển hướng khi url đó hiển thị trong chế độ xem web. Tuy nhiên, hàm onPageFinished bằng cách nào đó được gọi là hai lần vì một lý do nào đó, điều này thực sự làm rối loạn ứng dụng của tôi. Đây là mã:Android- Webview trênPageFinished 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. Xin vui lòng không đánh dấu điều này như là một bản sao ... Tôi đã đọc một câu hỏi tương tự trên StackOverflow và gọi ShouldOverrideUrlLoading không làm việc cho tôi (đó là lý do tại sao tôi sử dụng onPageFinished() ở nơi đầu tiên).

Trả lời

22

Nếu url là OK sau khi phương thức onPageStarted bắt đầu onPageFinished, nhưng nếu url được chuyển hướng sau onPageStarted bắt đầu shouldOverrideUrlLoading và sau đó onPageFinished. Bạn chỉ nên kiểm tra xem URL tải được chuyển hướng hay không

private boolean isRedirected; 

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

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

    isRedirected = false; 
} 

Nếu URL được chuyển hướng gọi lại bắt đầu chức năng này

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

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

Trước khi làm một cái gì đó trong tầm kiểm soát onPageFinished nếu gọi lại đã bước vào shouldOverrideUrlLoading phương pháp

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

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

đây không phải là trường hợp của tôi –

+0

Điều này không hoạt động chút nào –

2

Android vì một số lý do cuộc gọi onPageFinished() hai lần (và onPageStarted() ba lần!) Khi url được tải không phải là địa chỉ đang hoạt động. Giải pháp tạm thời đang thay đổi redirect_uri thành url của trang web đang hoạt động; trong trường hợp này, tôi đã đổi nó thành https://www.google.com/ (lol, xin lỗi Google). onPageFinished sau đó chỉ được gọi một lần.

NHƯNG-Tôi vẫn muốn câu trả lời về lý do khiến chế độ xem web hoạt động khác nhau khi url được tải không phải là địa chỉ đang hoạt động và giải pháp tốt hơn là thay đổi redirect_uri thành google.com.

+1

bạn có thể vui lòng giúp tôi trong cùng một trường hợp không, tôi đang ở hạn chót –

0

Thủ thuật này giúp tôi (Không được đề xuất nhưng trợ giúp)

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

Tôi đang nhìn vào một sự kiện mà m.yotube.com gây nên hai sự kiện onPageFinished nhưng nó không có vẻ như gây ra bởi chuyển hướng đối với tôi. Sau khi một số nghiên cứu tôi thấy rằng có thêm một onPageFinished được kích hoạt bởi didFinishNavigation trước khi một được kích hoạt bởi didStopLoading mà các trang khác cũng nhận được.

stack trace #1 stack trace #2

Xem thêm:

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

Một ví dụ tôi nhận cuộc gọi onPageFinished thêm (! Ngay cả trước khi onPageStarted) là khi tôi sử dụng webview.restoreState() trong Những mảnh vỡ . nó kích hoạt hai sự kiện onPageFinished khi cố gắng tiếp tục xem trang cuối cùng.