Android 从收件箱获取短信,优化的方式来阅读所有消息并将它们分组
Posted
技术标签:
【中文标题】Android 从收件箱获取短信,优化的方式来阅读所有消息并将它们分组【英文标题】:Android get sms from inbox, optimized way to read all messages and group them 【发布时间】:2013-01-10 19:47:59 【问题描述】:您好,我正在实施一个 SMS 应用程序,现在可以检索所有消息及其各自的联系信息,例如显示名称、照片 uri.. 并将它们显示在自定义列表中,单击项目会将您带到相应的讨论。我的问题是同步所有这些消息所花费的时间,
-
这次我需要优化。
每次我在讨论视图中发送新消息并返回最近的聊天时,我只需要更新特定项目,而不是整个列表。
这是我的代码:
读取短信.java:
public class ReadSMS
ArrayList<HashMap<Contact, ArrayList<OneComment>>> recentChats;
Application _context;
public ReadSMS(Application context)
this._context = context;
this.recentChats = ((ChatApplication) _context).getChats();
public ArrayList<HashMap<Contact, ArrayList<OneComment>>> getSMS()
// Init
ArrayList<SmsMsg> smsMsgs = new ArrayList<SmsMsg>();
TreeSet<Integer> threadIds = new TreeSet<Integer>();
Uri mSmsinboxQueryUri = Uri.parse("content://sms");
Cursor cursor = _context.getContentResolver().query(
mSmsinboxQueryUri,
new String[] "_id", "thread_id", "address", "date", "body",
"type" , null, null, null);
String[] columns = new String[] "address", "thread_id", "date",
"body", "type" ;
if (cursor.getCount() > 0)
while (cursor.moveToNext())
SmsMsg smsMsg = new SmsMsg();
String address = null, displayName = null, date = null, msg = null, type = null, threadId = null;
Uri photoUri = null;
threadId = cursor.getString(cursor.getColumnIndex(columns[1]));
type = cursor.getString(cursor.getColumnIndex(columns[4]));
if (Integer.parseInt(type) == 1 || Integer.parseInt(type) == 2)
address = cursor.getString(cursor
.getColumnIndex(columns[0]));
if (address.length() > 0)
String[] contactData = getContactByNumber(address);
if (contactData != null)
displayName = contactData[0];
if (contactData[1] != null)
photoUri = Uri.parse(contactData[1]);
else
address = null;
date = cursor.getString(cursor.getColumnIndex(columns[2]));
msg = cursor.getString(cursor.getColumnIndex(columns[3]));
smsMsg.setDisplayName(displayName);
smsMsg.setThreadId(threadId);
smsMsg.setAddress(address);
smsMsg.setPhotoUri(photoUri);
smsMsg.setDate(date);
smsMsg.setMsg(msg);
smsMsg.setType(type);
// Log.e("SMS-inbox", "\n\nNAME: " + displayName
// + "\nTHREAD_ID: " + threadId + "\nNUMBER: "
// + address + "\nPHOTO_URI: " + photoUri + "\nTIME: "
// + date + "\nMESSAGE: " + msg + "\nTYPE: " + type);
smsMsgs.add(smsMsg);
// Add threadId to Tree
threadIds.add(Integer.parseInt(threadId));
for (int threadId : threadIds)
HashMap<Contact, ArrayList<OneComment>> oneChat = new HashMap<Contact, ArrayList<OneComment>>();
Contact con = new Contact();
ArrayList<OneComment> oneDisc = new ArrayList<OneComment>();
for (SmsMsg smsMsg : smsMsgs)
if (Integer.parseInt(smsMsg.getThreadId()) == threadId)
con.setContactName(smsMsg.getDisplayName());
con.setContactNumber(smsMsg.getAddress());
con.setContactPhotoUri(smsMsg.getPhotoUri());
if (Integer.parseInt(smsMsg.getType()) == 1)
oneDisc.add(0, new OneComment(true,
smsMsg.getMsg(), smsMsg.getDisplayName(),
smsMsg.getDate(), false));
else if (Integer.parseInt(smsMsg.getType()) == 2)
oneDisc.add(0,
new OneComment(false, smsMsg.getMsg(),
"Me", smsMsg.getDate(), false));
oneChat.put(con, oneDisc);
// add at pos 0
recentChats.add(0, oneChat);
return recentChats;
public String[] getContactByNumber(final String number)
String[] data = new String[2];
try
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(number));
Cursor cur = _context.getContentResolver().query(uri,
new String[] PhoneLookup.DISPLAY_NAME, PhoneLookup._ID ,
null, null, null);
if (cur.moveToFirst())
int nameIdx = cur.getColumnIndex(PhoneLookup.DISPLAY_NAME);
data[0] = cur.getString(nameIdx);
String contactId = cur.getString(cur
.getColumnIndex(PhoneLookup._ID));
Uri photoUri = getContactPhotoUri(Long.parseLong(contactId));
if (photoUri != null)
data[1] = photoUri.toString();
else
data[1] = null;
cur.close();
return data;
catch (Exception e)
e.printStackTrace();
return null;
public Uri getContactPhotoUri(long contactId)
Uri photoUri = ContentUris.withAppendedId(Contacts.CONTENT_URI,
contactId);
photoUri = Uri.withAppendedPath(photoUri,
Contacts.Photo.CONTENT_DIRECTORY);
return photoUri;
SmsMsg.java POJO:
public class SmsMsg
private String address = null;
private String displayName = null;
private String threadId = null;
private String date = null;
private String msg = null;
private String type = null;
Uri photoUri = null;
public Uri getPhotoUri()
return photoUri;
public void setPhotoUri(Uri photoUri)
this.photoUri = photoUri;
public String getDisplayName()
return displayName;
public void setDisplayName(String displayName)
this.displayName = displayName;
public String getAddress()
return address;
public void setAddress(String address)
this.address = address;
public String getThreadId()
return threadId;
public void setThreadId(String threadId)
this.threadId = threadId;
public String getDate()
return date;
public void setDate(String date)
this.date = date;
public String getMsg()
return msg;
public void setMsg(String msg)
this.msg = msg;
public String getType()
return type;
public void setType(String type)
this.type = type;
【问题讨论】:
【参考方案1】:POJO 存储不是一个好方法,因为它们需要一直保留在内存中,否则会重新加载导致痛苦和缓慢。
在这种情况下,您应该创建一个更新 sqlite 数据库的服务,并将其显示为 ContentProvider。 sqlite db 应仅包含 android 未提供的结构,即您的联系人/线程层次结构,以及您可能在列表中显示的任何数据,例如最新消息的文本。
This thread 讨论了如何检测来自您的应用程序或其他应用程序的新 SMS 消息到达/发送,这可能是您真正想要的,而不是简单地检测用户从您自己的应用程序发布消息。 Service 应该执行这个任务,UI Activity 只需要观察 ContentProvider。
顺便说一句:我想知道用户将如何向尚未向其发送消息的联系人发送消息,因为您的列表仅包含他们已向其发送消息的联系人。
【讨论】:
【参考方案2】:您可能需要提供更多详细信息,说明您实际上是如何接近该方向的,特别是您有多少活动(似乎有两个)。
假设有两个,在第一个活动中不要尝试捕获每条消息,只需获取所有 thread_Id 和地址。
然后当用户单击任何列表项时,然后执行其他线程来读取属于该线程的所有消息。
使用以下内容:
Uri uriSMSURI = Uri.parse("content://sms/inbox");
Cursor cur = getContentResolver().query(uriSMSURI, null, null, null, null);
用于读取收件箱并获取 thread_Ids 和地址并将它们存储到一些 java modal 类,即 DTO
并填充列表,当用户单击任何项目时,传递 thread_id,然后像这样查询以获取所有对话,即线程。
Uri uriSMSURI = Uri.parse(Uri.parse("content://sms/conversations/")+ thread_id);
cursor = getContentResolver().query(uriSMSURI, null,"thread_id=?", new String[] tid , null);
【讨论】:
以上是关于Android 从收件箱获取短信,优化的方式来阅读所有消息并将它们分组的主要内容,如果未能解决你的问题,请参考以下文章