Проблема с загрузкой локальных файлов JavaScript внутри веб-просмотра - PullRequest
13 голосов
/ 16 февраля 2012

У меня была проблема, которая мучила меня несколько дней. Оказалось, что это был глюк Android, и он был представлен, подтвержден и, надеюсь, будет исправлен в следующем выпуске. Теперь я нашел решение, которое работает для меня, и предоставлю его ниже, однако решение не является идеальным, поскольку включает в себя редактирование источника пропусков телефона. Главным образом мой вопрос заключается в том, может ли кто-то найти лучшее решение этой проблемы.

Ошибка:
При попытке загрузить страницу внутри WebView на Android 3.0+ возникает сбой. Проблема заключается в том, что если эта страница ссылается на какие-либо локальные файлы JavaScript, вы не можете добавить данные запроса в URL. В основном

Это работает:
<script type="text/javascript" src="StaticJS.js"></script>

Это не работает:
<script type="text/javascript" src="StaticJS.js?var=val"></script>

Какого черта кто-то захочет это сделать, поскольку файл, очевидно, ничего не может сделать с значениями запроса? Для меня у меня есть приложение phonegap, которое загружает файл настроек через JSONP, однако, если файл настроек не указан, по умолчанию используется локальный файл. Так что да, файл не может обработать данные запроса, но было бы неплохо использовать тот же формат файла и структуру загрузки.


Решение 1 (не PhoneGap)

Так что есть простое решение, если целевая платформа для Android - 11 (Honeycomb) или выше. (Пока вы осторожны и не используете какой-либо метод, который не существует ни на одном более низком уровне API, этот код будет работать на уровне <11 apis, но вам все равно придется установить 11 в качестве цели) </p>

По сути, вы добавляете WebViewClient в WebView, который использует метод shouldInterceptRequest для перехвата загрузки локальных js-файлов с прикрепленными данными запроса.

import java.io.IOException;
import java.io.InputStream;

import android.content.res.AssetManager;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class PatchingWebViewClient extends WebViewClient{

    AssetManager am;

    public PatchingWebViewClient(AssetManager am){
        this.am = am;
    }

    @Override
    public WebResourceResponse shouldInterceptRequest (WebView view, String url){
        if(url.indexOf("file:///android_asset") == 0 && url.contains("?")){
            String filePath = url.substring(22, url.length());
            filePath = filePath.substring(0, filePath.indexOf("?"));
            try {
                InputStream is = am.open(filePath);
                WebResourceResponse wr = new WebResourceResponse("text/javascript", "UTF-8", is);
                return wr;
            } catch (IOException e) {
                return null;
            }
        }else{
            return null;
        }
    }

}

Чтобы установить WebViewClient, ваш код должен выглядеть примерно так:

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;

public class CanWeBreakAWebViewActivity extends Activity {
    WebView mWebView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mWebView = (WebView) findViewById(R.id.webview);
        mWebView.getSettings().setJavaScriptEnabled(true);
        mWebView.setWebViewClient(new PatchingWebViewClient(this.getAssets()));
        mWebView.loadUrl("file:///android_asset/index.html");
    }
}

Решение 2 (PhoneGap)

Теперь для Phonegap у меня нет чистого решения. Мое решение состоит в том, чтобы пойти и загрузить исходный код Phonegap и отредактировать CordovaWebViewClient, добавив следующий метод:

@Override
public WebResourceResponse shouldInterceptRequest (WebView view, String url){
    if(url.indexOf("file:///android_asset") == 0 && url.contains("?")){
        String filePath = url.substring(22, url.length());
        filePath = filePath.substring(0, filePath.indexOf("?"));
        try {
            InputStream is = ctx.getAssets().open(filePath);
            WebResourceResponse wr = new WebResourceResponse("text/javascript", "Cp1252", is);
            return wr;
        } catch (IOException e) {
            return null;
        }
    }else{
        return null;
    }
}

Решение 3 (Не существует)

Надеемся, что это решение было бы легко включить класс или настроить в основной вид деятельности, чтобы можно было использовать пробел в телефоне, но можно было просто использовать файл кода .jar, упрощая обновления.

Ответы [ 2 ]

2 голосов
/ 05 июня 2013

Спасибо за этот пост, вы сообщили мне о новейшем решении, которое заключается в простом использовании IceCreamCordovaWebViewClient.

@Override
    public void init() {
    super.init(webView, new IceCreamCordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}
1 голос
/ 16 февраля 2012

Данные запроса добавляются в файлы javascript (и другие типы файлов, такие как css) для предотвращения кэширования в браузере.Данные запроса бесполезны для файла, но браузер воспринимает его как новый, поскольку местоположение меняется (в глазах браузера) и загружается свежая копия.ваша проблема, просто подумал, что я хотел бы дать свой вклад в то, почему люди используют этот метод.

...