最近在做一個項目,要求:導出每個號碼最新的短信記錄,要求顯示人名,號碼,最近的一條短信內容且以時間降序排列。
短信數據庫存儲路徑:“./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出去後,編譯不過會報錯。你只要把換行刪掉就可以了。