I use this SMS Backup and Restore application on my android phone to export all my text messages.  What I really want, is to just get all the pictures and save them to a better location and to delete all the messages.  Unfortunately, this application only creates one large XML file with the images Base64 encoded into the XML.

I do this when I want to factory reset my phone but don't want to lose all the media files people have sent me.

I created this script to pull those images out and place them in a folder.  It is rudimentary.  The file names and directories are hard coded... whatever.  It does what I need, take it if you want.

 

package com.isaacray.sms;

 

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileOutputStream;

import java.io.FileReader;

import java.io.IOException;

import java.io.OutputStreamWriter;

import java.util.Base64;

import java.util.Set;

import java.util.TreeSet;

 

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

 

import org.w3c.dom.Document;

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;

 

public class Main {

public static void main(String[] argsv) {

p("Beginning program");

String filename = "C:\\sms-20150814082858.xml";

String tmpFileName = filename + ".tmp";

String outputDir = "C:\\output\\";

try {

cleanUpFile(filename, tmpFileName);

DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();

DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();

Document doc = dBuilder.parse(new File(tmpFileName));

NodeList parts = doc.getElementsByTagName("part");

// printMimeTypes(parts);

new File(outputDir).mkdirs();

for (int i = 0; i < parts.getLength(); ++i) {

p("Processing " + (i + 1) + " of " + parts.getLength());

Node part = parts.item(i);

String ct = part.getAttributes().getNamedItem("ct").toString();

if (ct.contains("image/") || ct.contains("video/") || ct.contains("audio/")) {

byte[] bytes = Base64.getDecoder().decode(part.getAttributes().getNamedItem("data").getTextContent());

String name = part.getAttributes().getNamedItem("name").getTextContent();

if (name.equals("null")) {

name = i + part.getAttributes().getNamedItem("cl").getTextContent();

}

FileOutputStream fos = new FileOutputStream(outputDir + name);

fos.write(bytes);

fos.close();

File file = new File(outputDir + name);

Node parent = part.getParentNode().getParentNode();

file.setLastModified(Long.valueOf(parent.getAttributes().getNamedItem("date").getTextContent()));

}

}

} catch (Exception e) {

p(e);

} finally {

try {

String command = "cmd /C del \"" + tmpFileName + "\"";

Runtime.getRuntime().exec(command);

} catch (Exception e) {

p(e);

}

}

}

 

private static void cleanUpFile(String filename, String tmpFileName) throws IOException {

BufferedReader br = new BufferedReader(new FileReader(filename));

FileOutputStream fos = new FileOutputStream(tmpFileName);

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos, "UTF8"));

while (br.ready()) {

String line = br.readLine();

bw.write(line.replaceAll("&#[0-9][0-9][0-9][0-9][0-9];", ""));

bw.newLine();

}

br.close();

bw.close();

}

 

private static void printMimeTypes(NodeList parts) {

Set<String> mimes = new TreeSet<String>();

for (int i = 0; i < parts.getLength(); ++i) {

Node part = parts.item(i);

String ct = part.getAttributes().getNamedItem("ct").toString();

mimes.add(ct);

}

for (String mime : mimes) {

p(mime);

}

}

 

private static void p(Object o) {

System.out.println(o);

}

}