我设法在我的一个使用 WebView 的应用程序的本地存储中缓存音频文件。这意味着音频文件被截取,如果缓存中不可用,则下载它们,然后从缓存中提供。缓存在手机在 Android 10 上重新启动后仍然存在。
这些是我用于 WebView 的设置:
@SuppressLint("SetJavaScriptEnabled")
public static void setupWebview(WebView webView) {
WebSettings settings = webView.getSettings();
settings.setLoadWithOverviewMode(true);
settings.setUseWideViewPort(true);
settings.setAllowFileAccess(true);
settings.setAllowContentAccess(true);
settings.setAllowFileAccessFromFileURLs(true);
settings.setAllowUniversalAccessFromFileURLs(true);
settings.setBlockNetworkImage(false);
settings.setBlockNetworkLoads(false);
settings.setLoadsImagesAutomatically(true);
settings.setMediaPlaybackRequiresUserGesture(false);
settings.setDomStorageEnabled(true);
settings.setLoadWithOverviewMode(true);
settings.setJavaScriptEnabled(true);
settings.setAllowUniversalAccessFromFileURLs(true);
settings.setDatabaseEnabled(true);
settings.setAppCacheEnabled(true);
settings.setAppCachePath("/beezone");
}
我已经为同一个WebView使用了自定义的WebClient:
所以基本上自定义的WebClient 看起来像这样:
mWebView.setWebViewClient(new WebViewClient() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Nullable
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
return cacheM4a(request, context);
}
@Nullable
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
return cacheM4a(Uri.parse(url), context);
}
});
方法cacheM4a的相关代码如下:
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Nullable
public static WebResourceResponse cacheM4a(WebResourceRequest request, Context context) {
Uri source = request.getUrl();
return cacheM4a(source, context);
}
@Nullable
public static WebResourceResponse cacheM4a(Uri source, Context context) {
String sourceStr = source.toString();
if (sourceStr.endsWith(CacheHelper.MAIN_AUDIO_FORMAT)) {
String language = LanguageHelper.INSTANCE.getLanguage();
String absolutePath = context.getCacheDir().getAbsolutePath();
String langPath = String.format("%s/%s", absolutePath, language);
boolean folderExists = createLanguageCachePath(langPath);
if(!folderExists) {
try {
return new WebResourceResponse("audio/mp4", "binary", new URL(sourceStr).openStream());
} catch (IOException e) {
Log.e(TAG, "Failed to read directly from the web", e);
return null;
}
}
String targetPath = String.format("%s/%s", langPath, source.getLastPathSegment());
File file = new File(targetPath);
if (!file.exists()) {
if (saveToCache(sourceStr, targetPath)) return null;
}
// Always read from cache.
try {
FileInputStream fis = new FileInputStream(new File(targetPath));
WebResourceResponse response = new WebResourceResponse("audio/mp4", "binary", fis);
return response;
} catch (IOException e) {
Log.e(TAG, "Failed to read cache", e);
return null;
}
}
return null;
}
private static boolean saveToCache(String sourceStr, String targetPath) {
// File is not present in cache and thus needs to be downloaded
try (InputStream in = new URL(sourceStr).openStream();
FileOutputStream fos = new FileOutputStream(new File(targetPath))) {
ByteStreams.copy(in, fos);
} catch (IOException e) {
Log.e(TAG, "Failed to save in cache", e);
return true;
}
return false;
}
private static boolean createLanguageCachePath(String langPath) {
File langPathFile = new File(langPath);
if(!langPathFile.exists()) {
if(!langPathFile.mkdirs()) {
Log.e(TAG, String.format("Could not create %s", langPathFile));
return false;
};
}
return true;
}
这些是我使用的权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />