Làm cách nào để nghe WebView hoàn tất tải URL?


447

tôi có một WebView cái đang tải một trang từ Internet. Tôi muốn hiển thị ProgressBarcho đến khi tải xong.

Làm thế nào để tôi lắng nghe việc hoàn thành tải trang của a WebView?


1
Vui lòng xem xét đánh dấu câu trả lời của tôi là chính xác, vì nó giải quyết một số vấn đề mà ian không có.
neteinstein

Tôi nghĩ rằng một cách tốt hơn để gọi mã java gốc với js khi tải trang. Tham khảo câu trả lời này, mặc dù là cho ios, nhưng ý tưởng cũng được áp dụng ở đây .
Kris Roofe

Kiểm tra câu trả lời của tôi dưới đây để biết giải pháp tối thiểu và súc tích
Skynet

Câu trả lời:


715

Mở rộng WebViewClient và gọi onPageFinished () như sau:

mWebView.setWebViewClient(new WebViewClient() {

   public void onPageFinished(WebView view, String url) {
        // do your stuff here
    }
});

Tôi có một số vấn đề với tải bên ngoài khi Internet không quá nhanh. Ví dụ: Google Analytics hoặc những thứ khác như thế. Tôi đã thử một số cách giải quyết và nó đã được cải thiện rất nhiều, nhưng vẫn chưa hoàn hảo. Đôi khi ứng dụng đóng băng trên màn hình tải và không thể thoát ra, trừ khi bạn ngắt kết nối mạng hoặc kết nối với một mạng tốt khác. Tôi không biết làm thế nào để giải quyết vấn đề này, tôi đang cố gắng.
Felipe

1
Hoạt động hoàn hảo. Bạn có thể sử dụng mWebView.setVisibility (View.INVISIBLE) trước khi tải. Khi tải xong, đặt nó trở lại View.VISIBLE. Tôi sử dụng nó với màn hình splash này: android-developers.blogspot.de/2009/03/...
Johan Hoeksma

39
Đây không phải là một giải pháp nào cả. Không có gì đảm bảo trang đã được tải khi phương thức này được gọi.
Hawk

3
Đây là một thiết kế tồi trên phần của Google. Hầu như tất cả thời gian khi hành động này hoàn thành, bạn muốn thực hiện một cái gì đó được định hướng xung quanh Hoạt động chính, chứ không phải chính chế độ xem web. Ghi đè một chức năng thay vì đăng ký một sự kiện là một kiểu chống phổ biến và lý do tôi không thích phát triển Android.
Ryan

6
Phương pháp này không đảm bảo kết thúc tải và có thể được gọi nhiều lần nếu tải url có một số điều hướng url trung gian. Vì vậy, điều này được gọi là nhiều lần. Tuy nhiên đó là một cách để kiểm tra nó.
người mới bắt đầu

150

@ian này không chính xác 100%. Nếu bạn có một vài iframe trong một trang, bạn sẽ có nhiều onPageFinished (và onPageStarted). Và nếu bạn có một vài chuyển hướng thì nó cũng có thể thất bại. Cách tiếp cận này giải quyết (gần như) tất cả các vấn đề:

boolean loadingFinished = true;
boolean redirect = false;

mWebView.setWebViewClient(new WebViewClient() {

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) {
        if (!loadingFinished) {
            redirect = true;
        }

        loadingFinished = false;
        webView.loadUrl(urlNewString);
        return true;
    }

    @Override
    public void onPageStarted(WebView view, String url) {
        loadingFinished = false;
        //SHOW LOADING IF IT ISNT ALREADY VISIBLE  
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        if (!redirect) {
           loadingFinished = true;
            //HIDE LOADING IT HAS FINISHED
        } else {
            redirect = false; 
        }
    }
});

CẬP NHẬT:

Theo tài liệu: onPageStarted sẽ KHÔNG được gọi khi nội dung của khung nhúng thay đổi, tức là nhấp vào liên kết có mục tiêu là iframe.

