Vraag Android-contacten Weergavenaam en telefoonnummer (s) in query met enkele database?


Ik probeer een lijst met contactpersonen uit de native database te verkrijgen met hun weergavenaam en telefoonnummer (een of meerdere). Er zijn veel methoden om deze informatie te verkrijgen met verschillende vragen in de database van de telefoon, maar dit brengt aanzienlijke overhead met zich mee.

Hier is de vraag waar ik aan gewerkt heb, maar het resultaat is

Uri uri                = ContactsContract.Contacts.CONTENT_URI;
String[] projection    = new String[] { ContactsContract.Contacts._ID,
                                        ContactsContract.Contacts.DISPLAY_NAME,
                                        ContactsContract.CommonDataKinds.Phone.NUMBER};
String selection       = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = '1'";
String[] selectionArgs = null;
String sortOrder       = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";

Cursor people          = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);

int index_id    = people.getColumnIndex(ContactsContract.Contacts._ID);
int indexName   = people.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
int indexNumber = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);

people.moveToFirst();
do {
    String _id    = people.getString(index_id);
    String name   = people.getString(indexName);
    String number = people.getString(indexNumber);
    // Do work...
} while (people.moveToNext());

En hier is de resulterende fout.

E/AndroidRuntime(21549): Caused by: java.lang.IllegalArgumentException: Invalid column data1
E/AndroidRuntime(21549):    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:144)
E/AndroidRuntime(21549):    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:114)
E/AndroidRuntime(21549):    at android.content.ContentProviderProxy.bulkQueryInternal(ContentProviderNative.java:372)
E/AndroidRuntime(21549):    at android.content.ContentProviderProxy.query(ContentProviderNative.java:408)
E/AndroidRuntime(21549):    at android.content.ContentResolver.query(ContentResolver.java:264)

Gedachten? Ik denk dat een join nodig kan zijn om alle kolommen in één query op te halen.


48
2017-07-05 19:14


oorsprong


antwoorden:


Probeer deze code:

Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String[] projection    = new String[] {ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                ContactsContract.CommonDataKinds.Phone.NUMBER};

Cursor people = getContentResolver().query(uri, projection, null, null, null);

int indexName = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
int indexNumber = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);

if(people.moveToFirst()) {
    do {
        String name   = people.getString(indexName);
        String number = people.getString(indexNumber);
        // Do work...
    } while (people.moveToNext());
}

104
2017-07-05 20:20



De API voor contacten is extreem lastig en heeft verschillende impliciete joins.

Lees de ContactContract en ContactsProvider2 als je de tijd kunt veroorloven.

Wat wil je? De tafels zijn als volgt geketend:

  • Contact 1 - * Ruw contact
  • Raw Contact 1 - * Telefoonnummer (gegevenstabel)

De API werkt als volgt: u selecteert het onderste element (een telefoonnummer) en impliciete join aan het bovenste element (contact).

U wilt de PHONE URI-case gebruiken (ContactsProvider2 / regel 4377). Dit moet alle telefoonnummers selecteren en samenvoegen met de contactpersoon.

Combineer de PHONE-uri met wat UI-magie (voor groeperen), vraag de DISPLAY_NAME en het TELEFOON-nummer aan (DATA1?) En je zou het probleem moeten kunnen oplossen.


14
2017-07-05 20:09



Telefoonnummers worden opgeslagen in hun eigen tabel en moeten apart worden opgevraagd. Gebruik de URI die is opgeslagen in de SDK-variabele ContactsContract.CommonDataKinds.Phone.CONTENT_URI om de tabel met het telefoonnummer te doorzoeken. Gebruik een voorwaarde WAARvoor om de telefoonnummers voor de opgegeven contactpersoon te krijgen.

private String displayName(Uri contactUri) {
        HashSet detail = ContactDetail.getInstance().getContactArray();
        Log.d("ITEM", contactUri.toString());
        String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};
        Cursor queryCursor = getActivity().getContentResolver()
                .query(contactUri, null, null, null, null);
        queryCursor.moveToFirst();
        String name = queryCursor.getString(queryCursor.getColumnIndex("display_name"));
        String id = queryCursor.getString(
                queryCursor.getColumnIndex(ContactsContract.Contacts._ID));

        if (Integer.parseInt(queryCursor.getString(queryCursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
            Cursor pCur = getActivity().getContentResolver().query(
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    null,
                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
                    new String[]{id}, null);
            while (pCur.moveToNext()) {
                String number = pCur.getString(pCur.getColumnIndex("data1"));
                Log.d("Contact Name: ", number);
            }
            pCur.close();
        }


        return name;
    }

Voer een tweede query uit op de SQLite-database voor Android-contacten. De telefoonnummers worden bevraagd tegen de URI die is opgeslagen in ContactsContract.CommonDataKinds.Phone.CONTENT_URI. De contact-id wordt opgeslagen in de telefoontabel als ContactsContract.CommonDataKinds.Phone.CONTACT_ID en de WHERE-component wordt gebruikt om de geretourneerde gegevens te beperken.


1
2018-03-24 17:43