Подтвердить что ты не робот

Проблема с загрузкой локальных файлов javascript внутри webview

У меня была проблема, которая мучила меня в течение нескольких дней. Оказалось, что это был глюк 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>

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


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

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

В основном вы добавляете 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 кода, упростив обновление.

4b9b3361

Ответ 1

Спасибо за этот пост, вы указали мне на последнее решение, которое просто использует IceCreamCordovaWebViewClient.

@Override
    public void init() {
    super.init(webView, new IceCreamCordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}

Ответ 2

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

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