Tôi đã tìm thấy một trường hợp cụ thể như thế trên Twitter khi chỉ có một trangFinished được gọi và làm rối logic một chút. Để giải quyết, tôi đã thêm một tác vụ theo lịch trình để xóa tải sau X giây. Điều này là không cần thiết trong tất cả các trường hợp khác.

CẬP NHẬT 2 :

Bây giờ với triển khai Android WebView hiện tại:

boolean loadingFinished = true;
boolean redirect = false;

    mWebView.setWebViewClient(new WebViewClient() {

        @Override
        public boolean shouldOverrideUrlLoading(
                WebView view, WebResourceRequest request) {
            if (!loadingFinished) {
               redirect = true;
            }

            loadingFinished = false;
            webView.loadUrl(request.getUrl().toString());
            return true;
        }

        @Override
        public void onPageStarted(
                WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            loadingFinished = false;
            //SHOW LOADING IF IT ISNT ALREADY VISIBLE  
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            if (!redirect) {
               loadingFinished = true;
                //HIDE LOADING IT HAS FINISHED
            } else {
                redirect = false; 
            }
        }
    });

3
Bạn có thể đã nhận thấy sự cảnh báo trong tài liệu của onPageStarted: onPageStarted sẽ KHÔNG được gọi khi nội dung của khung nhúng thay đổi, tức là nhấp vào liên kết có mục tiêu là iframe. Vì vậy, điều này có thể sai lệch logic trong những trường hợp. BTW, đơn giản hóa của @ polen có thực sự hiệu quả không?
an00b

1
Bắt đẹp, không bao giờ nhận thấy các công cụ khung. Tôi đã không thử mã của polen .. điều duy nhất tôi có thể đảm bảo rằng công việc đó là ở trên mà tôi đang sử dụng.
neteinstein

3
Chỉ là một sửa chữa nhỏ. Đó thực sự là "void void onPageStarted (WebView view, String url, Bitmap favicon)" thay vì "public void onPageStarted (WebView view, String url)"
MrMaffen

Không hoạt động đối với một số trang web mới hơn không bao giờ tải xong ... ví dụ: "Wikipedia". Bạn không bao giờ nhận được cuộc gọi onPageFinished vì đó là một chuyển hướng.
kenyee

Tôi đã thấy onPageFinished được gọi hai lần trong khi chuyển hướng. Nhưng, những gì bạn đã nói "Nếu bạn có một vài iframe trong một trang, bạn sẽ có nhiều onPageFinished (và onPageStarted)" không đúng theo tài liệu của onPageFinished: "Phương thức này chỉ được gọi cho khung chính."
garnet

40

Tôi khá là một phần đối với giải pháp @NeTeInStEiN (và @polen) nhưng sẽ triển khai nó với một bộ đếm thay vì nhiều booleans hoặc theo dõi trạng thái (chỉ là một hương vị khác nhưng tôi nghĩ có thể chia sẻ). Nó có một sắc thái JS về nó nhưng tôi cảm thấy logic dễ hiểu hơn một chút.

private void setupWebViewClient() {
    webView.setWebViewClient(new WebViewClient() {
        private int running = 0; // Could be public if you want a timer to check.

        @Override
        public boolean shouldOverrideUrlLoading(WebView webView, String urlNewString) {
            running++;
            webView.loadUrl(urlNewString);
            return true;
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            running = Math.max(running, 1); // First request move it to 1.
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            if(--running == 0) { // just "running--;" if you add a timer.
                // TODO: finished... if you want to fire a method.
            }
        }
    });
}

2
Bạn code có vẻ tốt. Tôi đã cố gắng tương tự cho webview của tôi tải từ dữ liệu html không phải url. Nhưng cái này kích hoạt onPageFinished nếu webview đầu tiên tải nhanh và trước khi cái thứ hai bắt đầu tải. Kịch bản bình thường. đang chạy = 1, đang chạy = 2, --rucky = 1, --rucky = 0. Kịch bản bất thường thất bại - đang chạy = 1, --rucky = 0, đang chạy = 1 đang chạy = 0
Ajith Memana

1
Ngoài ra còn có một kịch bản khác, khi một sự kiện không được thực hiện vì một số lý do, phần TODO sẽ không bao giờ đạt được. Vì vậy, bạn cần một bộ đếm thời gian để kiểm tra thời gian chờ. Hoặc bạn có thể gọi một hàm java đã xuất trong javascript khi bạn biết mọi thứ được tải đúng cách. Một cái gì đó như documentReady () hoặc một cái gì đó tương tự.
Codebeat

Tại sao không chỉ running = 1;trong onPageStarted()?
Choletski

@Choletski Vì tối đa 1 và số lớn hơn 1 không phải là 1.
Matthew Đọc

25

Tôi cũng tìm thấy một giải pháp tao nhã, chưa thử nghiệm nó một cách nghiêm ngặt:

public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            if (m_webView.getProgress() == 100) {
                progressBar.setVisibility(View.GONE);
                m_webView.setVisibility(View.VISIBLE);
            }
        } 

2
Tôi đã thử nghiệm nó và nó đang hoạt động hoàn hảo, tất nhiên, bạn có thể gọi nó từ bên ngoài phương thức onPageFinished và sử dụng Trình xử lý để kiểm tra trong các khoảng thời gian ngắn - trong trường hợp, bạn không muốn mở rộng lớp WebViewClient.
Gal Rom

1
Tôi tin rằng điều này có thể tốt hơn câu trả lời được chấp nhận, bạn chỉ cần kiểm tra onError và bạn đã thiết lập.
Evin1_

1
Đây phải là câu trả lời được chấp nhận.
زياد

1
Upvote cho cái này
Khdkls

23

Tôi đã đơn giản hóa mã của NeTeInStEiN như thế này:

mWebView.setWebViewClient(new WebViewClient() {
        private int       webViewPreviousState;
        private final int PAGE_STARTED    = 0x1;
        private final int PAGE_REDIRECTED = 0x2;

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) {
            webViewPreviousState = PAGE_REDIRECTED;
            mWebView.loadUrl(urlNewString);
            return true;
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            webViewPreviousState = PAGE_STARTED;
            if (dialog == null || !dialog.isShowing())
                dialog = ProgressDialog.show(WebViewActivity.this, "", getString(R.string.loadingMessege), true, true,
                        new OnCancelListener() {

                            @Override
                            public void onCancel(DialogInterface dialog) {
                                // do something
                            }
                        });
        }

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

            if (webViewPreviousState == PAGE_STARTED) {
                dialog.dismiss();
                dialog = null;
            }

        }
 });

Thật dễ hiểu, OnPageFinished nếu cuộc gọi lại trước đó là onPageStarted, vì vậy trang được tải hoàn toàn.


3
@polen PAGE_STARTED không bao giờ bị xóa? Điều gì xảy ra nếu không nên gọi làververUrlLoading ()?
an00b

20

Nếu bạn muốn hiển thị thanh tiến trình, bạn cần lắng nghe sự kiện thay đổi tiến độ, không chỉ để hoàn thành trang:

mWebView.setWebChromeClient(new WebChromeClient(){

            @Override
            public void onProgressChanged(WebView view, int newProgress) {

                //change your progress bar
            }


        });

BTW nếu bạn muốn chỉ hiển thị một ProgressBar không xác định ghi đè phương thức onPageFinished là đủ



5

Bạn có thể theo dõi các Staus Progress bởi getProgress phương pháp trong webview lớp.

Khởi tạo trạng thái tiến độ

private int mProgressStatus = 0;

sau đó AsyncTask để tải như thế này:

