14

मैं एक एंड्रॉइड ऐप लिख रहा हूं जिसमें एक डेटा प्रकार है जो किसी व्यक्ति (विशेष रूप से, बच्चे के माता-पिता या अभिभावक) का प्रतिनिधित्व करता है। मैं एंड्रॉइड डिवाइस में संपर्क डेटाबेस से संबंधित डेटा फ़ील्ड को "आयात" करने में सक्षम होना चाहता हूं। (यह वैकल्पिक होना चाहिए; यानी, यह एक आवश्यकता नहीं होगी कि अभिभावक/अभिभावक पहले से ही संपर्क डेटाबेस में है, न ही संपर्क डेटाबेस अपडेट किए जाएंगे यदि वे नए माता-पिता/अभिभावकों को जोड़ते हैं।)इराद से लौटाई गई यूआरआई से विशिष्ट संपर्क जानकारी प्राप्त करें। एक्शन_PICK

अभी तक, मैंने विशिष्ट संपर्क (Intent.ACTION_PICK का उपयोग करके) चुनने के लिए एक नया इरादा शुरू करने के लिए कोड लिखा है। मैं फिर एक यूआरआई प्राप्त करता हूं जो डेटाबेस में एक विशिष्ट संपर्क का प्रतिनिधित्व करता है।

दुर्भाग्यवश, मुझे नहीं पता कि अगला कदम क्या है। ऐसा लगता है कि यह दुनिया में सबसे सरल चीज होना चाहिए, लेकिन स्पष्ट रूप से नहीं। मैंने एंड्रॉइड डेवलपर वेबसाइट पर प्रलेखन के माध्यम से पढ़ा है, और मैंने एक से अधिक एंड्रॉइड पुस्तक देखी है। कोई आनंद नहीं है।

विशेष जानकारी मैं प्राप्त करना चाहते हैं, यह है:

  1. संपर्क का नाम (पहली और अलग से यदि संभव हो तो पिछले)

  2. संपर्क का (प्राथमिक) ईमेल पता

  3. संपर्क का सेल फोन नंबर

I कल्पना करें कि ContentResolver का उपयोग करके पूछताछ करके यह संभव होना चाहिए, लेकिन मुझे नहीं पता कि इरादे से वापस आने वाले यूआरआई के साथ ऐसा कैसे किया जाए। अधिकांश दस्तावेज मानते हैं कि आपके पास संपर्क आईडी है, न कि संपर्क की यूआरआई। साथ ही, मुझे नहीं पता कि मैं किस प्रकार के फ़ील्ड को क्वेरी के प्रक्षेपण में डाल सकता हूं, यह मानते हुए कि यह वही करने का सही तरीका है जो मैं चाहता हूं।

यहाँ मेरा प्रारंभ कोड है:

// In a button's onClick event handler: 
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); 
startActivityForResult(intent, PICK_CONTACT); 

// In onActivityResult: 
if (resultCode == RESULT_OK) { 
    if (requestCode == PICK_CONTACT) { 
     contactURI = data.getData(); 
     // NOW WHAT? 
    } 
} 

उत्तर

14

जैसा कि यह पता चला है, ऐसा करने का एक बेहतर तरीका है।

जैसा कि मैंने उल्लेख किया है, contactContract.Contacts.Entity क्लास एपीआई 11 तक उपलब्ध नहीं था। हालांकि, ContactsContract.Data कक्षा एपीआई 5 में वापस उपलब्ध थी, और आप उस वर्ग का उपयोग बड़े पैमाने पर उसी तरह कर सकते हैं जैसे आप इसका उपयोग करते हैं इकाई वर्ग

मैंने अपना कोड अपडेट किया है। यह इकाई वर्ग के लिए कोड के समान है, और काफी हद तक काम करता है। हालांकि, मैंने इसे अपने फोन के साथ जिंजरब्रेड चलाने के साथ परीक्षण किया है, और यह ठीक काम करता है।

