如何从服务电话簿获取所有联系人

时间:2017-04-28 21:37:14

标签: java android contacts android-contacts contact

我开发的应用程序需要从电话簿中获取所有联系人。联系人案例:Viber,WhatsApp,Telegram。我找到了一个很好的解决方案RxContacts library。但这种变化并没有给我电话簿中的所有联系人。 This is我与作者讨论了这个问题。

如何从服务电话簿中获取所有可用的联系人?

RxContacts
                .fetch(context)
                .filter(contact -> contact.inVisibleGroup == 1)
                .filter(contact -> !contact.phoneNumbers.isEmpty())
                .filter(contact -> contact.phoneNumber.contains(mPhoneField) || contact.displayName.toLowerCase().contains(mPhoneField.toLowerCase()))
                .toSortedList((lhs, rhs) -> lhs.displayName.compareToIgnoreCase(rhs.displayName))
                .compose(RxUtils.async())
                .doOnSubscribe(this::showLoading)
                .compose(mRxLoaderManager.restart(CONTACTS_LOADER))
                .subscribe(this::handleResponse, this::handleContactsError, this::onCompleted);

RxContacts

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.util.LongSparseArray;

import com.elegion.friendlypay.model.rxContacts.Contact;

import rx.Observable;
import rx.Subscriber;

import static com.elegion.friendlypay.rxcontacts.ColumnMapper.mapDisplayName;
import static com.elegion.friendlypay.rxcontacts.ColumnMapper.mapEmail;
import static com.elegion.friendlypay.rxcontacts.ColumnMapper.mapInVisibleGroup;
import static com.elegion.friendlypay.rxcontacts.ColumnMapper.mapPhoneNumber;
import static com.elegion.friendlypay.rxcontacts.ColumnMapper.mapPhoneNumberSingle;
import static com.elegion.friendlypay.rxcontacts.ColumnMapper.mapPhoto;
import static com.elegion.friendlypay.rxcontacts.ColumnMapper.mapStarred;
import static com.elegion.friendlypay.rxcontacts.ColumnMapper.mapThumbnail;


public class RxContacts {

    private static final String[] PROJECTION = {
            ContactsContract.Data.CONTACT_ID,
            ContactsContract.Data.DISPLAY_NAME_PRIMARY,
            ContactsContract.Data.STARRED,
            ContactsContract.Data.PHOTO_URI,
            ContactsContract.Data.PHOTO_THUMBNAIL_URI,
            ContactsContract.Data.DATA1,
            ContactsContract.Data.MIMETYPE,
            ContactsContract.Data.IN_VISIBLE_GROUP
    };

    private ContentResolver resolver;

    /**
     * Fetches all contacts from the contacts apps and social networking apps.
     * @param context The context.
     * @return Observable that emits contacts on success.
     */
    public static Observable<Contact> fetch (@NonNull final Context context) {
        return Observable.create(new Observable.OnSubscribe<Contact>() {
            @Override
            public void call (Subscriber<? super Contact> subscriber) {
                new RxContacts(context).fetch(subscriber);
            }
        });
    }

    private RxContacts (@NonNull Context context) {
        resolver = context.getContentResolver();
    }

    private void fetch (Subscriber<? super Contact> subscriber) {
        LongSparseArray<Contact> contacts = new LongSparseArray<>();
        // Create a new cursor and go to the first position
        Cursor cursor = createCursor();
        cursor.moveToFirst();
        // Get the column indexes
        int idxId = cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
        int idxInVisibleGroup = cursor.getColumnIndex(ContactsContract.Data.IN_VISIBLE_GROUP);
        int idxDisplayNamePrimary = cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME_PRIMARY);
        int idxStarred = cursor.getColumnIndex(ContactsContract.Data.STARRED);
        int idxPhoto = cursor.getColumnIndex(ContactsContract.Data.PHOTO_URI);
        int idxThumbnail = cursor.getColumnIndex(ContactsContract.Data.PHOTO_THUMBNAIL_URI);
        int idxMimetype = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE);
        int idxData1 = cursor.getColumnIndex(ContactsContract.Data.DATA1);
        // Map the columns to the fields of the contact
        while (!cursor.isAfterLast()) {
            // Get the id and the contact for this id. The contact may be a null.
            long id = cursor.getLong(idxId);
            Contact contact = contacts.get(id, null);
            if (contact == null) {
                // Create a new contact
                contact = new Contact(id);
                // Map the non collection attributes
                mapInVisibleGroup(cursor, contact, idxInVisibleGroup);
                mapDisplayName(cursor, contact, idxDisplayNamePrimary);
                mapStarred(cursor, contact, idxStarred);
                mapPhoto(cursor, contact, idxPhoto);
                mapThumbnail(cursor, contact, idxThumbnail);
                // Add the contact to the collection
                contacts.put(id, contact);
            } else {
                String mimetype = cursor.getString(idxMimetype);
                switch (mimetype) {
                    case ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE: {
                        mapEmail(cursor, contact, idxData1);
                        break;
                    }
                    case ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE: {
                        mapPhoneNumber(cursor, contact, idxData1);
                        //while (contact.phoneNumbers.iterator().hasNext())
                        mapPhoneNumberSingle(cursor, contact, idxData1);
                        break;
                    }
                }
            }
            cursor.moveToNext();
        }
        // Close the cursor
        cursor.close();
        // Emit the contacts
        for (int i = 0; i < contacts.size(); i++) {
            subscriber.onNext(contacts.valueAt(i));
        }
        subscriber.onCompleted();
    }

    private Cursor createCursor () {
        return resolver.query(
                ContactsContract.Data.CONTENT_URI,
                PROJECTION,
                null,
                null,
                ContactsContract.Data.CONTACT_ID
        );
    }
}

