在android webview中使用apk扩展文件中的图像

Posted

技术标签:

【中文标题】在android webview中使用apk扩展文件中的图像【英文标题】:Using images from apk expansion file in android webview 【发布时间】:2012-08-12 18:05:16 【问题描述】:

我有一个显示地图的安卓应用。这些地图是高分辨率图像,每张地图切成 100 个图块以保持分辨率。我目前将每张地图放在资产文件夹中的单独文件夹中。由于这使我的 apk 很大,我想将这些图像移动到我的主 apk 扩展文件中。 目前我正在使用以下代码在 webview 中显示图像,以便在 webview 中将图块拼接在一起:

class ShowMapTask extends AsyncTask<String, Void, String> 

    @Override
    protected String doInBackground(String... maps) 
        String html = "<html><table cellpadding=\"0\" border=\"0\" cellspacing=\"0.0\">";
        for (int i = 0; i < 10; i++) 
            html += "<tr>";
            for (int j = 0; j < 10; j++)
                html += "<td><img src=\"maps/" + maps[0] + "/slice_" + i
                        + "_" + j + ".png\"></td>";
            html += "</tr>";
        
        return html + "</table></html>";
    

    @Override
    protected void onPostExecute(String result) 
        WebView wv = (WebView) context.findViewById(R.id.webView);
        wv.getSettings().setSupportZoom(true);
        wv.getSettings().setBuiltInZoomControls(true);
        wv.getSettings().setUseWideViewPort(true);
        wv.getSettings().setLoadWithOverviewMode(true);
        wv.loadDataWithBaseURL("file:///android_asset/", result,
                "text/html", "utf-8", null);
        super.onPostExecute(result);
    

如何迁移到 apk 扩展文件?是否可以在不将 obb 解压缩到 sdcard 的情况下使用图像?

【问题讨论】:

你解决过这个问题吗?我有 API 11 及更高版本的解决方案,请参阅***.com/questions/13073594/… 我正在使用 webview.loadUrl,但我已经验证它与 webview.loadDataWithBaseURL 的工作原理相同,但仍然需要 API 10 的解决方案 无法解决这个问题。我目前正在将 obb 提取到 sdcard 并使用那里的图像。 【参考方案1】:

由于我的原始答案已降级为评论,因此我将尝试使用新答案进行回复。我不知道为什么,但我现在确实有针对 API 10 及更低版本以及 API 11 及更高版本的解决方案。我将发布代码以澄清。

对于 API 11 及更高版本,只需在您的 webview 客户端中覆盖 ShouldInterceptRequest,

对于 API 10 及以下版本,请使用此 http 侦听器,http://elonen.iki.fi/code/nanohttpd/,

将这两种方法放在一起,对我来说相关的代码是:

final String assetPrefix = "file:///android_asset/";
final String httpPrefix = "http://localhost:8001";

// for me this part is in onCreateView after the webview settings bit...


    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        webView.setWebViewClient(new HoneyCombWebViewClient());
    else
        webView.setWebViewClient(new MyWebViewClient());    

    webViewLoadUrl();


private void webViewLoadUrl() 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 

        curURL = assetPrefix + curFileName;


        webView.loadUrl(curURL);
    
    else
    
        curURL = httpPrefix + '/' + curFileName;

        String str = assetFileToString(curFileName);        
        webView.loadDataWithBaseURL(httpPrefix, str, "text/html", "UTF-8", null);    
    


// then for the WebViewClient
private class HoneyCombWebViewClient extends MyWebViewClient 

    public WebResourceResponse shouldInterceptRequest(WebView view, String url)
    
                    // remove the asset prefix from the url
        String fileName = url.substring(assetPrefix.length() - 1);

                    // ExpansionFiles is the pointer to your ZipResourceFile
        InputStream inputStream = ExpansionFiles.getWebResource(fileName);

        if (url.endsWith("jpg") || url.endsWith("png"))
            return new WebResourceResponse("image/*", "base64", inputStream);

        return super.shouldInterceptRequest(view, url);
    


private class MyWebViewClient extends WebViewClient 
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) 

            else if (url.startsWith(httpPrefix)) 

            curURL = url;

            String str = assetFileToString(url.substring(httpPrefix.length() + 1));

            webView.loadDataWithBaseURL(httpPrefix, str, "text/html", "UTF-8", null); 
            return true;
        
        else if (url.startsWith(assetPrefix))
            curURL = url;

            view.loadUrl(url);
            return true;        
        
        // else.....
    

最后,要使用 NanoHTTPD,找到方法 serve 并将输入流从扩展文件返回到您的文件:

public Response serve( String uri, String method, Properties header, Properties parms, Properties files )

    InputStream data = ExpansionFiles.getWebResource(uri);

    String mimeType;
    if (uri.endsWith("jpg") || uri.endsWith("png"))
        mimeType = "base64";
    else if (uri.endsWith("css"))
        mimeType = "text/css";
    else if (uri.endsWith("js"))
        mimeType = "text/javascript";
    else
        mimeType = "text/html";

    return new Response( HTTP_OK, mimeType, data );

在顶层某处调用构造函数:

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) 
    // this for loading images from expansion file under webview in API 10
    try
    
        webServer = new NanoHTTPD(8001, new File("."));
    
    catch( IOException ioe )
    
        System.err.println( "Couldn't start server:\n" + ioe );
        System.exit( -1 );
    

哦,你需要从 NanoHTTPD 中删除 main 方法

我希望这对您有所帮助。这对我来说是一个漫长而痛苦的过程......

【讨论】:

NanoHTTPD 已经弃用了 serve(String, String, Properties...) 取而代之的是 serve(IHTTPSession),但是你可以得到相同的所有属性 - IHTTPSession.getUri() 等等。 【参考方案2】:

使用JOBB工具打包扩展文件并使用StorageManager挂载是一个不错的选择。之后,扩展文件中的文件应该可以作为文件系统中的常规文件访问。这种情况下不需要解压扩展文件。

【讨论】:

谢谢!我认为这是一个很好的方法。我写了一篇博客文章,描述了我是如何实现它的:saveme-dot-txt.blogspot.com/2016/06/…

以上是关于在android webview中使用apk扩展文件中的图像的主要内容,如果未能解决你的问题,请参考以下文章

android webview 强制横屏

Android中webView的基础使用

Android分享笔记 Android的webview加载本地html本apk内html和远程URL

反应原生 - 构建发布 apk 时 webview 不呈现本地 html

WebView的基础用法

Android - 在片段中显示 WebView