private class Task_News_ArticleView extends AsyncTask<Void, Void, Void> {
    private final ProgressDialog dialog = new ProgressDialog(
            your_class.this);

    // can use UI thread here
    protected void onPreExecute() {
        this.dialog.setMessage("Loading...");
        this.dialog.setCancelable(false);
        this.dialog.show();
    }

    @Override
    protected Void doInBackground(Void... params) {
        try {
            while (mProgressStatus < 100) {
                mProgressStatus = webview.getProgress();

            }
        } catch (Exception e) {

        }
        return null;

    }

    protected void onPostExecute(Void result) {
        if (this.dialog.isShowing()) {
            this.dialog.dismiss();
        }
    }
}

mProTHERStatus = webview.getProTHER (); cần được gọi từ một luồng UI.
Skynet

5

cảm ơn vì câu trả lời Nó đã giúp tôi, nhưng tôi phải cải thiện nó một chút cho nhu cầu của mình. Tôi đã có một số pagestarts và kết thúc vì vậy tôi đã thêm một bộ đếm thời gian để kiểm tra xem liệu trang đó có bắt đầu một pagestart mới hay không. Được rồi, giải thích xấu. Xem mã :)

myWebView.setWebViewClient(new WebViewClient() {
        boolean loadingFinished = true;
        boolean redirect = false;

        long last_page_start;
        long now;

        // Load the url
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (!loadingFinished) {
                redirect = true;
            }

            loadingFinished = false;
            view.loadUrl(url);
            return false;
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            Log.i("p","pagestart");
            loadingFinished = false;
            last_page_start = System.nanoTime();
            show_splash();
        }

        // When finish loading page
        public void onPageFinished(WebView view, String url) {
            Log.i("p","pagefinish");
            if(!redirect){
                loadingFinished = true;
            }
            //call remove_splash in 500 miSec
            if(loadingFinished && !redirect){
                now = System.nanoTime();
                new android.os.Handler().postDelayed(
                        new Runnable() {
                            public void run() {
                                remove_splash();
                            }
                        },
                        500);
            } else{
                redirect = false;
            }
        }
        private void show_splash() {
            if(myWebView.getVisibility() == View.VISIBLE) {
                myWebView.setVisibility(View.GONE);
                myWebView_splash.setVisibility(View.VISIBLE);
            }
        }
        //if a new "page start" was fired dont remove splash screen
        private void remove_splash() {
            if (last_page_start < now) {
                myWebView.setVisibility(View.VISIBLE);
                myWebView_splash.setVisibility(View.GONE);
            }
        }

});

2

Đây là một phương pháp mới để phát hiện khi URL đã được tải bằng cách sử dụng khả năng của Android cho các móc JavaScript . Sử dụng mẫu này, chúng tôi khai thác kiến ​​thức của JavaScript về trạng thái của tài liệu để tạo cuộc gọi phương thức gốc trong thời gian chạy Android. Các cuộc gọi có thể truy cập JavaScript này có thể được thực hiện bằng cách sử dụng@JavaScriptInterface chú thích.

Việc triển khai này yêu cầu chúng tôi gọi setJavaScriptEnabled(true)các WebViewcài đặt của, vì vậy nó có thể không phù hợp tùy thuộc vào yêu cầu của ứng dụng của bạn, ví dụ như các vấn đề bảo mật.

src / io / github / cawfree / webviewcallback / MainActivity.java (Jelly Bean, API cấp 16)

package io.github.cawfree.webviewcallback;

/**
 *  Created by Alex Thomas (@Cawfree), 30/03/2017.
 **/

import android.net.http.SslError;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

/** An Activity demonstrating how to introduce a callback mechanism into Android's WebView. */
public class MainActivity extends AppCompatActivity {

    /* Static Declarations. */
    private static final String HOOK_JS             = "Android";
    private static final String URL_TEST            = "http://www.zonal.co.uk/";
    private static final String URL_PREPARE_WEBVIEW = "";

