通过从 RawContacts 过滤 account_type 列来显示联系人

Posted

技术标签:

【中文标题】通过从 RawContacts 过滤 account_type 列来显示联系人【英文标题】:showing contacts by filtering account_type column from RawContacts 【发布时间】:2018-02-20 18:45:33 【问题描述】:

我在 RecyclerView 和以下代码检索联系人上显示联系人

 Uri Contact_URI=ContactsContract.CommonDataKinds.Phone.CONTENT_URI;


            return  new CursorLoader(getActivity(),Contact_URI,null,null,null,Build.VERSION.SDK_INT
                    >= Build.VERSION_CODES.HONEYCOMB ?
                    ContactsContract.Contacts.DISPLAY_NAME_PRIMARY :
                    ContactsContract.Contacts.DISPLAY_NAME+ "ASC");

但有些联系人会被多次显示,所以我决定在account_type 列上过滤联系人。下面的代码过滤器基于account_type

if(list.getString(list.getColumnIndex("account_type")).equals("Local Phone Account") || list.getString(list.getColumnIndex("account_type")).equals("SIM Account") ) 

            textView.setText(list.getString(list.getColumnIndex(Build.VERSION.SDK_INT
                    >= Build.VERSION_CODES.HONEYCOMB ?
                    ContactsContract.Contacts.DISPLAY_NAME_PRIMARY :
                    ContactsContract.Contacts.DISPLAY_NAME)));
            number.setText(list.getString(list.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
        number.setText(list.getString(list.getColumnIndex("account_type")));

        

问题是 sim 卡和电话联系人的 account_type 值因设备而异。在Samsung GT-l9082 中,为 sim "Sim Account" 和 Phone "Local Phone Account" 提供了值,但是当我在 Galaxy J5 上对其进行测试时,它针对account_type 显示了针对 sim 和电话联系人的不同值。我只想显示 Sim 和电话联系方式

【问题讨论】:

【参考方案1】:

这不是要走的路。

CommonDataKinds.Phone.CONTENT_URI 是联系人数据库中所有手机的表格,而不是联系人。 因此,即使您只过滤到一个帐户,如果某个联系人包含多于一部手机,它也会在您的列表中出现两次。

如果您只想为每个联系人显示一行,但仍需要在主列表中显示电话,则不能使用 CursorLoader 范例(这实际上很糟糕,我也不会使用它) .

改为对Phones.CONTENT_URI 表中的所有项目运行一个简单查询,并创建一个从CONTACT_IDNUMBERs 列表的HashMap,然后在地图中的每个项目显示一行,然后您还可以访问该联系人的电话列表以进行显示。

Map<String, List<String>> contacts = new HashMap<String, List<String>>();

String[] projection =  Phone.CONTACT_ID, Phone.DISPLAY_NAME, Phone.NUMBER ;
Cursor cur = cr.query(Phone.CONTENT_URI, projection, null, null, null);

while (cur != null && cur.moveToNext()) 
    long id = cur.getLong(0);
    String name = cur.getString(1);
    String data = cur.getString(2); // the actual info, e.g. +1-212-555-1234

    Log.d(TAG, "got " + id + ", " + name + ", " + data);

    // add info to existing list if this contact-id was already found, or create a new list in case it's new
    String key = id + " - " + name;
    List<String> infos;
    if (contacts.containsKey(key)) 
        infos = contacts.get(key);
     else 
        infos = new ArrayList<String>();
        contacts.put(key, infos);
    
    infos.add(data);


// now you can iterate over the 'contacts' map to display all contacts

【讨论】:

感谢您的回答。我还认为它可以过滤联系人,但 CursorLoader 返回一个 CursorCursorLoader.query() 在非 UI 线程上运行。所以这没关系。虽然,我同意使用 HashMaps。我接受它作为答案 您可以自己运行查询并在非UI线程上构建HashMap(使用Thread),然后将HashMap传递给适配器以在屏幕上显示数据 我只获取了直接查询ContactsContract.Data 的电话号码并过滤Data.MIMTYPE=Phone.CONTENT_ITEM_TYPE 。它只给我联系人的电话号码,无论是属于 SIM 卡、电话还是任何电子邮件帐户 您在ContactsContract.Data 上提到的查询与在ContactsContract.CommonDataKinds.Phone 上简单查询相同,Phone 表会为您添加 mimetype 选择。 是的,我知道,但现在问题是,如果我在投影Phone.CONTACT_ID, Phone.LOOKUP_KEY,Phone.DISPLAY_NAME_PRIMARY,Phone.NUMBER 中包含这些列,它只会给我保存在联系人中的电话号码,但如果在该投影中包含像 Phone.Data_Version 这样的附加列,它会显示重复项Whatsapp 也有 mimetype 电话。我认为它应该在没有 Phone.Data_Version 列的情况下显示重复项,因为 whatsapp 联系人还使用电话 mimetype 保存号码

以上是关于通过从 RawContacts 过滤 account_type 列来显示联系人的主要内容,如果未能解决你的问题,请参考以下文章

通过从多个列中删除匹配的电子邮件域来过滤 Pandas 数据框

如何通过从 input type='file' 中选择来设置多个视频文件的预览

通过从另一个方法引用设置 NSString

通过从文件中读取值来计算移动平均值

如何通过从 CloudFormation 中删除来从 DynamoDb 中删除全局二级索引?

通过从数组中选择来创建排列