I have noticed that for Android 4.4 handsets, saving a webview with:
webview.saveWebArchive(name);
and reading it after with WebArchiveReader WebArchiveReader (see code below) throws an Encoding Exception:
11-08 15:10:31.976: W/System.err(2240): org.xml.sax.SAXParseException: Unexpected end of document
11-08 15:10:31.976: W/System.err(2240): at org.apache.harmony.xml.parsers.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:125)
The method used to read the stored XML file worked perfectly fine until 4.3 and it is (NOTE: I tried to parse it in two different ways):
public boolean readWebArchive(InputStream is) {
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
myDoc = null;
try {
builder = builderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
try {
//New attempt
InputSource input = new InputSource(is);
input.setEncoding("UTF-8");
myDoc = builder.parse(input);
//This used to be the way it used to work for
//Android 4.3 and below without trouble
//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 (SAXParseException se){
//Some problems parsing the saved XML file
se.printStackTrace();
myDoc = null;
} catch (Exception e) {
e.printStackTrace();
myDoc = null;
}
return myDoc != null;
}
I've played a bit with the way the buider is invoked. Instead of giving it a FileInputStream, I first create an InputSource as you can see to force a given encoding. However, I had no success. By not including the InputSource, the exception was instead:
org.xml.SAXParseException: Unexpected token
I've read in previous posts that this may be an encoding issue (e.g. android-utf-8-file-parsing) but none of the proposed solutions worked for me.
Does anyone else have the same issue or does anyone know what has changed on Kit Kat, and if so, how could it be avoided?
Many thanks in advance
My WebArchiveReader code is not needed under Android 4.4 KitKat and newer to read back a saved web archive. If you save your page with webview.saveWebArchive(name); method on KitKat, you get an MHTML formatted file, as "#Dragon warrior" indicates above. To read this file back into webview, just use:
webView.loadUrl("file:///my_folder/mySavedPage.mht");
Just make sure to give your file the .mht or .mhtml extension, so that WebView recognizes its contents. Otherwise it may just display the MHTML code in text format.
Greg
I have the exactly same problem as you do.
Apparently, Android 4.4 WebView saves web archives as MHTML. Therefore, you can't use WebArchiveReader anymore.
You might want to parse MHTML files with some other 3rd party lib. Good luck!
Related
I am new to Android. I have been trying to update a node value of my xml file using DomParser. I have been workin with asset folder xml file to read. I realised asset folder files cannot be updated and then created a raw folder to save my xml file.I have been refering many answers provided by different people for a long time but nothing is workin!
Portion of my .xml file
<events>
<type>ABC</type>
<time>1:30-2:45pm</time>
<day>XYX</day>
<note>123</note>
</events>
and I have been trying the code
try{
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
InputStream is = this.getResources().openRawResource(temp1);
Document doc = docBuilder.parse(is);
if (null != doc.getDocumentElement()){
v1.setText("\n\nhiii888",doc.getDocumentElement()); ("HERE")
RelativeLayout layout = (RelativeLayout) findViewById(R.id.content);
layout.addView(v1);
}
Node nodes = doc.getElementsByTagName("events").item(0);
NodeList list = nodes.getChildNodes();
for (int i =0; i<list.getLength();i++){
Node node = list.item(i);
if("type".equals(nodes.getNodeName())){
node.setNodeValue("ABC123");
}
}
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("temp1.xml"));
transformer.transform(source, result);
}
My app shows stopped running when executing this and so I put in the piece of if block with textview and relative layout("mentioned as "HERE") to see where until the code works fine..The getDocumentElement()does return a value and so it displays in textview as
hiii888org.apache.harmony.xml.dom.ElementImpl#e58aa2f
I dont know why this is coming.I also used Text to typecast and retrieve the result and also .toString() function expecting typecasting can solve the problem.Nothing seem to work..Have been trying Xml update now for days...Hope to see answers that can sort my issue regarding xml update other than the already existing ones...Thanks in advance.
I am running into a strange error with trying to parse XML from an android device. What is strange is parsing the xml worked several days before and I have not touched the code. Today, loading the xml will not work.
The xml files are located in the "assets" folder in my project directory.
Here is the part where I am passing the path of that specific xml file into a parser called MazeFileReader.
private void generateFromFile() {
Log.v(TAG, "Generating from file");
File maze_file = new File(getCacheDir() + "/" + pregen_maze);
if (!maze_file.exists()) try {
InputStream is = getAssets().open(pregen_maze);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
FileOutputStream fos = new FileOutputStream(maze_file);
fos.write(buffer);
fos.close();
} catch (Exception e) { throw new RuntimeException(e); }
MazeFileReader mazeFileReader = new MazeFileReader(getApplicationContext(), maze_file.getPath());
Here is MazeFileReader now taking that path and trying to parse it.
private void load(String filename)
{
try{
File fXmlFile = new File(filename);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile); //Fails here
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("Maze");
for (int temp = 0 ; temp < nList.getLength() ; temp++) {
...
}
}
catch (Exception e) {
e.printStackTrace();
I've traced the error and it seems in that this line of code executes in DocumentBuilderImpl
if (parser.nextToken() == XmlPullParser.END_DOCUMENT) {
throw new SAXParseException("Unexpected end of document", null);
}
Also, I don't think there is anything wrong with my xml file either as I have not touched it and it was working several days before. I have 4 or 5 other xml files that have all worked, but today, all run into the same SAXParseException for some reason. What are the possible reasons for SAXParseException? Is it possible that the filepath to the xml is incorrect?
Here is the xml in question:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Maze>
<sizeX>
4
</sizeX>
<sizeY>
4
</sizeY>
<roomNum>
0
</roomNum>
<partiters>
60
</partiters>
<cell_0>
173
</cell_0>
<cell_1>
132
</cell_1>
<cell_2>
140
</cell_2>
<cell_3>
198
</cell_3>
</Maze>
EDIT: I found something WEIRD. I checked out an old version of my project and it still does not work. Then I made a new emulator and reinstalled the app. Now it works!!! What is the reason behind this?
I've discovered something else. The xml file will run into SAXParserException if I debug and step through the parsing. Then the file will be unable to parse from then on. However, if I do not debug it and reinstall the app on a new device, then the xml parses correctly. Btw, the xml is located in assets folder. Why is Android exhibiting this sort of behavior?. Are the xml files somehow getting corrupted?
I would like to implement an application to get android default browser history and saving the browser history to an xml file.But the browser history is not saving in some devices into an xml file.
I have implemented my application for get the browser history info to save to xml file as follows:
private void browserHistoryDOM() {
try{
File newxmlfile = new File("/sdcard/Xmlfiles/briwserHistory.xml");
newxmlfile.createNewFile();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
Element rootElement = document.createElement("root");
document.appendChild(rootElement);
Cursor mCur = managedQuery(Browser.BOOKMARKS_URI,Browser.HISTORY_PROJECTION, null, null, null);
mCur.moveToFirst();
if (mCur.moveToFirst() && mCur.getCount() > 0) {
while (mCur.isAfterLast() == false) {
Element em = document.createElement("bookmarkIdx");
em.appendChild(document.createTextNode(mCur.getString(Browser.HISTORY_PROJECTION_BOOKMARK_INDEX)));
rootElement.appendChild(em);
long callDate = Long.parseLong(mCur.getString(Browser.HISTORY_PROJECTION_DATE_INDEX));
SimpleDateFormat datePattern = new SimpleDateFormat ("dd-MM-yyyy/h:m:s:a");
datePattern.setTimeZone(TimeZone.getTimeZone("GMT"));
String date_str = datePattern.format(new Date(callDate));
Element em1 = document.createElement("dateIdx");
em1.appendChild(document.createTextNode(date_str));
rootElement.appendChild(em1);
Element em2 = document.createElement("idIdx");
em2.appendChild(document.createTextNode(mCur.getString(Browser.HISTORY_PROJECTION_ID_INDEX)));
rootElement.appendChild(em2);
Element em3 = document.createElement("titleIdx");
em3.appendChild(document.createTextNode(mCur.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX)));
rootElement.appendChild(em3);
Element em4 = document.createElement("urlIdx");
em4.appendChild(document.createTextNode(mCur.getString(Browser.HISTORY_PROJECTION_URL_INDEX)));
rootElement.appendChild(em4);
Element em5 = document.createElement("visitsIdx");
em5.appendChild(document.createTextNode(mCur.getString(Browser.HISTORY_PROJECTION_VISITS_INDEX)));
rootElement.appendChild(em5);
long searchDate = Long.parseLong(mCur.getString(Browser.SEARCHES_PROJECTION_DATE_INDEX));
SimpleDateFormat datePattern1 = new SimpleDateFormat ("dd-MM-yyyy/h:m:s:a");
datePattern1.setTimeZone(TimeZone.getTimeZone("GMT"));
String date_str1 = datePattern.format(new Date(searchDate));
Element em6 = document.createElement("searchDateIdx");
em6.appendChild(document.createTextNode(date_str1));
rootElement.appendChild(em6);
Element em7 = document.createElement("searchIdx");
em7.appendChild(document.createTextNode(mCur.getString(Browser.SEARCHES_PROJECTION_SEARCH_INDEX)));
rootElement.appendChild(em7);
Element em8 = document.createElement("truncateIdIdx");
em8.appendChild(document.createTextNode(mCur.getString(Browser.TRUNCATE_HISTORY_PROJECTION_ID_INDEX)));
rootElement.appendChild(em8);
Element em9 = document.createElement("truncateOldest");
em9.appendChild(document.createTextNode(mCur.getString(Browser.TRUNCATE_N_OLDEST)));
rootElement.appendChild(em9);
mCur.moveToNext();
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(newxmlfile);
transformer.transform(source, result);
} catch (Exception e) {
e.printStackTrace();
}
}
By using the above method i can get the browser history and able to save the data into xml file on sdcard.But in some kind of android devices are not getting browser history completly and not saving into xml file.If I test the app on Motorola Droid device then it is working fine.But If I test the same app on I have tested app on npm702 NOVO7PALADIN then i am not able to get browser history in my xml file.
First, never hardwire /sdcard. Use Environment.getExternalStorageDirectory() to get to the root of external storage.
Second, Browser.BOOKMARKS_URI will, at most, work for the open source Browser app that is part of the Android Open Source Project. Device manufacturers are welcome to replace that app with something else that will not be recording its history, bookmarks, or anything else in that ContentProvider. Similarly, users are allowed to download third-party browsers, which may not be storing things in that ContentProvider.
Third, NOVO7PALADIN may not have passed the Compatibility Test Suite, particularly if it does not have the Google Play Store (formerly Android Market) pre-installed. That would mean that the device manufacturer is welcome to break anything they want, including whether the open source Browser app stores things in that ContentProvider.
You would need to contact the NOVO7PALADIN manufacturer to learn anything more.
I am parsing a xml from an url.The url is has mobile IMEI no and searchstring based on my application. i put my xml parsing code in android project it does not work. but if i run as separate java program it is working. please help me.
Log.e("rsport-", "function1");
try{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setIgnoringComments(true);
factory.setCoalescing(true); // Convert CDATA to Text nodes
factory.setNamespaceAware(false); // No namespaces: this is default
factory.setValidating(false); // Don't validate DTD: also default
DocumentBuilder parser = factory.newDocumentBuilder();
Log.e("rsport-", "function2");
Document document = parser.parse("http://demo.greatinnovus.com/restingspot/search?userid=xxxxxxxxxxxxxxxx&firstname=a&lastname=a");
Log.e("rsport-","function3");
NodeList sections = document.getElementsByTagName("Searchdata");
int numSections = sections.getLength();
for (int i = 0; i < numSections; i++)
{
Element section = (Element) sections.item(i);
if(section.hasChildNodes()==true){
NodeList section1=section.getChildNodes();
for(int j=0;j<section1.getLength();j++){
if(section1.item(j).hasChildNodes()==true) {
for(int k=0;k<section1.item(j).getChildNodes().getLength();k++)
xmlvalue=String.valueOf(section1.item(j).getChildNodes().item(k).getNodeValue()).trim();
arl.add(xmlvalue);
}
}
}
}
}
}
catch(Exception e){}
System.out.println("id"+id+" searchdatacount"+searchdatacount);
System.out.println("---------");
ListIterator<String> litr = arl.listIterator();
while (litr.hasNext()) {
String element = litr.next();
Log.e("rsport-", "elememt");
}
after the Log.e("rsport-", "function2"); does not work.
Refer my blog, i had gave Detailed explanation, http://sankarganesh-info-exchange.blogspot.com/2011/04/parsing-data-from-internet-and-creating.html, and make sure , that you had add the Internet permission in your Manifest file.
If you had gone through Myblog, then you will able to notice that you did the following line as wrong
Document document = parser.parse("http://demo.greatinnovus.com/restingspot/search?userid=xxxxxxxxxxxxxxxx&firstname=a&lastname=a");
use like this
URL url =new URL("http://demo.greatinnovus.com/restingspot/search?userid=xxxxxxxxxxxxxxxx&firstname=a&lastname=a");
Document document= parser.parse(new InputSource(url.openStream()));
I'm using the DOM parser to retrive information from a XML file that looks like this:
<data>
<metData>
<wantedInformation>
</metData>
<metData>
<Information>
</metData>
<metData>
<Information>
</metData>
<data>
The problem is because I don't know how to parse only the first part of <metData>. I don't need the second and the third part, but the parser displays them anyway.
The xml file is from a weather forcast site:
http://www.meteo.si/uploads/probase/www/fproduct/text/sl/fcast_SLOVENIA_MIDDLE_latest.xml
and I need just the following line: <nn_shortText>oblačno</nn_shortText>
Pls take care whether your XML file is well formed or not,
You have to the notice three methods which i had shown below, they are
1. getElementsByTagName - Mention the tag which you want to parse
2.getChildNodes - retervies the child node
3.getNodeValue()- with the help of this method you can access the
value of particular tag
Step 1: Create a Method to parse _Information_Value ,inorder to parse the data of Information tag
String[] infoId=null;
public void parse_Information_Value() throws UnknownHostException{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(this.getInputStream());
org.w3c.dom.Element root = dom.getDocumentElement();
NodeList items = root.getElementsByTagName("metData");
int a=items.getLength();
int k=0;
for (int i = 0; i < items.getLength(); i++) {
Message_category message = new Message_category();
Node item = items.item(i);
NodeList properties = item.getChildNodes();
for (int j = 0; j < properties.getLength(); j++) {
Node property = properties.item(j);
String name = property.getNodeName();
if (name.equalsIgnoreCase("wantedInformation")) {
message.setId(property.getFirstChild()
.getNodeValue());
infoId[k]=property.getFirstChild().getNodeValue();
k++;
}
}
}
} catch (Exception e) { }
}
Depending on the size of your document, you may also want to use at a streaming oriented parser like SAX or Stax, which does not pull the whole document into memory and thus needs less memory than DOM.
Good thing is that SAX is already built into Android, so you can use it right away.
See this link for a usage example.