20

मैं फोन रिकॉर्ड खोजने के लिए ContactsContract.Data तालिका से पूछताछ कर रहा हूं।अंतर्निहित कॉलम एंड्रॉइड संपर्क डेटा के साथ कॉलम कैसे काम करते हैं?

जब मैं एक नया CursorLoader बनाने मैं एक त्रुटि मिलती है:

java.lang.IllegalArgumentException: Invalid column deleted 

मेरे कोड:

import android.provider.ContactsContract.CommonDataKinds.Phone; 
import android.provider.ContactsContract.Data; 

... 

String[] projection = { 
    Phone.DELETED, 
    Phone.LOOKUP_KEY, 
    Phone.NUMBER, 
    Phone.TYPE, 
    Phone.LABEL, 
    Data.MIMETYPE, 
    Data.DISPLAY_NAME_PRIMARY 
}; 

// "mimetype = ? AND deleted = ?" 
String selection = Data.MIMETYPE + " = ? AND " Phone.DELETED + " = ?"; 
String[] args = {Phone.CONTENT_ITEM_TYPE, "0"}; 

return new CursorLoader(
    this, 
    Data.CONTENT_URI, 
    projection, 
    selection, 
    args, 
    null); 

किसी भी विचार क्यों Phone.DELETED स्तंभ कर्सर में शामिल नहीं है? documentation कहता है -

संबद्ध अधूरी संपर्क में आने से कुछ कॉलम में शामिल होने के एक निहित माध्यम से भी उपलब्ध हैं।

+0

क्या यह कई उपकरणों में है? –

+0

@MichaelAlanHuff - हाँ, मैंने दो उपकरणों पर कोशिश की है। एंड्रॉइड 5.0 और 5.1। – Gautam

उत्तर

5

ऐसा लगता है कि आपको ऐसी सुविधा मिली है जो कई स्थानों पर प्रलेखित की गई है, लेकिन अभी तक इसे लागू नहीं किया गया है। मैंने इस मुद्दे को ट्रैक करने के लिए एक बग खोला - देखते हैं कि एओएसपी लोगों को इस विषय पर क्या कहना है (bug report)।

Uri uri = ContactsContract.RawContactsEntity.CONTENT_URI; 

String[] projection = { 
    Phone._ID, 
    Phone.DELETED, 
    //Phone.LOOKUP_KEY, 
    Phone.NUMBER, 
    Phone.TYPE, 
    Phone.LABEL, 
    Data.MIMETYPE, 
    Data.DISPLAY_NAME_PRIMARY 
}; 

String selection = Data.MIMETYPE + " = ? AND " + Data.DELETED + " = ?"; 
String[] args = { 
    Phone.CONTENT_ITEM_TYPE, "0" 
}; 

return new CursorLoader(
this, 
uri, 
projection, 
selection, 
args, 
null); 

परिवर्तन::

इस बीच, आप निम्नलिखित तरीके का उपयोग कर सकते हैं

  1. उपयोग RawContactsEntity's यूआरआई
  2. LOOKUP_KEY यूआरआई ऊपर के माध्यम से सुलभ नहीं है - आप अतिरिक्त क्वेरी निष्पादित करने के लिए होगा यदि आप पूरी तरह इस स्तंभ की जरूरत है
  3. _ID आप वें उपयोग करने के लिए जा रहे हैं स्तंभ की आवश्यकता होगी ई CursorCursorAdapter में परिणामस्वरूप।

संपादित करें: निम्नलिखित @ MichaelAlanHuff के अनुरोध मैं कोड के कुछ हिस्सों जो इस जवाब

पर आधारित है com.android.providers.contacts.ContactsProvider2#queryLocal() से पोस्टिंग कर रहा हूँ (ContactsProvider2 के स्रोत कोड):

protected Cursor queryLocal(final Uri uri, final String[] projection, String selection, 
String[] selectionArgs, String sortOrder, final long directoryId, 
final CancellationSignal cancellationSignal) { 


    final SQLiteDatabase db = mDbHelper.get().getReadableDatabase(); 

    SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 
    String groupBy = null; 
    String having = null; 
    String limit = getLimit(uri); 
    boolean snippetDeferred = false; 

    // The expression used in bundleLetterCountExtras() to get count. 
    String addressBookIndexerCountExpression = null; 

    final int match = sUriMatcher.match(uri); 
    switch (match) { 


     ... 

     case DATA: 
     case PROFILE_DATA: 
      { 
       final String usageType = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE); 
       final int typeInt = getDataUsageFeedbackType(usageType, USAGE_TYPE_ALL); 
       setTablesAndProjectionMapForData(qb, uri, projection, false, typeInt); 
       if (uri.getBooleanQueryParameter(Data.VISIBLE_CONTACTS_ONLY, false)) { 
        qb.appendWhere(" AND " + Data.CONTACT_ID + " in " + Tables.DEFAULT_DIRECTORY); 
       } 
       break; 
      } 


      ... 

    } 



    qb.setStrict(true); 

    // Auto-rewrite SORT_KEY_{PRIMARY, ALTERNATIVE} sort orders. 
    String localizedSortOrder = getLocalizedSortOrder(sortOrder); 
    Cursor cursor = query(db, qb, projection, selection, selectionArgs, localizedSortOrder, groupBy, 
    having, limit, cancellationSignal); 

    if (readBooleanQueryParameter(uri, Contacts.EXTRA_ADDRESS_BOOK_INDEX, false)) { 
     bundleFastScrollingIndexExtras(cursor, uri, db, qb, selection, 
     selectionArgs, sortOrder, addressBookIndexerCountExpression, 
     cancellationSignal); 
    } 
    if (snippetDeferred) { 
     cursor = addDeferredSnippetingExtra(cursor); 
    } 

    return cursor; 


} 

