2012-12-08 99 views
1

我已经创建了一个小的Android应用程序,可以响应传入的短信。问题是,我似乎无法可靠地获取收件箱中未读邮件的数量。Android短信收件箱未读计数问题

下面是一个最低限度的课程来说明问题。有时它会打印“Got SMS!Unread count:0”,有时会打印“Got SMS!Unread count:1”。对我来说,如果程序流进入该命令,未读计数总是至少为1,那么看起来更合理。我一直在通过将SMS消息从一个模拟器发送到另一个模拟器来进行测试(您可以通过将消息发送到模拟器号码 - 例如5554)来进行测试。

import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.database.Cursor; 
import android.net.Uri; 
import android.util.Log; 

public class SmsReceiver extends BroadcastReceiver { 
private static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED"; 

@Override 
public void onReceive(Context context, Intent intent) { 
    Log.d("onReceive", "Got something: "+intent.getAction()); 
    if (!SMS_RECEIVED_ACTION.equals(intent.getAction())) { 
     Log.d("onReceive", "Returning."); 
     return; 
    } 
    Log.d("onReceive", "Got SMS! Unread count: " + getNumberOfUnreadMessages(context)); 
    // Do stuff 
} 

public int getNumberOfUnreadMessages(Context context) { 
    final Uri SMS_INBOX_URI = Uri.parse("content://sms/inbox"); 
    Cursor inboxCursor = context.getContentResolver().query(SMS_INBOX_URI, null, "read = 0", null, null); 
    int unreadMessagesCount = inboxCursor.getCount(); 
    inboxCursor.close(); 
    return unreadMessagesCount; 
} 
} 

最后,这里的相关部分从AndroidManifest.xml文件:

<receiver android:name=".SmsReceiver" > 
    <intent-filter> 
     <action android:name="android.provider.Telephony.SMS_RECEIVED" /> 
    </intent-filter> 
</receiver> 

我如何获得的未读邮件是否正确?

编辑/添加:或者,如果是在保存SMS之前发送广播的情况,是否有订阅应用程序的方法来侦听新SMS消息被保存到收件箱中?

+0

我有与广播接收机相同的问题。看来,当广播检查游标的未读计数时,新消息就会丢失,就像在数据库中存储消息之前触发广播一样,所以会导致错误的计数。我只是喜欢inboxCursor.getCount()+ 1; – Samet

+0

@Samet是的,就是这样。那么你对此做了什么?只有在邮件保存到数据库后,如何制作广播触发器?请注意,它不会经常失败,只是在其他时间左右,所以'getCount()+ 1'不是一个好的解决方案。 – ZeroOne

+0

,但你应该避免getCount()这很慢,我有经验,有更多的消息,应用程序将挂起。你应该创建一个int count = 1;在循环外,并在游标中移动时,执行count ++;这样它需要几毫秒而不是几秒钟,我想你会得到真正的计数。 – Samet

回答

4

如果你想观察的短信收件箱,使用这样的ContentObserver:)

的OnCreate(:

contentObserver observer = new contentObserver(handler); 
getContentResolver().registerContentObserver(Uri.parse("content://sms/inbox"), true, observer); 

创建一个新的内部类或outter类:

public class contentObserver extends ContentObserver { 

    public contentObserver(Handler handler) { 
     super(handler); 
     // you can use a handler if you want or directly do everythinh onChange(); 
    } 

    @Override 
    public void onChange(boolean selfChange) { 
     // Do your stuff here 
     super.onChange(selfChange); 
    } 
} 

的OnDestroy ():

getContentResolver().unregisterContentObserver(observer); 
+0

谢谢,这可能是比我现在更好的方法。一旦我有机会尝试这个,我会决定接受这个答案。 – ZeroOne

0

我有同样的问题。看起来,当您实际收到短信时,BroadcastReceiver会被触发。这可以在SmsManager将消息写入数据库之前。

收到广播后等待几秒钟,或手动记录您接收广播的次数并增加计数,保存到私有SharedPreferences并在用户读取消息时减少计数。