web-dev-qa-db-fra.com

Android contacts afficher le nom et le (s) numéro (s) de téléphone dans une seule requête de base de données?

J'essaie d'obtenir une liste de contacts de la base de données native avec leur nom d'affichage et leur numéro de téléphone (tout ou partie). Il existe de nombreuses méthodes pour obtenir ces informations avec plusieurs requêtes dans la base de données du téléphone, mais cela entraîne une surcharge considérable.

Voici la requête sur laquelle je travaille, mais elle aboutit à

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());

Et voici l'erreur qui en résulte.

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)

Pensées? Je crois qu'une jointure peut être nécessaire pour obtenir toutes les colonnes dans une seule requête.

49
Derek

Essayez ce 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
jamapag

L'API des contacts est extrêmement délicate et a plusieurs jointures implicites .

Lisez les ContactContract et ContactsProvider2 si vous pouvez vous le permettre.

Qu'est-ce que vous voulez? Les tables sont enchaînées comme ceci:

  • Contact 1 - * Contact brut
  • Contact brut 1 - * Numéro de téléphone (tableau de données)

L'API fonctionne comme ceci: vous sélectionnez l'élément le plus bas (un numéro de téléphone) et la jointure implicite à l'élément le plus haut (contact).

Vous souhaitez utiliser le boîtier PHONE URI (ContactsProvider2/ligne 4377). Cela devrait sélectionner tous les numéros de téléphone et rejoindre le contact.

Combinez l'URI du TÉLÉPHONE avec de la magie d'interface utilisateur (pour le regroupement), demandez le DISPLAY_NAME et le numéro de TÉLÉPHONE (DATA1?) Et vous devriez être en mesure de résoudre le problème.

14
treffer

Les numéros de téléphone sont stockés dans leur propre table et doivent être interrogés séparément. Pour interroger la table des numéros de téléphone, utilisez l'URI stocké dans la variable SDK ContactsContract.CommonDataKinds.Phone.CONTENT_URI. Utilisez une condition WHERE pour obtenir les numéros de téléphone du contact spécifié.

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;
    }

Exécutez une seconde requête sur la base de données SQLite Android contacts. Les numéros de téléphone sont interrogés par rapport à l'URI stocké dans ContactsContract.CommonDataKinds.Phone.CONTENT_URI. L'ID du contact est stocké dans la table téléphonique en tant que ContactsContract. CommonDataKinds.Phone.CONTACT_ID et la clause WHERE sont utilisés pour limiter les données renvoyées.

1
rinkesh