software - Android WebView-> Visualizar WebArchive
webview interface android (2)
Actualización febrero 21, 2014
Mi respuesta publicada a continuación no se aplica a los archivos de archivos web guardados en Android 4.4 KitKat y posteriores. El método saveWebArchive () de WebView en Android 4.4 "KitKat" (y probablemente también las versiones más recientes) no guarda el archivo web en el código XML que este código de lector publicó a continuación. En su lugar, guarda las páginas en formato MHT (MHTML). Es fácil volver a leer los archivos .mht; solo use:
webView.loadUrl("file:///my_dir/mySavedWebPage.mht");
Eso es todo, mucho más fácil que el método anterior y compatible con otras plataformas.
Publicado anteriormente
Yo mismo lo necesitaba, y dondequiera que busqué, hubo preguntas sin respuesta como esta. Así que tuve que resolverlo yo mismo. A continuación se encuentra mi pequeña clase WebArchiveReader y código de ejemplo sobre cómo usarlo. Tenga en cuenta que a pesar de que la documentación de Android declara que se ha agregado shouldInterceptRequest () a WebViewClient en API11 (Honeycomb), este código funciona y se probó con éxito en emuladores de Android hasta API8 (Froyo). A continuación se encuentra todo el código que se necesita, también subí el proyecto completo al repositorio de GitHub en https://github.com/gregko/WebArchiveReader
Archivo WebArchiveReader.java:
package com.hyperionics.war_test;
import android.util.Base64;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
public abstract class WebArchiveReader {
private Document myDoc = null;
private static boolean myLoadingArchive = false;
private WebView myWebView = null;
private ArrayList<String> urlList = new ArrayList<String>();
private ArrayList<Element> urlNodes = new ArrayList<Element>();
abstract void onFinished(WebView webView);
public boolean readWebArchive(InputStream is) {
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
myDoc = null;
try {
builder = builderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
try {
myDoc = builder.parse(is);
NodeList nl = myDoc.getElementsByTagName("url");
for (int i = 0; i < nl.getLength(); i++) {
Node nd = nl.item(i);
if(nd instanceof Element) {
Element el = (Element) nd;
// siblings of el (url) are: mimeType, textEncoding, frameName, data
NodeList nodes = el.getChildNodes();
for (int j = 0; j < nodes.getLength(); j++) {
Node node = nodes.item(j);
if (node instanceof Text) {
String dt = ((Text)node).getData();
byte[] b = Base64.decode(dt, Base64.DEFAULT);
dt = new String(b);
urlList.add(dt);
urlNodes.add((Element) el.getParentNode());
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
myDoc = null;
}
return myDoc != null;
}
private byte [] getElBytes(Element el, String childName) {
try {
Node kid = el.getFirstChild();
while (kid != null) {
if (childName.equals(kid.getNodeName())) {
Node nn = kid.getFirstChild();
if (nn instanceof Text) {
String dt = ((Text)nn).getData();
return Base64.decode(dt, Base64.DEFAULT);
}
}
kid = kid.getNextSibling();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public boolean loadToWebView(WebView v) {
myWebView = v;
v.setWebViewClient(new WebClient());
WebSettings webSettings = v.getSettings();
webSettings.setDefaultTextEncodingName("UTF-8");
myLoadingArchive = true;
try {
// Find the first ArchiveResource in myDoc, should be <ArchiveResource>
Element ar = (Element) myDoc.getDocumentElement().getFirstChild().getFirstChild();
byte b[] = getElBytes(ar, "data");
// Find out the web page charset encoding
String charset = null;
String topHtml = new String(b).toLowerCase();
int n1 = topHtml.indexOf("<meta http-equiv=/"content-type/"");
if (n1 > -1) {
int n2 = topHtml.indexOf(''>'', n1);
if (n2 > -1) {
String tag = topHtml.substring(n1, n2);
n1 = tag.indexOf("charset");
if (n1 > -1) {
tag = tag.substring(n1);
n1 = tag.indexOf(''='');
if (n1 > -1) {
tag = tag.substring(n1+1);
tag = tag.trim();
n1 = tag.indexOf(''/"'');
if (n1 < 0)
n1 = tag.indexOf(''/''');
if (n1 > -1) {
charset = tag.substring(0, n1).trim();
}
}
}
}
}
if (charset != null)
topHtml = new String(b, charset);
else
topHtml = new String(b);
String baseUrl = new String(getElBytes(ar, "url"));
v.loadDataWithBaseURL(baseUrl, topHtml, "text/html", "UTF-8", null);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
private class WebClient extends WebViewClient {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if (!myLoadingArchive)
return null;
int n = urlList.indexOf(url);
if (n < 0)
return null;
Element parentEl = urlNodes.get(n);
byte [] b = getElBytes(parentEl, "mimeType");
String mimeType = b == null ? "text/html" : new String(b);
b = getElBytes(parentEl, "textEncoding");
String encoding = b == null ? "UTF-8" : new String(b);
b = getElBytes(parentEl, "data");
return new WebResourceResponse(mimeType, encoding, new ByteArrayInputStream(b));
}
@Override
public void onPageFinished(WebView view, String url)
{
// our WebClient is no longer needed in view
view.setWebViewClient(null);
myLoadingArchive = false;
onFinished(myWebView);
}
}
}
Aquí es cómo usar esta clase, muestra la clase MyActivity.java:
package com.hyperionics.war_test;
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.io.IOException;
import java.io.InputStream;
public class MyActivity extends Activity {
// Sample WebViewClient in case it was needed...
// See continueWhenLoaded() sample function for the best place to set it on our webView
private class MyWebClient extends WebViewClient {
@Override
public void onPageFinished(WebView view, String url)
{
Lt.d("Web page loaded: " + url);
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView webView = (WebView) findViewById(R.id.webView);
try {
InputStream is = getAssets().open("TestHtmlArchive.xml");
WebArchiveReader wr = new WebArchiveReader() {
void onFinished(WebView v) {
// we are notified here when the page is fully loaded.
continueWhenLoaded(v);
}
};
// To read from a file instead of an asset, use:
// FileInputStream is = new FileInputStream(fileName);
if (wr.readWebArchive(is)) {
wr.loadToWebView(webView);
}
} catch (IOException e) {
e.printStackTrace();
}
}
void continueWhenLoaded(WebView webView) {
Lt.d("Page from WebArchive fully loaded.");
// If you need to set your own WebViewClient, do it here,
// after the WebArchive was fully loaded:
webView.setWebViewClient(new MyWebClient());
// Any other code we need to execute after loading a page from a WebArchive...
}
}
Para completar las cosas, aquí está mi pequeña clase Lt.java para salida de depuración:
package com.hyperionics.war_test;
import android.util.Log;
public class Lt {
private static String myTag = "war_test";
private Lt() {}
static void setTag(String tag) { myTag = tag; }
public static void d(String msg) {
// Uncomment line below to turn on debug output
Log.d(myTag, msg == null ? "(null)" : msg);
}
public static void df(String msg) {
// Forced output, do not comment out - for exceptions etc.
Log.d(myTag, msg == null ? "(null)" : msg);
}
}
Espero que esto sea de ayuda.
Actualización 19 de julio de 2013
Algunas páginas web no tienen etiquetas meta que especifican la codificación de texto, y luego el código que mostramos arriba no muestra los caracteres correctamente. En la versión de GitHub de este código, ahora agregué un algoritmo de detección de juego de caracteres, que adivina la codificación en tales casos. Nuevamente, vea https://github.com/gregko/WebArchiveReader
Greg
WebView de Android tiene este método saveWebArchive desde el nivel de API 11: http://developer.android.com/ .
Puede guardar sitios web completos como archivos web, lo que es genial! Pero, ¿cómo puedo obtener los contenidos descargados de nuevo en una vista web? Lo intenté
webview.loadUrl(Uri.fromFile(mywebarchivefile));
Pero eso solo muestra xml en la pantalla.
He encontrado una manera indocumentada de leer el archivo web guardado. Solo haz:
String raw_data = (read the mywebarchivefile as a string)
y luego llamar
webview.loadDataWithBaseURL(mywebarchivefile, raw_data, "application/x-webarchive-xml", "UTF-8", null);
La referencia: http://androidxref.com/4.0.4/xref/external/webkit/Source/WebCore/loader/archive/ArchiveFactory.cpp
Disponible desde Android 3.0, api nivel 11.