Android開發之調用系統的ContentProvider——簡訊的擷取和備份

來源:互聯網
上載者:User

Android開發之調用系統的ContentProvider——簡訊的擷取和備份
忍耐和堅持雖是痛苦的事情,但卻能漸漸地為你帶來好處.——奧維德。
可能在堅持一件事情一段時間後,我們腦海中會有很多放棄的念頭,可能在放棄之後的幾年後,我們會想如果當時堅持下來會怎麼怎麼樣。。。,但是可惜的是我們沒有堅持。最近比較懶,也在這裡提醒自己,不要迷失自己,堅持學習。 在上一篇我們講到了如何建立自己的ContentProvider,如果你掌握了上一篇所講的內容,那麼相信今天這一篇,你會很輕鬆的掌握。這一篇的主要內容就是調用Google工程師給我們提供好的ContentProvider,也就是說Google定義好一個ContentProvider後會給我們一個Uri,我們拿著這個Uri就可以得到相應的資料。如果你沒調用過系統的Uri,沒有關係,今天我們會通過一個案例來詳細講解怎麼調用。廢話不多說進入正題,如有謬誤歡迎批評指正,如有疑問歡迎留言。 通過本篇部落格你將學到以下知識點①如何調用系統的ContentProvider②如何通過Google給我們的Uri獲得簡訊的資料③一個案例將手機中的簡訊進行備份和恢複 1、如何調用系統的ContentProvider 其實閱讀了上一篇文章之後,這個問題會很好的理解,Google工程師在將ContentProvider寫好之後,肯定會給我們一個Uri,只要知道這個Uri,我們就可以拿到我們需要的資料,比方說你想獲得手機簡訊的資訊,那麼必定有和其對應的Uri,你想獲得圖庫、連絡人資訊,也必定有相應的Uri與之對應。知道對應的Uri後,就可以過ContentResolver這個對象,根據Uri進行資料訪問。更多的內容請參考:Android開發之內容提供者——建立自己的ContentProvider(詳解),今天的主要任務就是完成一個案例擷取系統的簡訊資料。 2、案例(手機簡訊資料的擷取,以及備份和恢複) 接下來我們就來看一個案例,這個案例的主要功能就是根據Uri擷取手機簡訊的資訊,並將其備份和恢複,它的如下:

這個圖片示範了這樣一種功能,首先在DDMS中向模擬器中發幾條簡訊,然後運行我們的程式,點擊備份,提示備份成功後,將所有的簡訊刪除,然後在我們的程式中點擊恢複,開啟簡訊介面發現剛才刪除的簡訊已經恢複,這就是我們要實現的功能

首先來分析一下怎麼實現上述效果,如果想備份簡訊,首先要做的就是擷取簡訊的列表,這一步比較簡單因為Google已經將其封裝好,我們所要做的就是用Uri去查詢簡訊庫,就O了,然後拿到資料後需要將資料以XML的形式儲存到SD卡裡面,當然你用其它的方式也可以,只要能將其恢複就行。最後恢複的時候將指定路徑的XML檔案解析,根據Uri將解析的簡訊資料插入到系統的簡訊列表中。思路就是這樣一個思路。沒有看懂沒關係,下面會有源碼以及對它們的分析。 瞭解了大概思路後,另一個重要的任務就是看看簡訊的表結構在模擬器中它的路徑是data->data->com.android.providers.telephony->databases下,如將其匯出然後用Sqlite資料開啟可以看到資料的結構如下,這裡只關心threads表和sms表就夠了threads表的結構如下其中_id:用於區分不同的電話號碼,系統會為不同的電話號碼分配不同的_id。date:收到資訊的時間(如果收到來自同一個phone number多條資訊,並且有對於一條資訊未讀,那麼date表示收到的最後一條資訊時的時間)message_count:收到的資訊的數目read: 0.代表未讀。1.代表已讀對於其它欄位一般很少用到,這裡就不多做介紹了, sms表的結構如下其中_id:用於區分不同的簡訊

date:該條簡訊接收的時間

read: 0表未讀,1表已讀