एक परिवर्तन मैं करना था यह है: वहाँ एक तरह से प्रारंभिक क्वेरी से ContactsContract.Data.RAW_CONTACT_ID पाने के लिए होना प्रतीत नहीं होता है, और कहा कि आईडी नहीं आईडी आप जैसे से प्राप्त करने के समान है ContactsContract.Contacts._ID। इसके बजाय, मैंने ContactsContract.Contacts.DISPLAY_NAME निरंतर पर पूछताछ की, जो कि प्रत्येक संपर्क नियंत्रण कक्षा में काफी सुसंगत है।

यहाँ काम कर कोड है:

 Cursor cursor; // Cursor object 
     String mime; // MIME type 
     int dataIdx; // Index of DATA1 column 
     int mimeIdx; // Index of MIMETYPE column 
     int nameIdx; // Index of DISPLAY_NAME column 

     // Get the name 
     cursor = getContentResolver().query(params[0], 
       new String[] { ContactsContract.Contacts.DISPLAY_NAME }, 
       null, null, null); 
     if (cursor.moveToFirst()) { 
      nameIdx = cursor.getColumnIndex(
        ContactsContract.Contacts.DISPLAY_NAME); 
      name = cursor.getString(nameIdx); 

      // Set up the projection 
      String[] projection = { 
        ContactsContract.Data.DISPLAY_NAME, 
        ContactsContract.Contacts.Data.DATA1, 
        ContactsContract.Contacts.Data.MIMETYPE }; 

      // Query ContactsContract.Data 
      cursor = getContentResolver().query(
        ContactsContract.Data.CONTENT_URI, projection, 
        ContactsContract.Data.DISPLAY_NAME + " = ?", 
        new String[] { name }, 
        null); 

      if (cursor.moveToFirst()) { 
       // Get the indexes of the MIME type and data 
       mimeIdx = cursor.getColumnIndex(
         ContactsContract.Contacts.Data.MIMETYPE); 
       dataIdx = cursor.getColumnIndex(
         ContactsContract.Contacts.Data.DATA1); 

       // Match the data to the MIME type, store in variables 
       do { 
        mime = cursor.getString(mimeIdx); 
        if (ContactsContract.CommonDataKinds.Email 
          .CONTENT_ITEM_TYPE.equalsIgnoreCase(mime)) { 
         email = cursor.getString(dataIdx); 
        } 
        if (ContactsContract.CommonDataKinds.Phone 
          .CONTENT_ITEM_TYPE.equalsIgnoreCase(mime)) { 
         phone = cursor.getString(dataIdx); 
         phone = PhoneNumberUtils.formatNumber(phone); 
        } 
       } while (cursor.moveToNext()); 
      } 
     } 
+0

मुझे पैराम्स पर चेतावनी मिलती है [0] यह क्या है? –

+0

आपके उत्तरों के लिए बहुत धन्यवाद! – Chisko

+0

@ GerardGrundy कार्ल इस समाधान को एक AsyncTask के भीतर कार्यान्वित कर रहा है, जिसे सामग्री रिज़ॉल्वर से पूछताछ के संभावित लंबे समय तक चलने वाले संचालन के कारण अनुशंसा की जाती है।पैराम्स [] सरणी (जिसे आप चाहते हैं उसका नाम दिया जा सकता है, लेकिन "पैराम्स" और "तर्क" आम नाम हैं) यह है कि डेटा को AsyncTask में कैसे पारित किया जाता है। अधिक जानकारी के लिए [AsyncTask] (https://developer.android.com/reference/android/os/AsyncTask.html) दस्तावेज़ देखें। – Slerig

16

ठीक है, खुदाई के बहुत सारे के बाद, मैंने पाया कि मैं क्या जवाब होना करने के लिए विश्वास करते हैं। आपके द्वारा उपयोग किए जाने वाले समाधानों के अनुसार आप किस एंड्रॉइड एपीआई स्तर का उपयोग कर रहे हैं। हालांकि, वे बिल्कुल सुंदर नहीं हैं, इसलिए यदि बेहतर समाधान हैं, तो मुझे जानना अच्छा लगेगा।

किसी भी मामले में, पहला कदम Intent.ACTION_PICK से लौटाई गई यूआरआई पर एक प्रश्न करके संपर्क की आईडी प्राप्त करना है। जब हम यहां हैं, हमें डिस्प्ले नाम भी प्राप्त करना चाहिए, और स्ट्रिंग का प्रतिनिधित्व करना चाहिए कि संपर्क में फ़ोन नंबर है या नहीं। (हम उन्हें आधुनिक समाधान के लिए की आवश्यकता होगी नहीं, लेकिन हम उन्हें विरासत समाधान के लिए की आवश्यकता होगी।)

String id, name, phone, hasPhone; 
int idx; 
Cursor cursor = getContentResolver().query(contactUri, null, null, null, null); 
if (cursor.moveToFirst()) { 
    idx = cursor.getColumnIndex(ContactsContract.Contacts._ID); 
    id = cursor.getString(idx); 

    idx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); 
    name = cursor.getString(idx); 

    idx = cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER); 
    hasPhone = cursor.getString(idx); 
} 

