Android- Webview onPageFinished调用两次

ldxq2e6h  于 2023-06-20  发布在  Android
关注(0)|答案(9)|浏览(609)

我有一个活动,它通过拦截重定向URL来进行OAuth身份验证,一旦它出现在webview中。但是,onPageFinished函数由于某种原因被调用了两次,这确实把我的应用程序搞得一团糟。代码如下:

  1. public class WebViewActivity extends Activity {
  2. private WebView gWebView;
  3. final String REDIRECT_URI = "https://localhost:5000/receive_code";
  4. final String CLIENT_ID = "can't post it here";
  5. final String CLIENT_SECRET = "can't post it here";
  6. final String SCOPE = "basic names genomes analyses";
  7. Hashtable<String, String> riskPairs;
  8. public void onCreate(Bundle savedInstanceState){
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.webview);
  11. gWebView = (WebView) findViewById(R.id.webView1);
  12. gWebView.loadUrl("https://api.23andme.com/authorize/?redirect_uri="
  13. + REDIRECT_URI + "&response_type=code&client_id=" + CLIENT_ID
  14. + "&scope=" + SCOPE);
  15. Log.d("WEBVIEW", "got to webpage");
  16. gWebView.setWebViewClient(new WebViewClient() {
  17. @Override
  18. public void onPageFinished(WebView view, String url) {
  19. super.onPageFinished(view, url);
  20. if (url.startsWith(REDIRECT_URI)) {
  21. Log.d("WEBVIEW", "onpagefinished is called");
  22. System.out.println("got to override");
  23. if (url.indexOf("code=") != -1) {
  24. //if the query contains code
  25. String queryString = null;
  26. try {
  27. queryString = new URL(url).getQuery();
  28. } catch (MalformedURLException e) {
  29. // TODO Auto-generated catch block
  30. e.printStackTrace();
  31. }
  32. System.out.println(queryString);
  33. String[] params = queryString.split("&");
  34. String code = null;
  35. for (String param : params) {
  36. if (param.startsWith("code=")) {
  37. code = param.substring(param.indexOf('=') + 1);
  38. }
  39. }
  40. gWebView.setVisibility(View.GONE);
  41. new PostRequest().execute(code);
  42. // don't go to redirectUri
  43. }
  44. }
  45. }
  46. });
  47. }
  48. class PostRequest extends AsyncTask<String,Void,String>{ code getting client data...}

P.S.请不要将此标记为重复...我在StackOverflow上读到过类似的问题,调用ShouldOverrideUrlLoading对我不起作用(这就是为什么我首先使用onPageFinished())。

n6lpvg4x

n6lpvg4x1#

如果onPageStarted方法启动onPageFinished后URL正常,但如果在onPageStarted启动shouldOverrideUrlLoading然后onPageFinished后URL被重定向。你只需要检查加载URL是否被重定向

  1. private boolean isRedirected;
  2. @Override
  3. public void onPageStarted(WebView view, String url, Bitmap favicon) {
  4. if (!isRedirected) {
  5. //Do something you want when starts loading
  6. }
  7. isRedirected = false;
  8. }

如果URL被重定向,则回调将启动此函数

  1. @Override
  2. public boolean shouldOverrideUrlLoading(WebView view, String url) {
  3. view.loadUrl(url);
  4. isRedirected = true;
  5. return true;
  6. }

在onPageFinished中执行某些操作之前,请检查回调是否已进入shouldOverrideUrlLoading方法

  1. @Override
  2. public void onPageFinished(WebView view, String url) {
  3. if (!isRedirected) {
  4. //Do something you want when finished loading
  5. }
  6. }
展开查看全部
sulc1iza

sulc1iza2#

也许它能帮助某人。
我有一些问题-方法onPageFinished调用了两次。
System. out. println();
在第一次执行时webView.getProgress()== 89,在第二次执行时== 100。100表示页面加载完成。

wvt8vs2t

wvt8vs2t3#

所以,上面的答案都没有给我一个解决方案,因为我的问题不是重定向,webview只是在同一个网页上调用onPageFinished 3次。我的解决方案如下,主要思想是在同一个URL上执行一次功能。

  1. private String urlFinished = " ";
  2. @Override
  3. public void onPageFinished(WebView view, String url) {
  4. Logger.d(TAG, "onPageFinished");
  5. if (!urlFinished.equals(url)) {
  6. //Place your code here
  7. }
  8. urlFinished = url;
  9. super.onPageFinished(view, url);
  10. }