    /* Member Variables. */
    private WebView mWebView = null;

    /** Create the Activity. */
    @Override protected final void onCreate(final Bundle pSavedInstanceState) {
        // Initialize the parent definition.
        super.onCreate(pSavedInstanceState);
        // Set the Content View.
        this.setContentView(R.layout.activity_main);
        // Fetch the WebView.
        this.mWebView = (WebView)this.findViewById(R.id.webView);
        // Enable JavaScript.
        this.getWebView().getSettings().setJavaScriptEnabled(true);
        // Define the custom WebClient. (Here I'm just suppressing security errors, since older Android devices struggle with TLS.)
        this.getWebView().setWebViewClient(new WebViewClient() { @Override     public final void onReceivedSslError(final WebView pWebView, final SslErrorHandler pSslErrorHandler, final SslError pSslError) { pSslErrorHandler.proceed(); } });
        // Define the WebView JavaScript hook.
        this.getWebView().addJavascriptInterface(this, MainActivity.HOOK_JS);
        // Make this initial call to prepare JavaScript execution.
        this.getWebView().loadUrl(MainActivity.URL_PREPARE_WEBVIEW);
    }

    /** When the Activity is Resumed. */
    @Override protected final void onPostResume() {
        // Handle as usual.
        super.onPostResume();
        // Load the URL as usual.
        this.getWebView().loadUrl(MainActivity.URL_TEST);
        // Use JavaScript to embed a hook to Android's MainActivity. (The onExportPageLoaded() function implements the callback, whilst we add some tests for the state of the WebPage so as to infer when to export the event.)
        this.getWebView().loadUrl("javascript:" + "function onExportPageLoaded() { " + MainActivity.HOOK_JS + ".onPageLoaded(); }" + "if(document.readyState === 'complete') { onExportPageLoaded(); } else { window.addEventListener('onload', function () { onExportPageLoaded(); }, false); }");
    }

    /** Javascript-accessible callback for declaring when a page has loaded. */
    @JavascriptInterface @SuppressWarnings("unused") public final void onPageLoaded() {
        // Display the Message.
        Toast.makeText(this, "Page has loaded!", Toast.LENGTH_SHORT).show();
    }

    /* Getters. */
    public final WebView getWebView() {
        return this.mWebView;
    }

}

res / layout / Activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<WebView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
/>

Về cơ bản, chúng tôi đang nối thêm một hàm JavaScript bổ sung được sử dụng để kiểm tra trạng thái của tài liệu. Nếu nó được tải, chúng tôi sẽ khởi chạy một onPageLoaded()sự kiện tùy chỉnh trong AndroidMainActivity ; mặt khác, chúng tôi đăng ký một trình lắng nghe sự kiện cập nhật Android khi trang đã sẵn sàng, sử dụng window.addEventListener('onload', ...);.

Vì chúng tôi đang nối thêm tập lệnh này sau khi cuộc gọi this.getWebView().loadURL("")được thực hiện, có thể chúng tôi không cần phải 'lắng nghe' cho các sự kiện, vì chúng tôi chỉ có cơ hội nối thêm móc nối JavaScript bằng cách thực hiện cuộc gọi liên tiếp đến loadURL, một khi trang đã được tải.


Giải pháp tuyệt vời, thường hoạt động. Tôi đang gặp vấn đề với https://reddit.com/r/Nature (nói chung với Reddit), khi bạn nhấp vào một số chủ đề và chủ đề được tải, tôi không thể bắt sự kiện đó. Bạn có thể giúp tôi không?
Primož Kralj

@ PrimožKralj Rất vui khi biết bạn có một số thành công với điều này ... Tôi không chắc nên đề xuất cụ thể điều gì, nhưng nếu có bất kỳ loại sự kiện nào mà bạn biết được kích hoạt mà bạn có thể tham gia, ví dụ như khi số bình luận được cập nhật, bạn có thể sử dụng nó như một nguồn. Bạn có nghĩ rằng có thể vấn đề của bạn có thể được khắc phục bằng cách nhấn API của Reddit trực tiếp không?
Mapsy

