2016-12-20 2 views
1

Die Situation: Ich habe eine benutzerdefinierte Aktion zu einem Kontakt in Android nach den Anweisungen in this question und related sample app on GitHub hinzugefügt. Wenn ich gedrückt werde, möchte ich diesen Kontakt in meiner Anwendung wählen. Ich kann den Kontakt in der Aktivität, die beim Drücken der benutzerdefinierten Aktion geöffnet wird, erfolgreich abrufen.Wie kann ich die Telefonnummern eines Kontakts abrufen, indem Sie in der nativen Kontaktanwendung in Android auf ein benutzerdefiniertes Feld klicken?

ich dies ausführen:

Cursor cursor = context.getContentResolver().query(data, null, null, null, null); 
if (cursor != null) { 
    newIntent = true; 
    contact = LocalContactAsync.getContacts(cursor, context.getContentResolver()).get(0); 
    cursor.close(); 
} 

Und die data ich von Android abrufen ist:

Inhalt: //com.android.contacts/data/2849

Hinweis die Nummer 2849 am Ende, das ist nicht die native ID des Kontakts. Die native ID des Kontakts lautet 459. Ich bin in der Lage, erfolgreich die Kontakt Ausführen dieser Abfrage abrufen, werden die folgenden Daten liefert:

cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID); 

-Gibt ‚2849‘

cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)) ; 

-Gibt ‚Probe Proben- aufstellfläche‘ Wich korrekt ist

Aber obwohl dies gilt:

