乐者为王

Do one thing, and do it well.

将Nokia 6670的短信导入HTC Hero G3

这事本该N久前就该干了(09年末把手机从Nokia 6670换到HTC Hero G3),却一直拖着没有做,今天终于把这事作了一个了结。

Nokia下导出的短信是如Messages_Nokia 6670_20091215.xml这样的一个XML文件,文件内容的编码是unicode,格式就像下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="unicode"?>
<SMS PhoneModel="Nokia 6670">
  <Message DateTime="2011-06-21 10:10:10">
    <Sender>路人甲</Sender>
    <PhoneNumber>+8613988888888</PhoneNumber>
    <Location>Inbox</Location>
    <Text>我是路人甲</Text>
  </Message>

  <Message DateTime="2011-06-21 11:11:11">
    <Sender>路人乙</Sender>
    <PhoneNumber>+8613966666666</PhoneNumber>
    <Location>Outbox</Location>
    <Text>我是路人乙</Text>
  </Message>
</SMS>

本来是想写个Android应用来直接导入这些备份短信的,不过在实现的过程中发现了SMS Backup&Restore应用导出的备份文件和Nokia的备份文件类似,产生了做个将Nokia备份文件转换成SMS Backup&Restore备份文件的念头,又在网上发现了nicholashan的将Nokia的短信导入Hero(可能适用所有Android机型),坚定了我的这个想法。

分析了一下SMS Backup&Restore备份文件的格式,文件内容的编码是utf-8的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<smses count="3">
  <sms protocol="0" address="10658658" date="1308629532000"
    type="1" subject="null" body="我是内容" toa="null"
    sc_toa="null" service_center="null" read="1"
    status="-1" locked="0" />
  <sms protocol="0" address="13566666666" date="1308633733000"
    type="2" subject="null" body="我也是内容" toa="null"
    sc_toa="null" service_center="null" read="1"
    status="-1" locked="0" />
  <sms protocol="0" address="+8613588888888" date="1308641377000"
    type="1" subject="null" body="我还是内容" toa="null"
    sc_toa="null" service_center="null" read="1"
    status="-1" locked="0" />
</smses>

与转换相关的就address、date、type和body四个属性。address是发信人的号码;date是短信发送日期的timestamp。这点nicholashan的确说错了,后面不需要加什么0的(实际上nicholashan自己也怀疑自己的说法);type等于1表示别人发给你的短信,如果是2的话就是你发给其他人的短信;body就是短信内容了。

将Nokia中的时间转换到SMS Backup&Restore的时间可以使用下面的代码:

1
2
3
4
5
6
7
8
DateFormat dt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
long value = 1355296332000L;    // 2012-12-12 12:12:12
Element e = (Element)iter.next();
Attribute attr = e.attribute("DateTime");
try {
    value = dt.parse(attr.getValue()).getTime();
} catch (ParseException ex) {
}

完整的代码如下(使用dom4j实现XML解析):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

public class Main {

    public static void main(String[] args) {
        try {
            SAXReader sr = new SAXReader();
            Document doc = sr.read(new File(args[0]));

            generateDocument(doc);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void generateDocument(Document doc) {
        List list = doc.selectNodes("//Message");

        Document document = DocumentHelper.createDocument();
        Element smses = document.addElement("smses");
        smses.addAttribute("count", String.valueOf(list.size()));

        DateFormat dt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long value = 1355296332000L;    // 2012-12-12 12:12:12
        Iterator iter = list.iterator();
        while (iter.hasNext()) {
            Element e = (Element)iter.next();
            Attribute attr = e.attribute("DateTime");
            try {
                value = dt.parse(attr.getValue()).getTime();
            } catch (ParseException e) {
                System.out.println(e.getMessage());
            }
            Node phone = e.selectSingleNode("PhoneNumber");
            Node location = e.selectSingleNode("Location");
            Node text = e.selectSingleNode("Text");

            Element sms = smses.addElement("sms");
            sms.addAttribute("protocol", "0");
            sms.addAttribute("address", phone.getText());
            sms.addAttribute("date", String.valueOf(value));
            if ("Inbox".equals(location.getText())) {
                sms.addAttribute("type", "1");
            } else if ("Outbox".equals(location.getText())) {
                sms.addAttribute("type", "2");
            }
            sms.addAttribute("subject", "null");
            sms.addAttribute("body", text.getText());
            sms.addAttribute("toa", "null");
            sms.addAttribute("sc_toa", "null");
            sms.addAttribute("service_center", "null");
            sms.addAttribute("read", "1");
            sms.addAttribute("status", "-1");
            sms.addAttribute("locked", "0");
        }

        File f = new File("output.xml");
        XMLWriter output = new XMLWriter(new FileWriter(f));
        output.write(document);
        output.close();
    }
}

Comments