olhwl3o2

olhwl3o24#

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

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

  1. @Override
  2. public void didFinishNavigation(final String url, boolean isInMainFrame, boolean isErrorPage,
  3. boolean hasCommitted, boolean isSameDocument, boolean isFragmentNavigation,
  4. Integer pageTransition, int errorCode, String errorDescription, int httpStatusCode) {
  5. ...
  6. if (client != null && isFragmentNavigation) {
  7. client.getCallbackHelper().postOnPageFinished(url);
  8. }
  9. }
  10. @Override
  11. public void didStopLoading(String validatedUrl) {
  12. if (validatedUrl.length() == 0) validatedUrl = ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL;
  13. AwContentsClient client = getClientIfNeedToFireCallback(validatedUrl);
  14. if (client != null && validatedUrl.equals(mLastDidFinishLoadUrl)) {
  15. client.getCallbackHelper().postOnPageFinished(validatedUrl);
  16. mLastDidFinishLoadUrl = null;
  17. }
  18. }

另一个例子是我收到了额外的onPageFinished调用(甚至在onPageStarted之前!)是我在Fragments中使用webview.restoreState()的时候。它在尝试恢复上次查看的页面时触发两个onPageFinished事件。

展开查看全部
vsikbqxv

vsikbqxv5#

Android出于某种原因调用onPageFinished()两次(和onPageStarted()三次!)当加载的URL不是工作URL时。临时解决方案是将redirect_uri更改为工作网站的url;在这种情况下,我将其更改为https://www.google.com/(lol,对不起Google)。onPageFinished只被调用一次。
但是-我仍然想知道为什么当加载的URL不是一个工作的URL时,webview的行为会有所不同,以及什么是比将redirect_uri更改为google.com更好的解决方案。

gxwragnw

gxwragnw6#

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

  1. private boolean alreadyEvaluated = false;
  2. @Override
  3. public void onPageStarted(WebView view, String url, Bitmap favicon) {
  4. Logger.d(TAG, "onPageStarted");
  5. super.onPageStarted(view, url, favicon);
  6. }
  7. @Override
  8. public void onPageFinished(WebView view, String url) {
  9. Logger.d(TAG, "onPageFinished");
  10. if (!alreadyEvaluated) {
  11. alreadyEvaluated = true;
  12. view.loadUrl("javascript:window.MyJavaScript.getPageText(document.getElementsByTagName('body')[0].innerText);");
  13. } else {
  14. alreadyEvaluated = false;
  15. }
  16. super.onPageFinished(view, url);
  17. }
展开查看全部
rkkpypqq

rkkpypqq7#

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

  1. @Override
  2. public void onPageFinished(WebView view, String url) {
  3. if (loaded) {
  4. return;
  5. }
  6. // Do something...
  7. loaded = true;
  8. }
rqcrx0a6

rqcrx0a68#

这里有一个更好的解决方案(不是最好的)。由于(在我的情况下)第二次触发非常快,我假设我可以依赖System.currentTimeMillis(),如下所示:

  1. webView.webViewClient = object : WebViewClient() {
  2. private var recentPageFinish = 0L
  3. override fun onPageFinished(webview: WebView, url: String) {
  4. if (System.currentTimeMillis() - recentPageFinish > 1000) {
  5. parsePage(webview)
  6. }
  7. recentPageFinish = System.currentTimeMillis()
  8. }
  9. }

该解决方法防止任何其他(短时间,1000 ms)链式触发,并且它从第一个触发调用parsePage()。无论如何,复杂的网页/网站不会在onPageFinished()触发器上准备好,因为javascript(计数器/帧/web-api-calls/等)正在运行。通常,如果要解析页面,应该在onPageFinished()触发器之后等待一段时间。

ujv3wf0j

ujv3wf0j9#

解决方案的最佳途径;
问题--> Android设备onPagefinished调用两次。(IOS设备没有问题)
解决方案-->在OnLoadStop之前你可以调用定义bool参数的onLoadStart方法。

*onLoadStart:(controller,url)async{ //bool param define this section },
*onLoadStop:(controller,url)async { if(bool param){ // than control enter code here } }

相关问题