2012-02-15 5 views
13

Tuve un problema que me ha plagado durante días. Resultó que se trataba de un error de Android y se envió, confirmó y, con suerte, se solucionará en una versión futura. Ahora he encontrado una solución que funciona para mí, y la proporcionaré a continuación, sin embargo, la solución no es perfecta, ya que implica la edición de la fuente de brecha telefónica. Principalmente, mi pregunta es si alguien puede encontrar una mejor solución a este problema.Problema con la carga de archivos javascript locales dentro de una vista web

Error:
Hay un error cuando intenta cargar una página dentro de un WebView en Android 3.0+. El problema es que si esa página hace referencia a cualquier archivo javascript local, no se pueden agregar datos de consulta a la url. Básicamente

Esto funciona:
<script type="text/javascript" src="StaticJS.js"></script>

esto no funciona:
<script type="text/javascript" src="StaticJS.js?var=val"></script>

¿Por qué demonios alguien querría hacer esto desde el archivo, obviamente, no puede hacer nada con el vals de consulta? Bueno, para mí tengo una aplicación de phonegap que carga un archivo de configuración a través de JSONP; sin embargo, si no se especifica un archivo de configuración, se establece de manera predeterminada en un archivo local. Entonces, sí, el archivo no puede procesar los datos de la consulta, pero sería bueno usar el mismo formato de archivo y estructura de carga.


Solución 1 (no PhoneGap)

Así que no es una solución fácil para esto si la plataforma androide objetivo 11 (Honeycomb) o superior. (Siempre que tenga cuidado y no use ningún método que no exista en niveles de API más bajos, este código se ejecutará en < 11 apis, pero igual tendrá que establecer 11 como su objetivo)

Básicamente usted agrega un WebViewClient para WebView que utiliza el método shouldInterceptRequest para interceptar la carga de archivos js locales con datos de consulta adjuntos.

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; 
     } 
    } 

} 

Para establecer el WebViewClient, el código podría ser algo como esto:

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"); 
    } 
} 

Solución 2 (PhoneGap)

Ahora, para Phonegap no tengo una solución limpia . Mi solución es ir y descargar el código fuente Phonegap y editar el CordovaWebViewClient añadiendo el siguiente método:

@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; 
    } 
} 

Solución 3 (inexistente)

Esta solución se espera pueda ser algún fácil incluir Clasifique o modifique la actividad principal para que pueda usar la brecha telefónica, pero solo podría usar un archivo .jar del código, lo que facilita las actualizaciones.

Respuesta

1

Los datos de consulta se añaden a los archivos javascript (y a otros tipos de archivos como css) para evitar el almacenamiento en caché del navegador. Los datos de consulta son inútiles para el archivo, pero el navegador lo trata como nuevo porque la ubicación ha cambiado (a los ojos del navegador) y carga una copia nueva.

Me alegro de que hayas encontrado una respuesta a tu problema, solo pensé en dar mi opinión de por qué las personas usan este método.

+0

El tema aquí no es el almacenamiento en caché del navegador, pero el hecho de que los archivos no se cargan si agrega datos de consulta – jtymann

+0

entendido. Solo quería ayudar cuando vi esta parte de su pregunta: "¿Por qué diablos alguien querría hacer esto ya que el archivo obviamente no puede hacer nada con la consulta vals?" –

2

Gracias por esta publicación, me ha explicado la última solución que es simplemente utilizar IceCreamCordovaWebViewClient.

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