Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save webview content for offline browsing?

I would like to implement an apps that allow users save the webpage including images. Then the users can view the web page again even there is no network access. However, I found that there is no such related API to do so. Does anyone have idea or experience? can any one give some idea or source code link?

like image 886
Ramz Avatar asked Jan 09 '12 07:01

Ramz


2 Answers

At least for basic pages, this should be possible.

(1) Download the HTML file instead of loading it directly into the WebView. Then use WebView.loadData() or WebView.loadDataWithBaseUrl() to load the page into the view. Don't trash the html, you'll need it later.

(2) Set your own WebViewClient which overrides [at least] onLoadResource(). Then save every single resource requested by the page.

(3) Now you have the HTML stored, and all the necessary files on the filesystem. Search through the HTML for absolute paths, you'll want to update these with a replacement function so they are either relative paths (and will work on the filesystem) or absolute paths to where you saved the images/css/etc. (on the filesystem)

(4) Write the html to the filesystem.

I hope this helps.

Alternatively, you could probably save the page as an image, essentially taking a screenshot of the WebView. This wouldn't allow for copy/paste, or clicking of links, but it would be much simpler if all you need is "view this again later".

like image 110
Matt Avatar answered Oct 28 '22 02:10

Matt


You can use saveWebArchive. If you want to also save the resources that are refered to on the page via url such as images, you need to override onLoadResource().

static WebView getWebView(Activity activity, int id, String url) {
    WebView w1 = activity.findViewById(id);
    WebSettings wSettings = w1.getSettings();
    wSettings.setJavaScriptEnabled(true);
    wSettings.setAllowFileAccess(true);
    wSettings.setAppCacheEnabled(true);
    wSettings.setAppCachePath(activity.getBaseContext().getCacheDir().getAbsolutePath());
    wSettings.setJavaScriptCanOpenWindowsAutomatically(true);
    wSettings.setSavePassword(true);
    wSettings.setSaveFormData(true);
    wSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
    wSettings.setUserAgentString("Android");
    w1.setWebViewClient(new WebViewClient() {
        boolean err;

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
            return true;
        }

        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            view.setVisibility(View.GONE);
            err = true;
        }

        public void onPageFinished(WebView view, String url) {
//                super.onPageFinished(view, url);
            if (!err) {
                if (!url.endsWith(".mht")) {
                    File f = getFileFromUrl(url);
                    view.saveWebArchive(f.getAbsolutePath());
                }
                view.setVisibility(VISIBLE);
            }
        }

        @Override
        public void onLoadResource(WebView view, String url) {
            File f = getFileFromUrl(url);
            if(f.exists()) url = "file:///" + f.getAbsolutePath();
            else {
                new Thread(()->{

                }).start();
            }
            super.onLoadResource(view, url);
        }
    });
    w1.setWebChromeClient(new WebChromeClient());
    File f = getFileFromUrl(url);
    if (f.exists() && f.lastModified() > new Date().getTime() - 5 * 24 * 3600000) w1.loadUrl("file:///" + f.getAbsolutePath());
    else w1.loadUrl(url);
    return w1;
}
like image 20
mayank1513 Avatar answered Oct 28 '22 01:10

mayank1513