रिकॉर्ड के लिए, कॉलम इस URI से लौटे के सबसे क्षेत्रों स्थिरांक का प्रतिनिधित्व कर रहे ContactsContract.Profile कक्षा में (अन्य इंटरफेस से प्राप्त स्थिरांक सहित)। PHOTO_FILE_ID, PHOTO_THUMBNAIL_URI, या PHOTO_URI शामिल नहीं हैं (लेकिन PHOTO_ID शामिल है)।

अब हमारे पास आईडी है, हमें प्रासंगिक डेटा प्राप्त करने की आवश्यकता है। पहला (और सबसे सरल) समाधान एक इकाई से पूछताछ करना है। इकाई प्रश्न एक संपर्क या कच्चे संपर्क के लिए सभी संपर्क डेटा को एक बार में पुनर्प्राप्त करते हैं। प्रत्येक पंक्ति एक एकल कच्चे संपर्क का प्रतिनिधित्व करती है, जो ContactsContract.Contacts.Entity में स्थिरांक का उपयोग करके उपयोग की जाती है। आमतौर पर आप केवल RAW_CONTACT_ID, DATA1 और MIMETYPE से चिंतित होंगे। हालांकि, अगर आप पहले और आखिरी नाम अलग से चाहते हैं, तो नाम MIME प्रकार का पहला नाम DATA2 और DATA3 में अंतिम नाम होता है।

आप ContactsContract.CommonDataKinds स्थिरांक के साथ MIMETYPE कॉलम से मेल करके चर को लोड करते हैं; उदाहरण के लिए, ईमेल MIME प्रकार ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE में है।

// Build the Entity URI. 
Uri.Builder b = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, id).buildUpon(); 
b.appendPath(ContactsContract.Contacts.Entity.CONTENT_DIRECTORY); 
URI contactUri = b.build(); 

// Create the projection (SQL fields) and sort order. 
String[] projection = { 
     ContactsContract.Contacts.Entity.RAW_CONTACT_ID, 
     ContactsContract.Contacts.Entity.DATA1, 
     ContactsContract.Contacts.Entity.MIMETYPE }; 
String sortOrder = ContactsContract.Contacts.Entity.RAW_CONTACT_ID + " ASC"; 
cursor = getContentResolver().query(contactUri, projection, null, null, sortOrder); 

String mime; 
int mimeIdx = cursor.getColumnIndex(ContactsContract.Contacts.Entity.MIMETYPE); 
int dataIdx = cursor.getColumnIndex(ContactsContract.Contacts.Entity.DATA1); 
if (cursor.moveToFirst()) { 
    do { 
     mime = cursor.getString(mimeIdx); 
     if (mime.equalsIgnoreCase(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) { 
      email = cursor.getString(dataIdx); 
     } 
     if (mime.equalsIgnoreCase(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) { 
      phone = cursor.getString(dataIdx); 
     } 
     // ...etc. 
    } while (cursor.moveToNext()); 
} 

दुर्भाग्य से, संस्थाओं unti एपीआई 11 (Android 3.0, Honeycomb), जिसका अर्थ है इस कोड को बाजार में Android उपकरणों (इस लेखन के रूप में) का लगभग 65% के साथ असंगत है पेश नहीं किया गया। यदि आप इसे आजमाते हैं, तो आपको यूआरआई से IllegalArgumentException मिल जाएगा।

// Get phone number - if they have one 
if ("1".equalsIgnoreCase(hasPhone)) { 
    cursor = getContentResolver().query(
      ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
      null, 
      ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = "+ id, 
      null, null); 
    if (cursor.moveToFirst()) { 
     colIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER); 
     phone = cursor.getString(colIdx); 
    } 
    cursor.close(); 
} 

// Get email address 
cursor = getContentResolver().query(
     ContactsContract.CommonDataKinds.Email.CONTENT_URI, 
     null, 
     ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + id, 
     null, null); 
if (cursor.moveToFirst()) { 
    colIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS); 
    email = cursor.getString(colIdx); 
} 
cursor.close(); 