body:表示具體的簡訊內容 到這裡準備工作還差一步就可以進行代碼的書寫了,哪一步呢?就是訪問這個資料庫的Uri,對於訪問手機簡訊的Uri主要有以下這麼幾個content://sms/ 所有簡訊
content://sms/inbox 收件匣
content://sms/sent 已發送
content://sms/draft 草稿
content://sms/outbox 寄件匣
content://sms/failed 發送失敗
content://sms/queued 待發送列表在這個案例中我們用content://sms/,因為是備份肯定是備份所有的簡訊,好了,下面一起來看看代碼吧。首先要做的就是根據Uri擷取簡訊的列表,這裡建立一個SmsManage類,將備份和恢複的方法放到這個類中,擷取簡訊列表的代碼如下
     /**      * 擷取簡訊列表      * @return      */      public List getSmsList() {            //擷取所有簡訊的 Uri           Uri uri = Uri. parse( "content://sms/");            //擷取ContentResolver對象           ContentResolver contentResolver = mContext.getContentResolver();            //根據Uri 查詢簡訊資料           Cursor cursor = contentResolver.query(uri, null, null, null, null);            if ( null != cursor) {                Log. i( TAG, "cursor.getCount():" + cursor.getCount());                 //根據得到的Cursor一條一條的添加到smsList(簡訊列表)中                 while (cursor.moveToNext()) {                      int _id = cursor.getInt(cursor.getColumnIndex("_id" ));                      int type = cursor.getInt(cursor.getColumnIndex("type" ));                     String address = cursor.getString(cursor.getColumnIndex( "address"));                     String body = cursor.getString(cursor.getColumnIndex("body" ));                     String date = cursor.getString(cursor.getColumnIndex("date" ));                     SmsData smsData = new SmsData(_id, type, address, body, date);                      smsList.add(smsData);                }                cursor.close();           }            return smsList;     }
可以看到上述代碼就是根據content://sms/這個Uri去查詢手機中簡訊的資料庫,得到一個Cursor這個Cursor就包含了一條一條的簡訊。然後去遍曆這個Cursor將我們需要的資料添加到smsList中。這樣簡訊資料就拿到了,因為我們做的功能是簡訊備份,所以接下來需要將smsList這個集合中的資料儲存到本地,以方便簡訊恢複的時候去讀取儲存的這個檔案,那麼問題來了,怎樣將smsList這個集合以檔案的形式儲存到本地呢?當然方法有很多,這裡我們採用的是使用XmlSerializer將其序列化,待我們需要恢複的時候使用XmlPullParser將其還原序列化,就可以拿到備份的資料,聽起來感覺挺高大上的,其實很簡單就是對xml的操作。下面來看看序列化的代碼即將上面得到的集合smsList中的資料產生一個xml檔案,並儲存到本地,代碼如下
/** * 將簡訊資料儲存到 sd卡中 */public void saveSmsToSdCard(){            smsList=getSmsList();            //獲得一個序列化對象           XmlSerializer xmlSerializer=Xml. newSerializer();            //將產生的 xml檔案儲存到sd 卡中名字為"sms.xml"           File file= new File(Environment.getExternalStorageDirectory(), "sms.xml");           FileOutputStream fos;                       try {                fos = new FileOutputStream(file);                xmlSerializer.setOutput(fos, "utf-8");                xmlSerializer.startDocument( "utf-8", true);                xmlSerializer.startTag( null, "smss");                                xmlSerializer.startTag( null, "count");                xmlSerializer.text( smsList.size()+ "");                xmlSerializer.endTag( null, "count");                                 for(SmsData smsData: smsList){                                          xmlSerializer.startTag( null, "sms");                                          xmlSerializer.startTag( null, "_id");                     xmlSerializer.text(smsData.get_id()+ "");                     System. out.println( "smsData.get_id()=" +smsData.get_id());                     xmlSerializer.endTag( null, "_id");                                          xmlSerializer.startTag( null, "type");                     xmlSerializer.text(smsData.getType()+ "");                     System. out.println( "smsData.getType=" +smsData.getType());                     xmlSerializer.endTag( null, "type");                                          xmlSerializer.startTag( null, "address");                     xmlSerializer.text(smsData.getAddress()+ "");                     System. out.println( "smsData.getAddress()=" +smsData.getAddress());                     xmlSerializer.endTag( null, "address");                                          xmlSerializer.startTag( null, "body");                     xmlSerializer.text(smsData.getBody()+ "");                     System. out.println( "smsData.getBody()=" +smsData.getBody());                     xmlSerializer.endTag( null, "body");                                          xmlSerializer.startTag( null, "date");                     xmlSerializer.text(smsData.getDate()+ "");                     System. out.println( "smsData.getDate()=" +smsData.getDate());                     xmlSerializer.endTag( null, "date");                                          xmlSerializer.endTag( null, "sms");                }                xmlSerializer.endTag( null, "smss");                xmlSerializer.endDocument();                                fos.flush();                fos.close();                Toast. makeText( mContext, "備份完成", Toast.LENGTH_SHORT ).show();           } catch (FileNotFoundException e) {                e.printStackTrace();           } catch (IllegalArgumentException e) {                e.printStackTrace();           } catch (IllegalStateException e) {                e.printStackTrace();           } catch (IOException e) {                e.printStackTrace();           }          }
通過調用以上方法就將簡訊以xml的形式儲存到了本地。運行這個方法後可以再sd卡中看到sms.xml檔案,將其匯出來可以看到它的格式如下
註:實際上xml檔案中它是一行這裡為了讓大家更清楚的看清結構,我手動將其改成上述格式了。儲存到本地後,工作就剩下最後一步了,那就是將這個xml檔案還原序列化,並將其中的資料一條一條插入到簡訊的資料庫中,與其對應的代碼如下
     /**      * 將指定路徑的 xml檔案中的資料插入到簡訊資料庫中      * @param path      */      public void restoreSms(String path) {           File file = new File(path);            //得到一個解析 xml的對象           XmlPullParser parser = Xml. newPullParser();            try {                 fis = new FileInputStream(file);                parser.setInput( fis, "utf-8");                ContentValues values = null;                 int type = parser.getEventType();                 while (type != XmlPullParser. END_DOCUMENT) {                      switch (type) {                      case XmlPullParser. START_TAG:                            if ( "count".equals(parser.getName())) {                           } else if ("sms" .equals(parser.getName())) {                                values = new ContentValues();                           } else if ("type" .equals(parser.getName())) {                                values.put( "type", parser.nextText());                           } else if ("address" .equals(parser.getName())) {                                values.put( "address", parser.nextText());                           } else if ("body" .equals(parser.getName())) {                                values.put( "body", parser.nextText());                           } else if ("date" .equals(parser.getName())) {                                values.put( "date", parser.nextText());                           }                            break;                      case XmlPullParser. END_TAG:                            if ( "sms".equals(parser.getName())) {// 如果節點是 sms                                Uri uri = Uri.parse( "content://sms/");                                ContentResolver resolver = mContext.getContentResolver();                                resolver.insert(uri, values);//向資料庫中插入資料                                System. out.println( "插入成功" );                                values = null; //                           }                            break;                     }                     type=parser.next();                }           } catch (FileNotFoundException e) {                e.printStackTrace();           } catch (XmlPullParserException e) {                e.printStackTrace();           } catch (NumberFormatException e) {                e.printStackTrace();           } catch (IOException e) {                e.printStackTrace();           }     }
可以看到在上述方法中判斷xml的END_TAG是不是"sms"如果是的話說明一條簡訊的"type"、"address"、"body"、"date"這些資訊已經拿到,然後就根據Uri將這條資料插入到資料庫中,就完成一條簡訊的恢複,待讀到 END_DOCUMENT說明xml檔案已經讀完,此時所備份的簡訊就全部恢複了。 好了今天這篇文章就到這裡了,如果發現文章中的錯誤,歡迎指出,如果有疑問請留言,謝謝。如果你覺的本篇文章對你有協助,就贊一下,頂一個唄,謝謝您的支援。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.