2

我有一个显示地图的 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 解压缩到 sdcard 的情况下使用图像?

4

2 回答 2

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,找到方法 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 方法

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

于 2012-11-28T22:22:47.263 回答
1

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

于 2013-11-05T16:06:29.717 回答