1 つの SQLite クエリで連絡先 ID、メール、電話番号を取得する方法 連絡先 Android の最適化 質問する

1 つの SQLite クエリで連絡先 ID、メール、電話番号を取得する方法 連絡先 Android の最適化 質問する

少なくとも 1 つの電話番号を持つすべての連絡先を取得したいのですが、すべての連絡先のすべての電話番号とすべてのメールも取得したいです。

現在のコード:

// To get All Contacts having atleast one phone number.

Uri uri = ContactsContract.Contacts.CONTENT_URI;
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " > ?";
String[] selectionArgs = new String[] {"0"};
Cursor cu = applicationContext.getContentResolver().query(uri, 
                null, selection, selectionArgs, null);

// For getting All Phone Numbers and Emails further queries : 
while(cu.moveToNext()){
String id = cu.getString(cu.getColumnIndex(ContactsContract.Contacts._ID));


 // To get Phone Numbers of Contact
    Cursor pCur = context.getContentResolver().query(
    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,  null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=?",
 new String[]{id}, null);

// To get Email ids of Contact
Cursor emailCur = context.getContentResolver().query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?",
new String[]{id}, null); 

// Iterate through these cursors to get Phone numbers and Emails
}

デバイスに 1000 件を超える連絡先がある場合、時間がかかりすぎます。連絡先ごとに 2 つの追加クエリを実行するのではなく、1 回のクエリですべてのデータを取得するにはどうすればよいでしょうか。

それとも、最適化する他の方法はありますか?

よろしくお願いします。

ベストアンサー1

ICS: クエリを実行すると、Data.CONTENT_URI関連付けられているすべての行がContactすでに結合されます。つまり、次のように動作します。

ジャワ:

    ContentResolver resolver = getContentResolver();
    Cursor c = resolver.query(
            Data.CONTENT_URI, 
            null, 
            Data.HAS_PHONE_NUMBER + "!=0 AND (" + Data.MIMETYPE + "=? OR " + Data.MIMETYPE + "=?)", 
            new String[]{Email.CONTENT_ITEM_TYPE, Phone.CONTENT_ITEM_TYPE},
            Data.CONTACT_ID);
    
    while (c.moveToNext()) {
        long id = c.getLong(c.getColumnIndex(Data.CONTACT_ID));
        String name = c.getString(c.getColumnIndex(Data.DISPLAY_NAME));
        String data1 = c.getString(c.getColumnIndex(Data.DATA1));
        
        System.out.println(id + ", name=" + name + ", data1=" + data1);
    }

コトリン:

        var c : Cursor? = null
        try {
                val resolver : ContentResolver = this.contentResolver //Replace "this" With Whatever The Reference To Your Activity Is (If Need Be)
                c = resolver.query(
                    ContactsContract.Data.CONTENT_URI,
                    null,
                    ContactsContract.Data.HAS_PHONE_NUMBER + "!=0 AND (" + ContactsContract.Data.MIMETYPE + "=? OR " + ContactsContract.Data.MIMETYPE + "=?)",
                    arrayOf(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE),
                    ContactsContract.Data.CONTACT_ID)

                if (c!!.count > 0) {
                    while (c.moveToNext()) {
                        val id : Long = c.getLong(c.getColumnIndex(ContactsContract.Data.CONTACT_ID))
                        val name : String = c.getString(c.getColumnIndex(ContactsContract.Data.DISPLAY_NAME))
                        val data1 : String = c.getString(c.getColumnIndex(ContactsContract.Data.DATA1))

                        Log.d("Tag", "$id) name=$name, data1=$data1")
                    }
                }
        } finally {
            c?.close() //<-- close if not null
        }

HAS_PHONE_NUMBER2.3 をターゲットにしている場合は、クエリ時に使用する結合を通じて が利用できないという事実を考慮する必要がありますData

楽しい

これは、例えば、連絡先の要件をスキップすることで解決できます。しなければならない電話番号を持たず、「少なくとも電話番号または電子メールアドレスを持つ連絡先」で済ませる:

Cursor c = resolver.query(
        Data.CONTENT_URI, 
        null, 
        Data.MIMETYPE + "=? OR " + Data.MIMETYPE + "=?", 
        new String[]{Email.CONTENT_ITEM_TYPE, Phone.CONTENT_ITEM_TYPE},
        Data.CONTACT_ID);

それが選択肢にない場合は、常にひどいハッキーサブ選択:

Cursor c = resolver.query(
        Data.CONTENT_URI, 
        null, 
        "(" + Data.MIMETYPE + "=? OR " + Data.MIMETYPE + "=?) AND " + 
        Data.CONTACT_ID + " IN (SELECT " + Contacts._ID + " FROM contacts WHERE " + Contacts.HAS_PHONE_NUMBER + "!=0)", 
        new String[]{Email.CONTENT_ITEM_TYPE, Phone.CONTENT_ITEM_TYPE}, Data.CONTACT_ID);

または、 Cursors:

Cursor contacts = resolver.query(Contacts.CONTENT_URI, 
        null, Contacts.HAS_PHONE_NUMBER + " != 0", null, Contacts._ID + " ASC");
Cursor data = resolver.query(Data.CONTENT_URI, null, 
        Data.MIMETYPE + "=? OR " + Data.MIMETYPE + "=?", 
        new String[]{Email.CONTENT_ITEM_TYPE, Phone.CONTENT_ITEM_TYPE}, 
        Data.CONTACT_ID + " ASC");

int idIndex = contacts.getColumnIndexOrThrow(Contacts._ID);
int nameIndex = contacts.getColumnIndexOrThrow(Contacts.DISPLAY_NAME);
int cidIndex = data.getColumnIndexOrThrow(Data.CONTACT_ID);
int data1Index = data.getColumnIndexOrThrow(Data.DATA1);
boolean hasData = data.moveToNext();

while (contacts.moveToNext()) {
    long id = contacts.getLong(idIndex);
    System.out.println("Contact(" + id + "): " + contacts.getString(nameIndex));
    if (hasData) {
        long cid = data.getLong(cidIndex);
        while (cid <= id && hasData) {
            if (cid == id) {
                System.out.println("\t(" + cid + "/" + id + ").data1:" + 
                        data.getString(data1Index));
            }
            hasData = data.moveToNext();
            if (hasData) {
                cid = data.getLong(cidIndex);
            }
        }
    }
}

おすすめ記事