2017-01-05 14 views
6

Bounty Nagroda - The Bounty otrzyma odpowiedź, że dostaje od zaludnionym wartości Telephony.Sms.Inbox.PERSON, do powiązanej Contact używając tylko ContractsContact tabele.Telephony.Sms.Inbox.PERSON wykorzystuje przestarzałe Contacts.People._ID


Czytam wiadomości SMS w standardowy sposób w mojej aplikacji:

final String[] projection = {Telephony.Sms.Inbox.BODY, 
      Telephony.Sms.Inbox.ADDRESS, 
      Telephony.Sms.Inbox.READ, 
      Telephony.Sms.Inbox.DATE, 
      Telephony.Sms.Inbox.PERSON}; 

    final Cursor cursor = ctx.getContentResolver().query(Telephony.Sms.Inbox.CONTENT_URI, 
      projection, null, null, Telephony.Sms.Inbox.DEFAULT_SORT_ORDER); 

Kiedy zaludnionych, id wrócił z indeksu Telephony.Sms.Inbox.PERSON dotyczy id nieaktualnych Contacts.People._ID i mogą być wykorzystane kwerendy dalszych informacji należy skontaktować się w następujący sposób:

final String[] projection = {Contacts.People.DISPLAY_NAME}; 
    final String[] selectionArgs = {contactId}; 

    final Cursor cursor = ctx.getContentResolver().query(Contacts.People.CONTENT_URI, 
      projection, Contacts.People._ID + " = ?", selectionArgs, null); 

Dlaczego miałby ponownie W związku z tym nowe Telephony API użyć deprecated tables, zamiast ContactsContract?

Telephony.Sms.Inbox.PERSON dokumentacja stanowi:

Typ: INTEGER (odniesienie do elementu w treści: // Kontakty/osoby)

Próbowałem bezskutecznie (? Ale nie jest zaskoczeniem), aby znaleźć mapowanie do identyfikatora w dowolnym z pól identyfikatora ContactsContract, dlatego muszę używać przestarzałych interfejsów API w celu rozwiązania zapytań, które muszę szybko wykonać.

Takie zapytania obejmują wyszukiwanie wiadomości przez konkretnego kontaktu, dla którego mam tylko nazwę. Styk może mieć kilka numerów, które nie mogą być w odpowiednim formacie do potencjalnie pasuje Telephony.Sms.Inbox.ADDRESS wpisy .....

workaround korzystania Telephony.Sms.Inbox.ADDRESS i ContactsContract.PhoneLookup nie jest koniec świata, gdy dzieje się od numeru do kontakt, ale wciąż czuję się . Muszę czegoś tu brakować?

Oto proces, którego używam, aby uzyskać wiadomości do "Joe Bloggs".

1) kwerendy tabeli ContactsContract aby potwierdzić kontakt o imieniu Jan Kowalski istnieje na urządzeniu - lub uzyskać ścisłe dopasowanie jeśli kontakt jest faktycznie wymienione jako „Joe Blogi”.

2) Korzystanie z potwierdzoną imię, kwerendy przestarzałe Contact.People stół, aby uzyskać wszystkie związane z nimi identyfikatory do kontaktu w następujący sposób:

final String selection = Contacts.People.DISPLAY_NAME + " LIKE ?"; 

    final String[] projection = {Contacts.People.DISPLAY_NAME, 
      Contacts.People._ID}; 

    final String[] selectionArgs = {contactName}; 

    final Cursor cursor = ctx.getContentResolver().query(Contacts.People.CONTENT_URI, 
      projection, selection, selectionArgs, null); 

3) przy użyciu listę nieaktualnych identyfikatorów stykowych, I kwerendy komunikat stół jak tak:

final String[] referredArgs = new String[contactIdArray.size()]; 
    for (int i = 0; i < contactIdArray.size(); i++) { 
     referredArgs[i] = contactIdArray.get(i); 
    } 

    final String referredSelection = Telephony.Sms.Inbox.PERSON + " IN " 
      + "(" + TextUtils.join(",", referredArgs) + ")"; 

    final String[] projection = {Telephony.Sms.Inbox.BODY, 
      Telephony.Sms.Inbox.ADDRESS, 
      Telephony.Sms.Inbox.READ, 
      Telephony.Sms.Inbox.DATE, 
      Telephony.Sms.Inbox.PERSON}; 

    final Cursor cursor = ctx.getContentResolver().query(Telephony.Sms.Inbox.CONTENT_URI, 
      projection, referredSelection, null, Telephony.Sms.Inbox.DEFAULT_SORT_ORDER); 

mam nadzieję, że ktoś powie mi, idę wokół domów tu i tam jest bardziej oczywiste rozwiązanie wykorzystujące aktualne API. Nie uważam iteracji całej tablicy wiadomości za pomocą zoptymalizowanego rozwiązania za pomocąContactsContract.PhoneLookup.

Z góry dziękuję.

Odpowiedz

-1

Nie rozumiem twoją troskę prawidłowo, ale pracuję nad podobnym projektem, oto kod podstawowy, a podstawowe, ważne kolumny do pobierania i wyświetli komunikat:

ContentResolver contentResolver = getContentResolver(); 
final String[] projection = new String[]{"*"}; 

