从内容提供者那里获取联系人,没有重复或无效的联系人,并保存到 Realm

Posted

技术标签:

【中文标题】从内容提供者那里获取联系人,没有重复或无效的联系人,并保存到 Realm【英文标题】:Obtaining contacts from content provider without duplicates or invalid contacts, and save to Realm 【发布时间】:2017-01-15 05:47:42 【问题描述】:

我有这段代码(感谢@EpicPandaForce 提供),但我在删除时遇到了问题。当我添加新联系人时,它就像一个魅力,而当我删除联系人(或该联系人中的号码,如果有两个联系人)时,它会保留在 Realm 中。我怎样才能让它正常工作?

realm.executeTransaction(new Realm.Transaction() 
        @Override
        public void execute(Realm realm) 
            Contact realmContact = new Contact();
            String filter = "" + ContactsContract.Contacts.HAS_PHONE_NUMBER + " > 0 and "
                    + ContactsContract.CommonDataKinds.Phone.TYPE +"="
                    + ContactsContract.CommonDataKinds.Phone.TYPE_MAIN;

            Cursor phones = getActivity()
                    .getContentResolver()
                    .query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, filter, null, null);

            while (phones.moveToNext()) 
                String id = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID));
                String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                realmContact.setId(id);
                realmContact.setName(name);
                realmContact.setNumber(phoneNumber);
                realmContact.setIsBeingSaved(true);
                realm.insertOrUpdate(realmContact);
            

            /** merge mechanism */
            realm.where(Contact.class)
                    .equalTo("isBeingSaved", false)
                    .findAll()
                    .deleteAllFromRealm(); // delete all non-saved data
            for(Contact contact : realm.where(Contact.class).findAll()) 
                realmContact.setIsBeingSaved(false); // reset all save state
            

联系人.class

public class Contact extends RealmObject

    @PrimaryKey
    private String id;

    @Index
    private String name;

    @Index
    private String number;

    @Index
    private boolean isBeingSaved;

    public String getId() 
        return id;
    

    public void setId(String id) 
        this.id = id;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public String getNumber() 
        return number;
    

    public void setNumber(String number) 
        this.number = number;
    

    public boolean getIsBeingSaved() 
        return isBeingSaved;
    

    public void setIsBeingSaved(boolean beingSaved) 
        isBeingSaved = beingSaved;
    

编辑 - 工作代码:

Contact realmContact = new Contact();

            Uri uri = Contacts.CONTENT_URI;

            String selection = "((" + CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY + " NOTNULL) AND ("
                    + Contacts.HAS_PHONE_NUMBER + "=1) AND ("
                    + CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY + " != '' ))";

            Cursor phones = getActivity()
                    .getContentResolver()
                    .query(uri, null, selection, null, null);

            String phoneNumber = "";
            while (phones.moveToNext()) 
                String id = phones.getString(phones.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
                String name = phones.getString(phones.getColumnIndex(Contacts.DISPLAY_NAME_PRIMARY));
                String lastTimeContacted = phones.getString(phones.getColumnIndex(Contacts.LAST_TIME_CONTACTED));

                if(Integer.parseInt(phones.getString(phones.getColumnIndex(Contacts.HAS_PHONE_NUMBER))) > 0)
                    Cursor pCur = getActivity().getContentResolver().query(
                            CommonDataKinds.Phone.CONTENT_URI,
                            null,
                            CommonDataKinds.Phone.LOOKUP_KEY +" = ?",
                            new String[]id, null);

                    while (pCur.moveToNext()) 
                        phoneNumber += "/" + pCur.getString(pCur.getColumnIndex(CommonDataKinds.Phone.NUMBER));
                        realmContact.setNumber(phoneNumber);
                    
                    phoneNumber = "";
                    pCur.close();
                 else 
                    realmContact.setNumber("1234");
                
                realmContact.setId(id);
                realmContact.setName(lastTimeContacted);
                realmContact.setIsBeingSaved(true);
                realm.insertOrUpdate(realmContact);
            

            Log.i("asd-size", realm.where(Contact.class).findAll().size() + "");

            /** merge mechanism */
            realm.where(Contact.class)
                    .equalTo("isBeingSaved", false)
                    .findAll()
                    .deleteAllFromRealm(); // delete all non-saved data


            for(Contact contact : realm.where(Contact.class).findAll()) 
                contact.setIsBeingSaved(false); // reset all save state
            

【问题讨论】:

@EpicPandaForce 刚刚发现DELETED 列已记录,但未实施:D 来源:***.com/questions/30609515/… 似乎有解决方法,但通常情况下还是相反:) ...伙计,联系人过于复杂了-_- 如果这个没有任何反应,我会在它可用时悬赏它 与此同时,我发现LOOKUP_KEY_ID 更推荐,因为后者在聚合发生时会发生变化:***.com/questions/5151885/… @EpicPandaForce 我找到了答案,我希望你不会因此而生我的气...... 【参考方案1】:

好吧,找了好久发现有错别字:

        /** merge mechanism */
        realm.where(Contact.class)
                .equalTo("isBeingSaved", false)
                .findAll()
                .deleteAllFromRealm(); // delete all non-saved data
        for(Contact contact : realm.where(Contact.class).findAll()) 
            realmContact.setIsBeingSaved(false); <- here it is
        

它是realmContact,实际上它应该是contact,所以它指的是for循环迭代的联系人。

所以,基本上,它将Contact realmContact = new Contact(); 设置为false。所以正确的版本是:

           /** merge mechanism */
            realm.where(Contact.class)
                    .equalTo("isBeingSaved", false)
                    .findAll()
                    .deleteAllFromRealm(); // delete all non-saved data
            for(Contact contact : realm.where(Contact.class).findAll()) 
                contact.setIsBeingSaved(false);
            

【讨论】:

哈哈哈哦好吧!同时,您从内容提供商那里获得的新联系查询是什么?毕竟他们说_ID 不是很稳定 我用实际代码更新了问题 :) 我现在使用 LOOKUP_KEY 更有希望 - 而不是 3245 你得到的东西看起来更像哈希码。另外,我更新了selection。仍然有 WhatsApp 重复号码,但我虽然 Maybe someone will use that channel instead of phone? 所以我保持原样,但现在所有号码都在一个联系人下:)

以上是关于从内容提供者那里获取联系人,没有重复或无效的联系人,并保存到 Realm的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Android 中的联系人列表中获取联系人?使用联系提供商

如何从联系人那里获取电子邮件

如何从已知联系人获取组名

从电话联系人中获取姓名、电话号码和电子邮件地址[关闭]

Android 联系人列表获取地址

Android读取短信和联系人