1
Cảm ơn, tôi sẽ có cái nhìn khác về các sự kiện được kích hoạt và cố gắng nối với một trong số chúng. Tôi biết về API và sẽ cố gắng thực hiện một giải pháp mạnh mẽ hơn bằng cách sử dụng nó trong tương lai. Cảm ơn!
Primož Kralj

1

Chỉ cần hiển thị thanh tiến trình, các phương thức "onPageStarted" và "onPageFinished" là đủ; nhưng nếu bạn muốn có cờ "is_loading" (cùng với chuyển hướng trang, ...), thì các phương thức này có thể được thực hiện với hàng không theo thứ tự, như "onPageStarted> onPageStarted> onPageFinished> onPageFinished".

Nhưng với thử nghiệm ngắn của tôi (tự kiểm tra nó.), Hàng đợi giá trị phương thức "onProTHERChanged" là "0-100> 0-100> 0-100> ..."

private boolean is_loading = false;

webView.setWebChromeClient(new MyWebChromeClient(context));

private final class MyWebChromeClient extends WebChromeClient{
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        if (newProgress == 0){
            is_loading = true;
        } else if (newProgress == 100){
            is_loading = false;
        }
        super.onProgressChanged(view, newProgress);
    }
}

Đồng thời đặt " is_loading = false" khi đóng hoạt động, nếu đó là biến tĩnh vì hoạt động có thể kết thúc trước khi kết thúc trang.


0

Đang tải url bằng SwipeRefreshLayoutProgressBar:

UrlPageActivity.java:

    WebView webView;
    SwipeRefreshLayout _swipe_procesbar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_url_page);


        String url = "http://stackoverflow.com/";

        _swipe_procesbar = (SwipeRefreshLayout)findViewById(R.id.url_path_swipe_procesbar);

        _swipe_procesbar.post(new Runnable() {
                                  @Override
                                  public void run() {
                                      _swipe_procesbar.setRefreshing(true);
                                  }
                              }
        );

        webView = (WebView) findViewById(R.id.url_page_web_view);
        webView.getSettings().setJavaScriptEnabled(true);

        webView.setWebViewClient(new WebViewClient() {
            public void onPageFinished(WebView view, String url) {
                _swipe_procesbar.setRefreshing(false);
                _swipe_procesbar.setEnabled(false);
            }
        });
        webView.loadUrl(url);
    }

Activity_url_page.xml:

<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/url_path_swipe_procesbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context="com.test.test1.UrlPageActivity">


            <WebView
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:id="@+id/url_page_web_view" />
        </RelativeLayout>

</android.support.v4.widget.SwipeRefreshLayout>

0

Đây là một phương pháp cho phép bạn đăng ký Runnableđể được thực thi khi một địa chỉ web cụ thể đã tải xong. Chúng tôi kết hợp mỗi Runnablevới một URL tương ứng Stringtrong một Map, và chúng ta sử dụng WebView's getOriginalUrl()phương pháp để lựa chọn gọi lại thích hợp.

package io.github.cawfree.webviewcallback;

/**
 *  Created by Alex Thomas (@Cawfree), 30/03/2017.
 **/

import android.net.http.SslError;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import java.util.HashMap;
import java.util.Map;

/** An Activity demonstrating how to introduce a callback mechanism into Android's WebView. */
public class MainActivity extends AppCompatActivity {

    /* Member Variables. */
    private WebView               mWebView;
    private Map<String, Runnable> mCallbackMap;