Cursor SMSL = contentResolver.query(Telephony.Sms.CONTENT_URI, projection, null, null, "date ASC"); 
int msgscount = SMSL.getCount(); 

if (msgscount>0) { 
msgs = new String[SMSL.getCount()][msgs_column_count]; 
    int i = 0; 
    while (SMSL.moveToNext()) { 
     progress.setProgress(i); 

     msgs[i][0] = SMSL.getString(SMSL.getColumnIndex("address")); 
     msgs[i][1] = SMSL.getString(SMSL.getColumnIndex("date_sent")); 
     msgs[i][2] = SMSL.getString(SMSL.getColumnIndex("date")); 
     msgs[i][3] = SMSL.getString(SMSL.getColumnIndex("type")); 
     msgs[i][4] = SMSL.getString(SMSL.getColumnIndex("body")); 
     msgs[i][5] = SMSL.getString(SMSL.getColumnIndex("read")); 
     if (SMSL.getString(SMSL.getColumnIndex("service_center")) != null){ 
      msgs[i][6] = SMSL.getString(SMSL.getColumnIndex("service_center")); 
     }else{ 
      msgs[i][6] = ""; 
     } 
        i++; 
    } 
    SMSL.close(); 
}else{ 
    msgs = new String[0][0]; 
    Toast.makeText(getApplicationContext(),"No messages found!",Toast.LENGTH_LONG).show(); 
} 

Jeśli chcesz żadnej pomocy z te lub przynoszące wiadomości, daj mi znać.

+0

Pytanie brzmi, dlaczego zwrócona wartość 'PERSON' odnosi się do wycofanego identyfikatora' Contacts.People', zamiast używać wartości z tabel 'ContactsContract'. Zapytanie o tabelę wiadomości nie jest problemem. – brandall

4

Nie użyłbym pola Telephony.Sms.Inbox.PERSON, a na pewno nie wysłałbym zapytań do przestarzałego apisa People, gdybym był tobą. Apis People był przestarzały, ponieważ nie można liczyć na wszystkie urządzenia, które są tam, aby właściwie go obsługiwać.

Pierwszą rzeczą, którą należy zrozumieć, jest to, że nie ma bezpośredniego związku między wiadomościami SMS i kontaktami. Wiadomość SMS może pochodzić z bezkontaktowego numeru telefonu, pojedynczego kontaktu, wielu kontaktów, mieszanki kontaktów i kontaktów, identyfikatorów alfanumerycznych, a nawet innych, rzadszych opcji.

Następną rzeczą, należy uważnie czytać kod akcji i jak to obsługuje poprawnie nazwie „ID Odbiorca”, które można uzyskać z kolekcji SMS, jest to kolekcja o nazwie canonical-addresses (lub canonical-address), który służy jako mapowanie pomiędzy pozycją numer telefonu (lub listę rozdzielonych przecinkami telefonów) i identyfikator odbiorcy. Kod wykonuje pojedynczą kwerendę podczas uruchamiania, aby buforować całą tabelę w pamięci, a następnie używa jej do mapowania między telefonami i identyfikatorami-odbiorcami.

Oto mapping class

+0

Dziękuję za odpowiedź - doceniam to, że 'nie ma bezpośredniego związku pomiędzy sms a kontaktami ', ale jedno jest" tworzone "gdzieś po otrzymaniu sms/mm, co skutkuje" identyfikatorem/identyfikatorem " "zaludnione. Z linku próbowałem znaleźć w kodzie źródłowym Androida, gdzie od adresu (adresów) to odwzorowanie ma miejsce, ale bez radości. Zastanawiam się, czy to jest teraz do domyślnego dostawcy sms/mms do realizacji tego? Czy masz jakieś doświadczenie w tym zakresie? – brandall

+0

Myślę, że mogłem go znaleźć [tutaj] (http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android-apps/5.1.1_r1/com/android/ mms/data/Contact.java # 343). Sugeruje, że używa 'ContactsContract.CommonDataKinds.Phone'? Przysięgam, że już sprawdziłem, że ten identyfikator nie pasuje. – brandall

+0

@brandall kontakt może zostać usunięty/utworzony/zmieniony i może istnieć wiele różnych kontaktów z tym samym numerem, sms db nie może nadążyć za zmianami w db danych kontaktów, jedyną rzeczą, która nie może się zmienić jest adres kanoniczny, który wysłał/odebrał to sms, dlatego RecipientId musi mapować na telefon (y), a nie na kontakt. Reszta jest, jak zaimplementowano w mms.data.Contact.java, aż do implementatora, aby mapować między adresem kanonicznym a kontaktem – marmor

1

Dlaczego stosunkowo nowy Telephony API byłoby użycie nieaktualnych tablic zamiast ContactsContract?

To, o czym mówisz, nie jest nowe. W Telephony.java, widać to opiera się na istniejącym content://sms dostawcy:

public static final class Inbox implements BaseColumns, TextBasedSmsColumns { 
     /** 
     * The {@code content://} style URL for this table. 
     */ 
     public static final Uri CONTENT_URI = Uri.parse("content://sms/inbox"); 

Było już there in Donut (i zapewne wcześniej, ale nie sprawdzałem).

Co nowego w wersji Kitkat is the ability to change the SMS app.