Telephony.Sms.Inbox.PERSON 使用已弃用的 Contacts.People._ID
Posted
技术标签:
【中文标题】Telephony.Sms.Inbox.PERSON 使用已弃用的 Contacts.People._ID【英文标题】:Telephony.Sms.Inbox.PERSON uses deprecated Contacts.People._ID 【发布时间】:2017-05-20 14:05:32 【问题描述】:赏金奖 - 赏金将颁发给仅使用ContractsContact
表从填充的Telephony.Sms.Inbox.PERSON
值到关联的Contact
的答案。
我正在我的应用程序中以标准方式阅读 SMS 消息:
final String[] projection = Telephony.Sms.Inbox.BODY,
Telephony.Sms.Inbox.ADDRESS,
Telephony.Sms.Inbox.READ,
Telephony.Sms.Inbox.DATE,
Telephony.Sms.Inbox.PERSON;
final Cursor cursor = ctx.getContentResolver().query(Telephony.Sms.Inbox.CONTENT_URI,
projection, null, null, Telephony.Sms.Inbox.DEFAULT_SORT_ORDER);
填充后,从索引 Telephony.Sms.Inbox.PERSON
返回的 id 与已弃用的 Contacts.People._ID
的 id 相关,可用于通过以下方式查询更多联系信息:
final String[] projection = Contacts.People.DISPLAY_NAME;
final String[] selectionArgs = contactId;
final Cursor cursor = ctx.getContentResolver().query(Contacts.People.CONTENT_URI,
projection, Contacts.People._ID + " = ?", selectionArgs, null);
为什么相对较新的Telephony API 会使用deprecated tables,而不是ContactsContract?
Telephony.Sms.Inbox.PERSON 文档状态:
类型:INTEGER(引用 content://contacts/people 中的项目)
我尝试在任何 ContactsContract
id 字段中查找到 id 的映射,但没有成功(但并不奇怪?),因此我不得不使用已弃用的 API 来解决我需要的查询快速执行。
此类查询包括搜索特定联系人的消息,我只知道该联系人的姓名。联系人可能有多个号码,其格式可能与Telephony.Sms.Inbox.ADDRESS
条目不匹配.....
使用Telephony.Sms.Inbox.ADDRESS
和ContactsContract.PhoneLookup 的workaround 不是从号码到联系人的世界末日,但我仍然觉得我一定在这里错过了什么?
这是我用来获取“Joe Bloggs”消息的过程。
1) 查询ContactsContract
表以确认设备上存在名为 Joe Bloggs 的联系人 - 如果联系人实际上被列为“Joe Blogs”,则获得密切匹配。
2) 使用确认的名称,我查询已弃用的Contact.People
表,以通过以下方式获取联系人的所有关联 ID:
final String selection = Contacts.People.DISPLAY_NAME + " LIKE ?";
final String[] projection = Contacts.People.DISPLAY_NAME,
Contacts.People._ID;
final String[] selectionArgs = contactName;
final Cursor cursor = ctx.getContentResolver().query(Contacts.People.CONTENT_URI,
projection, selection, selectionArgs, null);
3) 使用已弃用的联系人 ID 列表,我查询消息表如下:
final String[] referredArgs = new String[contactIdArray.size()];
for (int i = 0; i < contactIdArray.size(); i++)
referredArgs[i] = contactIdArray.get(i);
final String referredSelection = Telephony.Sms.Inbox.PERSON + " IN "
+ "(" + TextUtils.join(",", referredArgs) + ")";
final String[] projection = Telephony.Sms.Inbox.BODY,
Telephony.Sms.Inbox.ADDRESS,
Telephony.Sms.Inbox.READ,
Telephony.Sms.Inbox.DATE,
Telephony.Sms.Inbox.PERSON;
final Cursor cursor = ctx.getContentResolver().query(Telephony.Sms.Inbox.CONTENT_URI,
projection, referredSelection, null, Telephony.Sms.Inbox.DEFAULT_SORT_ORDER);
我希望有人会告诉我,我正在到处转转,使用当前的 API 有一个更明显的解决方案。 我不考虑使用 ContactsContract.PhoneLookup
迭代整个消息表优化的解决方案。
提前致谢。
【问题讨论】:
【参考方案1】:如果我是你,我不会使用Telephony.Sms.Inbox.PERSON
字段,也绝对不会查询已弃用的People
api。
People
api 已经被弃用了很长时间,你不能指望我们那里的所有设备都能够正确地支持它。
您需要了解的第一件事是短信和联系人之间没有一对一的链接。 SMS 可以来自非联系人电话号码、单个联系人、多个联系人、联系人和非联系人的混合、字母数字 ID,甚至其他更罕见的选项。
接下来,您应该仔细阅读股票代码以及它如何处理您可以从 SMS 集合中获得的正确称为“收件人 ID”的集合,有一个名为 canonical-addresses
(或 canonical-address
)的集合用作电话号码(或以逗号分隔的电话列表)和收件人 ID 之间的映射。
该代码在启动时执行单个查询以将整个表缓存在内存中,然后使用它在电话和收件人 ID 之间进行映射。
这是mapping class
【讨论】:
感谢您的回答 - 我很感激there isn't a one-to-one link between sms and contacts
,但是在收到短信/彩信后某处“创建”了一个,这导致填充了“id/ids”。从您的链接中,我试图在 android 源代码中从地址中找到此映射发生的位置,但没有任何乐趣。我想知道现在是否由默认的短信/彩信提供商来实现这一点?请问您有这方面的经验吗?
我想我可能已经找到它here。它建议它使用ContactsContract.CommonDataKinds.Phone
?我发誓我已经检查过这个 id 不匹配。
@brandall 一个联系人可以删除/创建/更改,并且可以有多个不同的联系人具有相同的号码,短信数据库跟不上联系人数据库的变化,唯一的事情无法更改的是发送/接收该短信的规范地址,这就是为什么 RecipientId 必须映射到电话而不是联系人的原因。其余的是,如在 mms.data.Contact.java 中实现的,由实现者在规范地址和联系人之间进行映射
我听到了,但系统会在某处创建规范地址和 Person
之间的映射,只要有可能。这就是我所追求的,因为当我找到它时,我可以扭转这个过程。 Phone
id 与上面的评论不匹配,Contacts
id 引用自 here 也不匹配。我目前正在对“ContactsContract”中引用的所有 id 字段重新运行查询,以确保我没有第一次忽略一个。【参考方案2】:
为什么相对较新的 Telephony API 会使用已弃用的表,而不是 ContactsContract?
你指的是不是新的。在Telephony.java 中,您会看到它依赖于现有的content://sms
提供程序:
public static final class Inbox implements BaseColumns, TextBasedSmsColumns
/**
* The @code content:// style URL for this table.
*/
public static final Uri CONTENT_URI = Uri.parse("content://sms/inbox");
它已经是there in Donut(可能之前,但我没有检查)。
Kitkat is the ability to change the SMS app 的新功能。
【讨论】:
【参考方案3】:我没有正确理解您的担忧,但我正在从事类似的项目,这里是基本代码,以及用于获取和显示消息的基本重要列:
ContentResolver contentResolver = getContentResolver();
final String[] projection = new String[]"*";
Cursor SMSL = contentResolver.query(Telephony.Sms.CONTENT_URI, projection, null, null, "date ASC");
int msgscount = SMSL.getCount();
if (msgscount>0)
msgs = new String[SMSL.getCount()][msgs_column_count];
int i = 0;
while (SMSL.moveToNext())
progress.setProgress(i);
msgs[i][0] = SMSL.getString(SMSL.getColumnIndex("address"));
msgs[i][1] = SMSL.getString(SMSL.getColumnIndex("date_sent"));
msgs[i][2] = SMSL.getString(SMSL.getColumnIndex("date"));
msgs[i][3] = SMSL.getString(SMSL.getColumnIndex("type"));
msgs[i][4] = SMSL.getString(SMSL.getColumnIndex("body"));
msgs[i][5] = SMSL.getString(SMSL.getColumnIndex("read"));
if (SMSL.getString(SMSL.getColumnIndex("service_center")) != null)
msgs[i][6] = SMSL.getString(SMSL.getColumnIndex("service_center"));
else
msgs[i][6] = "";
i++;
SMSL.close();
else
msgs = new String[0][0];
Toast.makeText(getApplicationContext(),"No messages found!",Toast.LENGTH_LONG).show();
如果您在这方面需要任何帮助或获取消息,请告诉我。
【讨论】:
问题是问为什么PERSON
的返回值与已弃用的Contacts.People
id 相关,而不是使用ContactsContract
表中的值。查询消息表不是问题。以上是关于Telephony.Sms.Inbox.PERSON 使用已弃用的 Contacts.People._ID的主要内容,如果未能解决你的问题,请参考以下文章