閱讀973 返回首頁    go 技術社區[雲棲]


還原Android彩信數據庫

幾周前在做Android彩信數據庫還原時遇到了一個很棘手的問題,就是Android的彩信數據庫不向短信數據庫那樣可以方便的用一條insert語句創建一條記錄,而我沒有得到許可去修改Android平台的彩信應用的原代碼,所以我不得不另尋它徑。在下麵我會盡我可能用盡量簡潔的語言描述整個解決的過程。
1 彩信數據庫
問題是這樣的,我備份了Android的彩信數據庫,即mmssms.db文件,並且希望能成功把彩信部分的數據信息還原到還原數據庫中。
在mmssms.db中與彩信相關的表有
Pdu表: 記錄一條彩信的主要信息,包括時間,thread_id等;
Addr表:記錄一條彩信發送的目的地地址(手機號碼),其中外鍵msg_id映射pdu表的id;
Part表:記錄一條彩信息的附件,文本信息,基中外鍵mid映射pdu表的id號;
訪問pdu表的uri:
Public static final Uri CONTENT_URI = Uri.parse(“content://mms”);
訪問part表的uri
Uri.parse(“content://mms”+pduID+”/part”),
當然你可以了把pduID放到query函數的selection語句中,如
String selection = new String("mid='" + key + "'");//這個key就是pdu裏麵的_id。 
Cursor cur = getContentResolver().query(Uri.parse("content://mms/part"), null, selection, null, null); 
訪問addr表的uri:
Uri.parse(“content://mms”+pduID+”/addr”),同樣也可以用另一種方法 
2 還原過程
開始做還原時,我繼承了還原短信數據庫時的思路,用了一個insert語句去插入一條新數據,但可惜的是在pdu表中的thread字段始終不能自動生成,這現象恰好和做普通的短信還原時相反,什麼原因呢?我查看了Android的mms的原代碼,發現原代碼中更本就沒有支持你去插入一條彩信時,它會自動去生成thread字段。我要的可不是簡單的憑空創建一個thread字段喲。在短信數據庫中,同一個聯係人下會在threads表中對應一條thread記錄(我理解成一個組),發給同一個人的信息和同一個發給你的信息(包括普通短信與彩信)都會存在同一個組下,一條thread記錄會存儲有多少條這樣的短信與彩信,而pdu的外鍵thread會映射到threads表中的id號中。所以,在還原一條開始不存在的聯係人的彩信時,我需要一個可靠的thread。沒有thread,你是沒有辦法在手機Messaging下看到你還原的彩信信息的,相信我。
在一次偶然測試彩信發送的過程中,我發現當你在編輯一條彩信的過程中,會有一條信息“converting to multimedia message…”,原來是這樣。 我想你也應該明白了。原來程序本身在存入一條彩信記錄是從普通短信記錄轉換過來的,中間有個過渡。那麼在插入一條新彩信時,我應用同樣的先向sms表中插入一條記錄,當然address要和彩信的addr一致。這樣,你會得到一個thread記錄。然後再用還原pdu表的信息,這時thread_id已經知道了。記得要刪除我們的臨時短信:)
還沒有完呢,當你在還原part表中的附件信息時,你會發現你怎麼也沒法使附件的文件信息路徑(在_data字段中)與實際的附件文件一致,文件名PART_+一串數字,明顯與時間有關。你如果再仔細的分析會發現每次插入新數據,_data字段下的文件名會自動更新到插入時的時間,而不會管你插入時附給些字段的數據。沒得法,又隻能去看看源代碼了,很快就發現源代碼中的insert函數在插入_data字段時,如果是ct != “application/smil”時,是會以當前時間自動更新_data字段裏的文件名的,沒有相關的文件程序會自動創建一個0byte的文件。我處理方法很簡單,就是插入時你不要去更新_data字段,而是用update它,相信我update沒有自動更新的處理。
整理一下,還原的整個過程如下:
a.       創建thread記錄。在sms表中創建一條普通短信記錄,記得發送的號碼要一致,創建後再在pdu中創建彩信記錄,記得thread字段要與前麵創建得到的一致。還有記住在完成所有的工作後,要刪除sms表中的痕跡。
b.       還原addr表。這應該很簡單。
c.       還原part表。要小心_data字段。在更新_data字段前,記得要先上傳附件文件到com.android.providers.telephony下的app_parts下。 
3 編碼問題
在上傳一個中文的附件時,你會在數據庫中發現是亂碼,這點隻是編碼出現了一小點的轉換,這是不會影響到手機上的messaging程序對彩信的正確顯示。但如果你要在自己的程序中對數據庫中的數據進行處理時,我相信你還是需要知道是會編碼方式在搗亂。Android數據庫中是以iso8859-1對中文編碼的,而程序中一般都是用utf-8.所以,你需要用以下方式轉換編碼,
str = new String(str.getBytes("iso8859-1"), "utf-8"); 
還有個需要注意的地方就是,在logcat中是不能顯示中文的,不要因為在log中看不到中方就誤以為自己的編碼方式是錯誤的!!!
4 權限問題
WRITE_SMS    "android.permission.WRITE_SMS"  
READ_SMS    "android.permission.READ_SMS"
記得加權限。

最後更新:2017-04-04 07:03:45

  上一篇:go poj 1556 The Doors 最短路
  下一篇:go iOS開發那些事-響應內存警告