cursor.getInt(cur.getColumnIndex(
      ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) 

Die folgende Funktion gibt einen leeren Cursor zurück:

Cursor pCur = cr.query(
       ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
       null, 
       ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", 
       new String[]{id}, null); 

-id = 2849 in diesem Fall, aber wenn ich in 459 fülle ich rufe Sie die richtige Menge an Telefonnummern

Der eigentliche Kontakt hat drei Zahlen, so dass es 3 Zahlen zurückkehren.

Wie kann ich das beheben?

Edited:

Dies ist, wie ich Zahlen abrufen, klar sein: ich die richtigen Namen, aber die folgende Abfrage gibt null während die Kontaktnummern haben.

ArrayList<Number> numbers = new ArrayList<>(); 
    if (cur.getInt(cur.getColumnIndex(
      ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) { 
     Cursor pCur = cr.query(
       ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
       null, 
       ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", 
       new String[]{id}, null); 
     while (pCur.moveToNext()) { 
      numbers.add(new nl.coffeeit.clearvoxnexxt.objects.dto.Number(pCur.getString(pCur.getColumnIndex(
        ContactsContract.CommonDataKinds.Phone.NUMBER)))); 
     } 
     pCur.close(); 
    } 
    return numbers; 

Bitte beachten Sie, dass ich eine Absicht nicht verlangen, ich sie durch eine benutzerdefinierte Aktion erhalten, die zu einem nativen Kontakt hinzugefügt wird, wie Viber und WhatsApp tun:

custom action android contact

Voll Code LocalContacts Async:

private static final String TAG = "LocalContactAsync"; 
private static List<Contact> contacts; 

private Context context; 
private boolean refreshOtherFragments; 
private boolean renew;  

private synchronized List<Contact> getContacts(Context context) { 
    if (!renew && contacts != null) { 
     return contacts; 
    } 
    ContentResolver cr = context.getContentResolver(); 
    Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, 
      null, null, null, null); 

    if (cur != null && cur.getCount() > 0) { 
     contacts = getContacts(cur, cr); 
     cur.close(); 
     return contacts; 
    } 
    if (cur != null) { 
     cur.close(); 
    } 
    return new ArrayList<>(); 
} 

public static List<Contact> getContacts(Cursor cur, ContentResolver cr) { 
    List<Contact> contacts = new ArrayList<>(); 
    while (cur.moveToNext()) { 
     String id = getId(cur); 
     String name = getName(cur); 
     ArrayList<Number> numbers = getNumbers(cur, cr, id); 
     if (name != null) { 
      contacts.add(new Contact(id, name, numbers)); 
     } 
    } 
    Log.d(TAG, "amount of contacts" + contacts.size()); 
    return contacts; 
} 

private static ArrayList<Number> getNumbers(Cursor cur, ContentResolver cr, String id) { 
    ArrayList<Number> numbers = new ArrayList<>(); 
    if (cur.getInt(cur.getColumnIndex(
      ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) { 
     Cursor pCur = cr.query(
       ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
       null, 
       ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", 
       new String[]{id}, null); 
     while (pCur.moveToNext()) { 
      numbers.add(getNumber(pCur)); 
     } 
     pCur.close(); 
    } 
    return numbers; 
} 

private static Number getNumber(Cursor pCur) { 
    return new nl.coffeeit.clearvoxnexxt.objects.dto.Number(pCur.getString(pCur.getColumnIndex(
      ContactsContract.CommonDataKinds.Phone.NUMBER))); 
} 

private static String getId(Cursor cur) { 
    return cur.getString(
      cur.getColumnIndex(ContactsContract.Contacts._ID)); 
} 

private static String getName(Cursor cur) { 
    return cur.getString(cur.getColumnIndex(
      ContactsContract.Contacts.DISPLAY_NAME)); 
} 

-Code für Nummer DTO:

public class Number implements Parcelable, Serializable { 

    @SerializedName("number") 
    @Expose 
    public String number; 
    @SerializedName("type") 
    @Expose 
    public String type = ""; 
    @SerializedName("inherited") 
    @Expose 
    public Boolean inherited = false; 

    public Number(String number) { 
     this.number = number; 
    } 

    protected Number(Parcel in) { 
     number = in.readString(); 
     type = in.readString(); 
     byte inheritedVal = in.readByte(); 
     inherited = inheritedVal == 0x02 ? null : inheritedVal != 0x00; 
    } 

    @Override 
    public int describeContents() { 
     return 0; 
    } 

    @Override 
    public void writeToParcel(Parcel dest, int flags) { 
     dest.writeString(number); 
     dest.writeString(type); 
     if (inherited == null) { 
      dest.writeByte((byte) (0x02)); 
     } else { 
      dest.writeByte((byte) (inherited ? 0x01 : 0x00)); 
     } 
    } 

    @SuppressWarnings("unused") 
    public static final Parcelable.Creator<Number> CREATOR = new Parcelable.Creator<Number>() { 
     @Override 
     public Number createFromParcel(Parcel in) { 
      return new Number(in); 
     } 

     @Override 
     public Number[] newArray(int size) { 
      return new Number[size]; 
     } 
    }; 

    public Number setNumber(String number) { 
     this.number = number; 
     return this; 
    } 
} 

Antwort

1

Das erste, was zu bemerken ist, dass ein Anruf an die Kontakte wie diese Kommissionierer:

Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); 

eine Uri wie folgt zurück:

content://com.android.contacts/contacts/lookup/3163r328-4D2941473F314D2941473F3131/328 

vorletzten Weg (3163r .. ..) ist der Suchschlüssel, während 328 der NAME_RAW_ID ist.

Vergleichen Sie dies mit der Absicht, die Sie von der sample application bekommen. Dieser enthält eine Uri, die wie folgt aussieht:

content://com.android.contacts/data/2849 

Wie Sie gesagt haben, mit diesem Uri den Inhalt Resolver Aufruf nicht ausreichend ist, Telefonnummern abzurufen, obwohl sie verwendet werden kann, den Namen des Kontakts abzurufen und die Ich würde. Wir werden also den unvollständigen Intent Uri verwenden, um einen neuen Lookup Uri zu erstellen, mit dem wir die Telefonnummern abrufen können.

Lassen Sie uns die folgenden Methoden, um Ihre LocalContactAsync hinzufügen (Ich werde nichts Refactoring Sie bisher getan haben, ich werde einfach im Stil hinzufügen, haben Sie verwendet):

public static Uri getLookupUri(Cursor cur) { 
    return getContentUri(getLookupKey(cur), getNameRawId(cur)); 
} 

private static String getLookupKey(Cursor cur) { 
    return cur.getString(
      cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); 
} 

private static String getNameRawId(Cursor cur) { 
    return cur.getString(cur.getColumnIndex(ContactsContract.Contacts.NAME_RAW_CONTACT_ID)); 
} 

private static Uri getContentUri(String lookupKey, String nameRawId) { 
    return new Uri.Builder() 
      .scheme("content") 
      .authority("com.android.contacts") 
      .appendPath("contacts") 
      .appendPath("lookup") 
      .appendPath(lookupKey) 
      .appendPath(nameRawId) 
      .build(); 
} 

Lassen Sie uns die ViewingActivity innen verändern die Beispielanwendung, damit die Kontaktdaten tatsächlich abgerufen werden. Wir können jetzt tun, dass mit dem folgenden Code innerhalb onResume():

@Override 
protected void onResume() { 
    super.onResume(); 
    Uri uri = getIntent().getData(); 
    Cursor intentCursor = this.getContentResolver().query(uri, null, null, null, null); 
    Contact contact = null; 
    if (intentCursor != null) { 
     intentCursor.moveToFirst(); 
     Uri lookupUri = LocalContactAsync.getLookupUri(intentCursor); 
     Cursor lookupCursor = this.getContentResolver().query(lookupUri, null, null, null, null); 
     contact = LocalContactAsync.getContacts(lookupCursor, this.getContentResolver()).get(0); 
     intentCursor.close(); 
     lookupCursor.close(); 
    } 
} 

Der Kontakt wird nun die Telefonnummern enthalten, wie erforderlich.

+0

Danke für die Info, aber ich starte keine Aktivität für ein Ergebnis. Ich füge dem nativen Kontakt ein benutzerdefiniertes Ereignis hinzu, das meine App direkt über die Kontaktanwendung von Android öffnet. Wie verwalte ich diese Extras? – jobbert

+0

Ich habe zusätzliche Informationen zu der Frage hinzugefügt. Der von Ihnen angegebene Code funktionierte genauso wie meiner. Ich bekomme den Namen und die ID, aber keine Telefonnummern. Während der Kontakt 3 Telefonnummern hat. Auch wenn ich nur alle Kontakte abrufe, kann ich die Telefonnummern bekommen. – jobbert

+0

Dann kehrt die Nummer 2849 zurück. Es ist eine schlechte Namensgebung. Es ist überhaupt nicht asynchron. Ich kann den vollständigen Code posten, wenn Sie möchten. – jobbert

Verwandte Themen