android 導出每個號碼的最新的短信記錄(巧用SQL語句的"--"註釋符)

最近在做一個項目,要求:導出每個號碼最新的短信記錄,要求顯示人名,號碼,最近的一條短信內容且以時間降序排列。


短信數據庫存儲路徑:“./data/data/com.android.providers.telephony/databases/mmssms.db”

短信、彩信的數據庫的結構和模型講解見:http://www.cnblogs.com/shaweng/archive/2012/05/26/2518949.html

目前的方法有五種:

方法一:

SQL語句爲:select date, body, address, type from sms where (length(address)>0) group by (thread_id) order by date desc

但是不能夠導出草稿記錄

void getSmsData(Context cnt) {
        ContentResolver resolver = cnt.getContentResolver();
        Cursor cursor = null;
        try {
            cursor = resolver.query(Sms.CONTENT_URI, new String[] { 
                  Telephony.Sms.DATE, 
                 Telephony.Sms.BODY, Telephony.Sms.ADDRESS,
             Telephony.Sms.TYPE }, 
           "length(" + Telephony.Sms.ADDRESS + ")>0) group by ("
         + Telephony.Sms.THREAD_ID, null, Telephony.Sms.DEFAULT_SORT_ORDER);
            // 提高cursor訪問速度
            if (cursor != null) {
                int count = cursor.getCount();
                cursor.moveToFirst();
                synchronized (mImportDataList) {//正序查找
                    for (int i = 0; i < count; i++) {
                        cursor.moveToPosition(i);
                        long smsDate = cursor.getLong(0);//設置最新一條短信的時間
                        String smsBody = cursor.getString(1); // 內容
                        String phoneNum = cursor.getString(2); // 電話號碼
                        int smsType = cursor.getInt(3); // 短信類型
                 Log.i("DEBUG", "smsDate = " + smsDate + ",smsBody=" 
                       + smsBody + 
                       ",phoneNum=" + phoneNum + ",smsType=" + smsType);
                    }
                }
                cursor.close();
            }
        } catch (Exception e) {
            Log.w(TAG, e.toString());
            cursor = null;
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }


方法二:

SQL 語句:

select a.date,a.snippet,b.address,b.type from threads a, sms b where a._id = b.thread_id  group by b.address order by a.date desc --from sms

多表查詢,同時查詢表threads和sms。即先查出thread_ID,然後取出該thread_ID對應的電話號碼和內容等

參考網址:http://bbs.csdn.net/topics/340237133        

但是也不能夠導出草稿記錄

void getSmsData(Context cnt) {
        ContentResolver resolver = cnt.getContentResolver();
        Cursor cursor = null;
        try {
            cursor = resolver.query(Sms.CONTENT_URI,new String[] { 
                    " a.date,a.snippet",              
                    " b.address,b.type from threads a",
    " sms b where a._id = b.thread_id  group by b.address order by a.date desc-- ", 
            }, null, null, null);
            // 提高cursor訪問速度
            if (cursor != null) {
                int count = cursor.getCount();
                cursor.moveToFirst();
                synchronized (mImportDataList) {//正序查找
                    for (int i = 0; i < count; i++) {
                        cursor.moveToPosition(i);
                        long smsDate = cursor.getLong(0);//設置最新一條短信的時間
                        String smsBody = cursor.getString(1); // 內容
                        String phoneNum = cursor.getString(2); // 電話號碼
                        int smsType = cursor.getInt(3); // 短信類型      
                 Log.i("DEBUG", "smsDate = " + smsDate + ",
                      smsBody=" + 
                 smsBody + ",phoneNum=" + phoneNum   + ",smsType=" + smsType);
                    }
                }
                cursor.close();
            }
        } catch (Exception e) {
            Log.w(TAG, e.toString());
            cursor = null;
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }


方法三:

SQL 語句:

select a.date,a.snippet,b.address,b.type from threads a, sms b where a._id = b.thread_id  group by a.date --from sms

它是方法二的變種,能夠轉換爲android方式的查詢數據庫。

注意該方式的弊端是,無法滿足不同號碼的短信的時間相同時,會漏掉短信。因爲它是以日期爲group by。實現方式如下:

void getSmsData(Context cnt) {
        ContentResolver resolver = cnt.getContentResolver();
        Cursor cursor = null;
        try {
            cursor = resolver.query(Sms.CONTENT_URI,new String[] { 
                    " a.date,a.snippet",           
                    " b.address,b.type from threads a",
     " sms b where a._id = b.thread_id  group by b.date-- ", 
            }, null, null, null);
            // 提高cursor訪問速度
            if (cursor != null) {
                int count = cursor.getCount();
                cursor.moveToFirst();
                synchronized (mImportDataList) {//正序查找
                    for (int i = 0; i < count; i++) {
                        cursor.moveToPosition(i);
                        long smsDate = cursor.getLong(0);//設置最新一條短信的時間
                        String smsBody = cursor.getString(1); // 內容
                        String phoneNum = cursor.getString(2); // 電話號碼
                        int smsType = cursor.getInt(3); // 短信類型      
          Log.i("DEBUG", "smsDate = " + smsDate + ",smsBody=" + 
               smsBody + ",phoneNum=" + phoneNum   + ",smsType=" + smsType);
                    }
                }
                cursor.close();
            }
        } catch (Exception e) {
            Log.w(TAG, e.toString());
            cursor = null;
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }

方法四:

SQL 語句:

select a.date,a.snippet,c.type,b.address from threads a,canonical_addresses b , sms c where a.recipient_ids = b._id and c.date = a.date and c.thread_id = a._id and c.body >= a.snippet group by b.address order by a.date desc -- from sms

改變查詢策略,查詢表threads ,canonical_addresses ,sms

但是無法導出彩信記錄

注意:sql語句中的"--"代表註釋,所以

select a.date,a.snippet,c.type,b.address from threads a,canonical_addresses b , sms c where a.recipient_ids = b._id and c.date = a.date and c.thread_id = a._id and c.body >= a.snippet group by b.address order by a.date desc -- from sms

等同於

select a.date,a.snippet,c.type,b.address from threads a,canonical_addresses b , sms c where a.recipient_ids = b._id and c.date = a.date and c.thread_id = a._id and c.body >= a.snippet group by b.address order by a.date desc 

所以上面的sql語句是一個很巧妙的方式滿足了在ContentResolver 中查詢也能夠允許自定義的sql語句

void getSmsData(Context cnt) {
        ContentResolver resolver = cnt.getContentResolver();
        Cursor cursor = null;
        try {
            cursor = resolver.query(Sms.CONTENT_URI,new String[] { 
                    " a.date,a.snippet,a.type",             
                    " b.address from threads a",
  " canonical_addresses b",
  " sms c where a.recipient_ids = b._id and
  c.date = a.date and c.thread_id =
  a._id and c.body >= a.snippet
  group by b.address order by a.date desc -- ",   
            }, null, null, null);
            // 提高cursor訪問速度
            if (cursor != null) {
                int count = cursor.getCount();
                cursor.moveToFirst();
                synchronized (mImportDataList) {
                    for (int i = 0; i < count; i++) {
                        cursor.moveToPosition(i);
                        long smsDate = cursor.getLong(0);//設置最新一條短信的時間
                        String smsBody = cursor.getString(1); // 內容
                        String phoneNum = cursor.getString(3); // 電話號碼
                        int smsType = cursor.getInt(2); // 短信類型      
     Log.i("DEBUG", "smsDate = " + smsDate + ",smsBody=" + 
                          smsBody + ",phoneNum=" + phoneNum   + ",smsType=" + smsType);
                    }
                }
                cursor.close();
            }
        } catch (Exception e) {
            Log.w(TAG, e.toString());
            cursor = null;
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }


方法五:

終極大招,牛逼的SQL語句:

select address,date,body,type from (select a.address as address,c.date as date

,b.snippet as body,c.type as type from canonical_addresses a,threads b 

, sms c where  a._id = b.recipient_ids and b._id = c.thread_id and c.body >= b.snippet and c.date = b.date   union 
select c.address as address,b.date as date,a.sub as body,a.msg_box 

as type from pdu a,threads b,canonical_addresses 

c where a.thread_id = b._id and b.recipient_ids = c._id ) group by address order by date desc

它即能夠導出sms、mms、草稿等。

void getSmsData(Context cnt) {
        ContentResolver resolver = cnt.getContentResolver();
        Cursor cursor = null;
        try {
            cursor = resolver.query(Sms.CONTENT_URI,new String[] {
                "date,body,type,
				address from (select a.address
				as address,c.date as date", 
                "b.snippet as body,c.type
				as type from canonical_addresses
				a,threads b , sms c where
				a._id = b.recipient_ids
				and b._id = c.thread_id
				and c.body >= b.snippet
				and c.date = b.date union
				select c.address as
				address,b.date as date
				,a.sub as body,a.msg_box
				as type from pdu a,threads
				b,canonical_addresses
				c where a.thread_id
				= b._id and
				b.recipient_ids = c._id 
				) group by address order by date desc --", 
        }, null, null, null);
            // 提高cursor訪問速度
            if (cursor != null) {
                int count = cursor.getCount();
                cursor.moveToFirst();
                synchronized (mImportDataList) {
                    for (int i = 0; i < count; i++) {
                        cursor.moveToPosition(i);
                        long smsDate = cursor.getLong(0);//設置最新一條短信的時間
                        String smsBody = cursor.getString(1); // 內容
                        String phoneNum = cursor.getString(3); // 電話號碼
                        int smsType = cursor.getInt(2); // 短信類型      
     Log.i("DEBUG", "smsDate = " + smsDate + ",smsBody=" + 
                          smsBody + ",phoneNum=" + phoneNum   + ",smsType=" + smsType);
                    }
                }
                cursor.close();
            }
        } catch (Exception e) {
            Log.w(TAG, e.toString());
            cursor = null;
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }


綜上所述:

使用方法五即簡單也能夠滿足需求和解決邊界值問題。所以使用方法四來導入最新短信記錄。


注意:由於爲了讓內容能夠在網頁裏面顯示,有一些代碼是直接換行了,copy出去後,編譯不過會報錯。你只要把換行刪掉就可以了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章