    /** Create the Activity. */
    @Override protected final void onCreate(final Bundle pSavedInstanceState) {
        // Initialize the parent definition.
        super.onCreate(pSavedInstanceState);
        // Set the Content View.
        this.setContentView(R.layout.activity_main);
        // Fetch the WebView.
        this.mWebView     = (WebView)this.findViewById(R.id.webView);
        this.mCallbackMap = new HashMap<>();
        // Define the custom WebClient. (Here I'm just suppressing security errors, since older Android devices struggle with TLS.)
        this.getWebView().setWebViewClient(new WebViewClient() {
            /** Handle when a request has been launched. */
            @Override public final void onPageFinished(final WebView pWebView, final String pUrl) {
                // Determine whether we're allowed to process the Runnable; if the page hadn't been redirected, or if we've finished redirection.
                if(pUrl.equals(pWebView.getOriginalUrl())) {
                    // Fetch the Runnable for the OriginalUrl.
                    final Runnable lRunnable = getCallbackMap().get(pWebView.getOriginalUrl());
                    // Is it valid?
                    if(lRunnable != null) { lRunnable.run(); }
                }
                // Handle as usual.
                super.onPageFinished(pWebView, pUrl);
            }
            /** Ensure we handle SSL state properly. */
            @Override public final void onReceivedSslError(final WebView pWebView, final SslErrorHandler pSslErrorHandler, final SslError pSslError) { pSslErrorHandler.proceed(); }
        });
        // Assert that we wish to visit Zonal's website.
        this.getWebView().loadUrl("http://www.zonal.co.uk/");
        // Align a Callback for Zonal; this will be serviced once the page has loaded.
        this.getCallbackMap().put("http://www.zonal.co.uk/", new Runnable() {     @Override public void run() { /* Do something. */ } });
    }

    /* Getters. */
    public final WebView getWebView() {
        return this.mWebView;
    }

    private final Map<String, Runnable> getCallbackMap() {
        return this.mCallbackMap;
    }

}

0

Trình kết xuất sẽ không hoàn thành kết xuất khi phương thức OnPageFinshed được gọi hoặc tiến trình đạt 100% nên cả hai phương thức đều không đảm bảo cho bạn rằng chế độ xem hoàn toàn được hiển thị.

Nhưng bạn có thể tìm ra từ phương thức OnLoadResource những gì đã được kết xuất và những gì vẫn được kết xuất. Và phương pháp này được gọi nhiều lần.

        @Override
        public void onLoadResource(WebView view, String url) {
            super.onLoadResource(view, url);
           // Log and see all the urls and know exactly what is being rendered and visible. If you wanna know when the entire page is completely rendered, find the last url from log and check it with if clause and implement your logic there.
            if (url.contains("assets/loginpage/img/ui/forms/")) {
                // loginpage is rendered and visible now.
               // your logic here.

            }
        }

0

Sử dụng cái này sẽ giúp.`var currentUrl = "google.com" var partOfUrl = currentUrl.subopes (0, currentUrl.length-2)

webView.setWebViewClient (đối tượng: WebViewClient () {

override fun onLoadResource(WebView view, String url) {
     //call loadUrl() method  here 
     // also check if url contains partOfUrl, if not load it differently.
     if(url.contains(partOfUrl, true)) {
         //it should work if you reach inside this if scope.
     } else if(!(currentUrl.startWith("w", true))) {
         webView.loadurl("www.$currentUrl")

     } else if(!(currentUrl.startWith("h", true))) {
         webView.loadurl("https://$currentUrl")

     } else { ...}


 }

override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {
   // you can call again loadUrl from here too if there is any error.
}

// Bạn cũng nên ghi đè phương thức ghi đè khác cho lỗi, chẳng hạn như onReceiveError để xem tất cả các phương thức này được gọi lần lượt theo cách khác và cách chúng hoạt động trong khi gỡ lỗi với điểm ngắt. } `


-1

dành cho người dùng Kotlin:

webView.webViewClient = object : WebViewClient() {
            override fun onPageFinished(view: WebView?, url: String?) {
                // do your logic
            }
        }

có rất nhiều phương thức mà bạn có thể ghi đè

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.