如何使用 Telephony.Sms 仅检索每个对话的最后一条消息,包括锁定的消息?

Posted

技术标签:

【中文标题】如何使用 Telephony.Sms 仅检索每个对话的最后一条消息,包括锁定的消息?【英文标题】:How to retrieve only the last message of every conversation including the locked message using Telephony.Sms? 【发布时间】:2018-03-27 23:37:26 【问题描述】:

我正在使用以下代码从短信中检索消息。

private List<String> getEveryLastMessages()
    List<String> listSms = new ArrayList<String>();
    ContentResolver contentResolver = getActivity().getContentResolver();

    Cursor c = contentResolver.query(Telephony.Sms.Inbox.CONTENT_URI, // Official CONTENT_URI from docs
                new String[]  Telephony.Sms.Inbox.BODY , // Select body text
                null,
                null,
                Telephony.Sms.Inbox.DEFAULT_SORT_ORDER); // Default sort order

    int totalSMS = c.getCount();

    if (c.moveToFirst()) 
        for (int i = 0; i < totalSMS; i++) 
            listSms.add(c.getString(0));
            listSms.add("\n");
            c.moveToNext();
        
     else 
        //Do something, no messages
    
    c.close(); 

        return listSms;

我的问题是所有消息都被检索到了,除了锁定的消息。

我想要实现的是只检索最后一条消息 每个对话(包括锁定消息)并将其填充到我的 recyclerview 适配器中以将其显示为收件箱。

【问题讨论】:

嗯,这似乎不是标准行为。您确定锁定的消息是收到的消息吗?也就是说,您确定它在收件箱中吗?您正在测试哪个 android 版本?如果这是一个实际的设备,它具体是什么?此外,您声明您想要“每次对话的最后一条消息”。如果最后一条消息是已发送的消息怎么办?根据您的需要,this post 可能会有所帮助。 是的,锁定的消息是收到的消息。不确定锁定的消息是否在收件箱中,但android的默认信使在列表中,它只是被锁定。我目前正在 Android Marshmallow 上对其进行测试,是的,我正在使用型号为 INFINIX HOT S X521 的实际设备。最后一条消息是否发送、发送失败、草稿、锁定等无关紧要,只要它是每个对话中的最后内容即可。谢谢,我会检查那个帖子。 好的,我只是在询问收到/收件箱,因为这就是您在 sn-p 中查询的全部内容 - Telephony.Sms.Inbox.CONTENT_URI。 Anyhoo,从 Marshmallow 开始,非默认应用只能访问 SMS 表的受限视图,并且只能获取 inboxsent 消息,因此您不会除非您的应用是默认消息应用,否则会收到 faileddraft 消息。但是,locked 与那些是分开的,不应该出现在那个受限视图中,至少在标准 API 中是这样。不过,OEM 可能会更改其中任何一项。 awt.就是这样,让我试试我从你分享的链接中得到了什么。 @Mike M. - 请将您的评论放入答案中,我想将其标记为正确答案。谢谢! 【参考方案1】:

如果您想要每次对话中的最后一条消息,无论是发送还是接收,都可以使用方便的内置 URI,而不是只抓取所有内容并自行过滤。

Telephony.Sms.Conversations.CONTENT_URI(在android.provider 包中)可用于ContentResolver 查询以检索可用对话的摘要。例如:

Cursor c = contentResolver.query(Telephony.Sms.Conversations.CONTENT_URI,
                                 null, null, null, null);

此查询将返回三列:

Telephony.Sms.Conversations.SNIPPET ("snippet") Telephony.Sms.Conversations.MSG_COUNT ("msg_count") Telephony.Sms.Conversations.THREAD_ID ("thread_id")

SNIPPET 列将是该对话中最新的可用消息。

不幸的是,从 Marshmallow(API 级别 21)开始,任何不是默认消息应用程序的应用程序都只能访问 SMS 表的受限视图。这样的应用程序只能获取带有Telephony.Sms.TYPEMESSAGE_TYPE_INBOXMESSAGE_TYPE_SENT 的消息。这意味着你不会得到MESSAGE_TYPE_FAILEDMESSAGE_TYPE_DRAFT等,除非你的应用是当前的默认应用。

但是,Telephony.Sms.LOCKED 列是与 TYPE 列完全分开的分类,因此不应出现在受限视图中。也就是说,您应该能够收到锁定的消息,只要它们是sentinbox,无论您的应用是否是默认应用。当然,制造商可能已经改变了上述任何行为,您可能需要在您的应用中考虑到这一点。

【讨论】:

以上是关于如何使用 Telephony.Sms 仅检索每个对话的最后一条消息,包括锁定的消息?的主要内容,如果未能解决你的问题,请参考以下文章

android.provider.Telephony.SMS_RECEIVED 的广播者权限

寻找 Telephony.Sms 和 CallLog.Calls 之间的通用联系人 ID

Android,在服务当前不可用时使用 Telephony.SMS_RECEIVED 操作接收广播

权限拒绝:广播 Intent act=android.provider.Telephony.SMS_RECEIVED

在 Android 4.4.2 上更改 SMS 应用默认值

特定号码的SMS消息未显示在其他Android设备上