Использование изображений из файла расширения apk в веб-просмотре Android

У меня есть приложение для Android, которое отображает карты. Карты представляют собой изображения высокого разрешения, нарезанные на 100 фрагментов на карту для сохранения разрешения. В настоящее время у меня есть каждая карта в отдельной папке в папке с моими активами. Поскольку это делает мой apk огромным, я хочу переместить эти изображения в мой основной файл расширения apk. В настоящее время я показываю изображения в веб-просмотре, используя следующий код для объединения плиток в веб-просмотре:

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-карту?


person Javed    schedule 16.08.2012    source источник
comment
Вы когда-нибудь решали эту проблему? У меня есть решение для API 11 и выше, см. stackoverflow.com/questions/13073594/ Я использую webview.loadUrl, но я проверил, что он работает так же с webview.loadDataWithBaseURL. Тем не менее, нужно решение для API 10   -  person Chris Fawcett    schedule 30.10.2012
comment
Не удалось решить это. В настоящее время я извлекаю obb на SD-карту и использую изображения оттуда.   -  person Javed    schedule 28.11.2012


Ответы (2)


Я попытаюсь ответить новым ответом, так как мой первоначальный ответ был понижен до комментария. Я не уверен, почему, но теперь у меня есть решения для API 10 и ниже, а также для API 11 и выше. Я отправлю код, чтобы уточнить.

Для API 11 и выше просто переопределите 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

Я надеюсь, что вы найдете это полезным. Для меня это был долгий и мучительный процесс....

person Chris Fawcett    schedule 28.11.2012
comment
NanoHTTPD устарел serve(String, String, Properties...) в пользу serve(IHTTPSession), но вы можете получить все свойства одинаково – IHTTPSession.getUri() и т. д. - person AndyC; 23.09.2013

Это хорошая альтернатива использованию инструментов JOBB для упаковки файла расширения и использования StorageManager, чтобы смонтировать его. После этого файлы внутри файла расширения должны быть доступны как обычные файлы в файловой системе. Распаковка файла расширения в этом случае не требуется.

person Aleksei    schedule 05.11.2013
comment
Спасибо! Я подумал, что это отличный подход. Я написал сообщение в блоге, в котором описал, как я его реализовал: saveme-dot-txt.blogspot.com/2016/06/ - person Mike M; 14.06.2016