ColumnMapper

class ColumnMapper {

    // Utility class -> No instances allowed
    private ColumnMapper () {}

    static void mapInVisibleGroup (Cursor cursor, Contact contact, int columnIndex) {
        contact.inVisibleGroup = cursor.getInt(columnIndex);
    }

    static void mapDisplayName (Cursor cursor, Contact contact, int columnIndex) {
        String displayName = cursor.getString(columnIndex);
        if (displayName != null && !displayName.isEmpty()) {
            contact.displayName = displayName;
        }
    }

    static void mapEmail (Cursor cursor, Contact contact, int columnIndex) {
        String email = cursor.getString(columnIndex);
        if (email != null && !email.isEmpty()) {
            contact.emails.add(email);
        }
    }

    static void mapPhoneNumber (Cursor cursor, Contact contact, int columnIndex) {
        String phoneNumber = cursor.getString(columnIndex);
        if (phoneNumber != null && !phoneNumber.isEmpty() && ValidationPhoneUtil.isValidPhone(phoneNumber)) {
            // Remove all whitespaces
            phoneNumber = phoneNumber.replaceAll("\\s+","");
            contact.phoneNumbers.add(phoneNumber);
        }
    }

    static void mapPhoneNumberSingle (Cursor cursor, Contact contact, int columnIndex) {
        String phoneNumber = cursor.getString(columnIndex);
        if (phoneNumber != null && !phoneNumber.isEmpty() && ValidationPhoneUtil.isValidPhone(phoneNumber)) {
            // Remove all whitespaces
            phoneNumber = phoneNumber.replaceAll("\\s+","");
            contact.phoneNumber += phoneNumber + "\n";
        }
    }

    static void mapPhoto (Cursor cursor, Contact contact, int columnIndex) {
        String uri = cursor.getString(columnIndex);
        if (uri != null && !uri.isEmpty()) {
            contact.photo = Uri.parse(uri);
        }
    }

    static void mapStarred (Cursor cursor, Contact contact, int columnIndex) {
        contact.starred = cursor.getInt(columnIndex) != 0;
    }

    static void mapThumbnail (Cursor cursor, Contact contact, int columnIndex) {
        String uri = cursor.getString(columnIndex);
        if (uri != null && !uri.isEmpty()) {
            contact.thumbnail = Uri.parse(uri);
        }
    }
}

import android.net.Uri;

import java.util.HashSet;
import java.util.Set;


/**
 * Contact entity.
 * @author Ulrich Raab
 */
public class Contact {

    /**
     * The unique id of this contact.
     */
    public final long id;

    /**
     * Flag indicating if this contact should be visible in any user interface.
     */
    public int inVisibleGroup;

    /**
     * The display name of this contact.
     */
    public String displayName;

    /**
     * Flag indicating if this contact is a favorite contact.
     */
    public boolean starred;

    /**
     * The URI of the full-size photo of this contact.
     */
    public Uri photo;

    /**
     * The URI of the thumbnail of the photo of this contact.
     */
    public Uri thumbnail;

    /**
     * The email addresses of this contact.
     */
    public Set<String> emails = new HashSet<>();

    /**
     * The phone numbers of this contact.
     */
    public Set<String> phoneNumbers = new HashSet<>();

    /**
     * Creates a new contact with the specified id.
     * @param id The id of the contact.
     */
    Contact (long id) {
        this.id = id;
    }

    @Override
    public int hashCode () {
        return (int) (id ^ (id >>> 32));
    }

    @Override
    public boolean equals (Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Contact contact = (Contact) o;
        return id == contact.id;
    }
}

2 个答案:

答案 0 :(得分:1)

答案 1 :(得分:0)

似乎已在1.1.4版本中修复:https://github.com/UlrichRaab/rx-contacts/releases/tag/1.1.4

干杯