/* * Copyright (c) 2016 Ha Duy Trung * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.github.hidroh.materialistic.widget; import android.annotation.SuppressLint; import android.content.Context; import android.net.Uri; import android.os.Build; import android.support.annotation.CallSuper; import android.text.TextUtils; import android.util.AttributeSet; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebViewClient; import java.io.File; import java.util.Map; import io.github.hidroh.materialistic.AppUtils; public class CacheableWebView extends WebView { private static final String CACHE_PREFIX = "webarchive-"; private static final String CACHE_EXTENSION = ".mht"; private ArchiveClient mArchiveClient = new ArchiveClient(); public CacheableWebView(Context context) { this(context, null); } public CacheableWebView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CacheableWebView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } @Override public void reloadUrl(String url) { super.reloadUrl(getCacheableUrl(url)); } @Override public void loadUrl(String url) { if (TextUtils.isEmpty(url)) { return; } mArchiveClient.lastProgress = 0; super.loadUrl(getCacheableUrl(url)); } @Override public void loadUrl(String url, Map<String, String> additionalHttpHeaders) { if (TextUtils.isEmpty(url)) { return; } mArchiveClient.lastProgress = 0; super.loadUrl(getCacheableUrl(url), additionalHttpHeaders); } @Override public void setWebChromeClient(WebChromeClient client) { if (!(client instanceof ArchiveClient)) { throw new IllegalArgumentException("client should be an instance of " + ArchiveClient.class.getName()); } mArchiveClient = (ArchiveClient) client; super.setWebChromeClient(mArchiveClient); } private void init() { enableCache(); setLoadSettings(); setWebViewClient(new WebViewClient()); setWebChromeClient(mArchiveClient); } private void enableCache() { WebSettings webSettings = getSettings(); webSettings.setAppCacheEnabled(true); webSettings.setAllowFileAccess(true); webSettings.setAppCachePath(getContext().getApplicationContext() .getCacheDir().getAbsolutePath()); setCacheModeInternal(); } private void setCacheModeInternal() { getSettings().setCacheMode(AppUtils.hasConnection(getContext()) ? WebSettings.LOAD_CACHE_ELSE_NETWORK : WebSettings.LOAD_CACHE_ONLY); } @SuppressLint("SetJavaScriptEnabled") private void setLoadSettings() { WebSettings webSettings = getSettings(); webSettings.setLoadWithOverviewMode(true); webSettings.setUseWideViewPort(true); webSettings.setJavaScriptEnabled(true); } private String getCacheableUrl(String url) { if (TextUtils.equals(url, BLANK) || TextUtils.equals(url, FILE)) { return url; } mArchiveClient.cacheFileName = generateCacheFilename(url); setCacheModeInternal(); if (getSettings().getCacheMode() != WebSettings.LOAD_CACHE_ONLY) { return url; } File cacheFile = new File(mArchiveClient.cacheFileName); return cacheFile.exists() ? Uri.fromFile(cacheFile).toString() : url; } private String generateCacheFilename(String url) { return getContext().getApplicationContext().getCacheDir().getAbsolutePath() + File.separator + CACHE_PREFIX + url.hashCode() + CACHE_EXTENSION; } public static class ArchiveClient extends WebChromeClient { int lastProgress = 0; String cacheFileName = null; @CallSuper @Override public void onProgressChanged(android.webkit.WebView view, int newProgress) { if (view.getSettings().getCacheMode() == WebSettings.LOAD_CACHE_ONLY) { return; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && cacheFileName != null && lastProgress != 100 && newProgress == 100) { lastProgress = newProgress; view.saveWebArchive(cacheFileName); } } } }