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

时间:2012-08-16 11:41:22

标签: android image webview apk expansion

我有一个显示地图的Android应用程序。这些地图是高分辨率图像,每个地图切成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解压缩到SD卡的情况下使用图像?

2 个答案:

答案 0 :(得分:3)

我将尝试回复一个新的答案,因为我的原始答案被降级为评论。我不确定为什么,但我现在已经为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,找到方法服务并让它从扩展文件将输入流返回到您的文件:

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方法

我希望你觉得这很有帮助。对我来说这是一个漫长而痛苦的过程......

答案 1 :(得分:1)

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