आप के रूप में देख सकते हैं, दो अतिरिक्त विधियां हैं जहां SQLiteQueryBuilder क्वेरी बनाने के लिए उपयोग किया जा सकता है: setTablesAndProjectionMapForData() और अतिरिक्त query() विधि।

com.android.providers.contacts.ContactsProvider2#setTablesAndProjectionMapForData() के स्रोत:

private void setTablesAndProjectionMapForData(SQLiteQueryBuilder qb, Uri uri, 
     String[] projection, boolean distinct, boolean addSipLookupColumns, Integer usageType) { 
    StringBuilder sb = new StringBuilder(); 
    sb.append(Views.DATA); 
    sb.append(" data"); 

    appendContactPresenceJoin(sb, projection, RawContacts.CONTACT_ID); 
    appendContactStatusUpdateJoin(sb, projection, ContactsColumns.LAST_STATUS_UPDATE_ID); 
    appendDataPresenceJoin(sb, projection, DataColumns.CONCRETE_ID); 
    appendDataStatusUpdateJoin(sb, projection, DataColumns.CONCRETE_ID); 

    appendDataUsageStatJoin(
      sb, usageType == null ? USAGE_TYPE_ALL : usageType, DataColumns.CONCRETE_ID); 

    qb.setTables(sb.toString()); 

    boolean useDistinct = distinct || !ContactsDatabaseHelper.isInProjection(
      projection, DISTINCT_DATA_PROHIBITING_COLUMNS); 
    qb.setDistinct(useDistinct); 

    final ProjectionMap projectionMap; 
    if (addSipLookupColumns) { 
     projectionMap = 
       useDistinct ? sDistinctDataSipLookupProjectionMap : sDataSipLookupProjectionMap; 
    } else { 
     projectionMap = useDistinct ? sDistinctDataProjectionMap : sDataProjectionMap; 
    } 

    qb.setProjectionMap(projectionMap); 
    appendAccountIdFromParameter(qb, uri); 
} 

यहाँ आप अंतिम क्वेरी StringBuilder का उपयोग कर जो कई append*() तरीकों को पारित किया जा रहा है table तर्क के निर्माण को देखते हैं। मैं अपना स्रोत कोड पोस्ट नहीं कर रहा हूं, लेकिन वे वास्तव में join विधियों के नामों में दिखाई देने वाली तालिकाएं हैं। यदि rawContacts तालिका में शामिल हो जाएगा, तो मुझे appendRawContactJoin() जैसे कुछ को कॉल करने की उम्मीद है ...

पूर्णता के लिए: अन्य query() विधि है कि मैं उल्लेख table तर्क संशोधित नहीं करता है:

private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, 
     String selection, String[] selectionArgs, String sortOrder, String groupBy, 
     String having, String limit, CancellationSignal cancellationSignal) { 
    if (projection != null && projection.length == 1 
      && BaseColumns._COUNT.equals(projection[0])) { 
     qb.setProjectionMap(sCountProjectionMap); 
    } 
    final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, having, 
      sortOrder, limit, cancellationSignal); 
    if (c != null) { 
     c.setNotificationUri(getContext().getContentResolver(), ContactsContract.AUTHORITY_URI); 
    } 
    return c; 
} 

तरीकों में से ऊपर श्रृंखला के निरीक्षण मुझे निष्कर्ष एक आधिकारिक दस्तावेज सुविधा है जो नहीं है है कि वहाँ के लिए नेतृत्व किया कार्यान्वित किया।

+0

उत्तर के लिए धन्यवाद। कुछ दस्तावेज होने और कार्यान्वित नहीं होने की उम्मीद नहीं थी। यह आमतौर पर चारों ओर एक और तरीका है। :) – Gautam

+0

बीटीडब्ल्यू, क्या आपको पता है कि यहां क्या गलत हो सकता है: http://stackoverflow.com/q/30783516/886468 – Gautam

+2

@ गौतम, मैं मानता हूं कि यह बहुत असामान्य है। मैंने स्रोत कोड पर कई पीछे और आगे किए क्योंकि मुझे विश्वास नहीं था कि यह मामला है। हालांकि मैंने खोले गए बग पर नजर रखी - शायद मुझे अभी भी कुछ गलत तरीका मिल गया है। – Vasiliy

संबंधित मुद्दे