// ...etc. 

जाहिर है, इस तरह से अलग डाटाबेस प्रश्नों का एक बहुत में परिणाम होगा, तो यह है:

दूसरा समाधान एक क्वेरी स्ट्रिंग का निर्माण, और प्रत्येक डेटा के लिए टाइप करें आप उपयोग करना चाहते एक क्वेरी बनाने के लिए है दक्षता कारणों के लिए अनुशंसित नहीं है।

try { 
    // Build the Entity URI. 
    Uri.Builder b = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, id).buildUpon(); 
    b.appendPath(ContactsContract.Contacts.Entity.CONTENT_DIRECTORY); 
     // ...etc... 
} catch (IllegalArgumentException e) { 
    // Get phone number - if they have one 
    if ("1".equalsIgnoreCase(hasPhone)) { 
     // ...etc... 
} finally { 
    // If you want to display the info in GUI objects, put the code here 
} 

मुझे आशा है कि यह किसी को मदद मिलती है:

समाधान मैं ले कर आए हैं, संस्करण इकाई प्रश्नों का उपयोग करता है की कोशिश करने के IllegalArgumentException पकड़ने, और कैच ब्लॉक के अंदर विरासत कोड डाल है। और, फिर, अगर ऐसा करने के बेहतर तरीके हैं, तो मैं सभी कान हूं।

+0

इस उत्तर के आधार पर धन्यवाद, मैं 'इकाई' तालिका की शक्ति को अनदेखा करता हूं – DoruChidean

1
//Add a permission to read contacts data to your application manifest. 
<uses-permission android:name="android.permission.READ_CONTACTS"/> 

//Use Intent.ACTION_PICK in your Activity 
Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, 
       ContactsContract.CommonDataKinds.Phone.CONTENT_URI); 
     startActivityForResult(contactPickerIntent, RESULT_PICK_CONTACT); 

//Then Override the onActivityResult() and retrieve the ID,Phone number and Name in the data. 
@Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     // check whether the result is ok 
     if (resultCode == RESULT_OK) { 
      // Check for the request code, we might be usign multiple startActivityForReslut 
      switch (requestCode) { 
      case RESULT_PICK_CONTACT: 
       Cursor cursor = null; 
     try { 
      String phoneNo = null ; 
      String name = null;   
      Uri uri = data.getData();    
      cursor = getContentResolver().query(uri, null, null, null, null); 
      cursor.moveToFirst();   
      int phoneIndex =cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER); 
      phoneNo = cursor.getString(phoneIndex); 
      textView2.setText(phoneNo); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
       break; 
      } 
     } else { 
      Log.e("MainActivity", "Failed to pick contact"); 
     } 
    } 

नोट: Android 2.3 (एपीआई स्तर 9) से पहले, (नीचे दिखाए गए जैसा) संपर्क प्रदाता पर एक प्रश्न के प्रदर्शन अपने अनुप्रयोग घोषणा करते हैं कि आवश्यकता है READ_CONTACTS अनुमति (सुरक्षा और अनुमतियां देखें)। हालांकि, एंड्रॉइड 2.3 के साथ शुरुआत, संपर्क/लोग ऐप आपके ऐप को संपर्क प्रदाता से पढ़ने के लिए अस्थायी अनुमति देता है जब यह आपको परिणाम देता है। अस्थायी अनुमति केवल अनुरोध किए गए विशिष्ट संपर्क पर लागू होती है, इसलिए जब तक आप READ_CONTACTS अनुमति घोषित नहीं करते हैं, तब तक आप इरादे के उरी द्वारा निर्दिष्ट किसी अन्य के अलावा किसी अन्य संपर्क से पूछताछ नहीं कर सकते।

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