Статьи

Создание приложения для контактов с помощью jQuery Mobile и Android SDK — Часть 3

Во второй части учебного цикла мы продемонстрировали, как создать учетную запись для вновь созданных контактов. Мы также описали, как редактировать и удалять существующие контакты. В части 3 мы продолжим обучение, объяснив, как добавить новый контакт. Мы также обсудим, как использовать API Java Java для доступа к контактам на устройстве Android и управления ими.

В ListPage.html нажатие кнопки «Добавить» на панели заголовка (часть 1, рисунок 2) вызывает функцию JavaScript с именем addContact() . Связанные разделы HTML-кода и функции addContact() перечислены ниже. Обратите внимание, что функция немедленно отображает экран Progress и вызывает ContactsActivity.addContact() , передавая DetailPage.html в качестве страницы обратного вызова для отображения.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
<!— Contact List —>
<div data-role=»header» id=»hdrList» data-nobackbtn=»true»>
  <h1><img align=»top» src=»img/contacts.png»> Contacts</h1>
  <a id=»buttonAddContact» data-icon=»plus» class=»ui-btn-right»
    href=»<B>javascript:addContact();</B>return false;»
</div>
<div data-role=»content» id=»contentList» data-theme=»c»>
  <ul data-role=»listview» data-dividertheme=»c» id=»contactSelections»></ul>
</div>
<div data-role=»footer» id=»ftrList»></div>
<script>
function <B>addContact()</B>{
  showProgress();
  contactSupport.addContact(‘DetailPage.html’);
}
</script>

Связанный код в классе ContactsActivity показан ниже.

1
2
3
4
5
6
7
public void addContact(String displayPage){
  showContact(<B>»»</B>, displayPage);
}
 
public void showContact(String contactId, String displayPage){
  loadPage(displayPage + «?» + contactId);
}

Мы рассмотрели метод showContact() в разделе «Существующий контакт» выше. Добавление контакта обрабатывается очень похоже на сохранение существующего контакта, за исключением того, что параметр contactId передается в виде пустой строки из addContact() . Из обсуждения в разделе «Существующий контакт» следующая последовательность вызовов методов выполняется для существующего контакта (где id — непустая строка).

1
2
3
4
ContactsActivity.loadPage(‘DetailPage.html?<em>id</em>’)
  -> DetailPage.html:$(document).ready()
    -> ContactsActivity.getContact(<em>id</em>, ‘setCurrentContact’)
      -> DetailPage.html:setCurrentContact(json)

При добавлении контакта будет иметь место та же последовательность, однако id теперь является пустой строкой. Давайте снова посмотрим на листинг метода ContactsActivity.getContact() .

1
2
3
4
5
public void getContact(String contactId, String contactCallback){
  String json = <B>ContactUtility.getContactJSON(contactId, …);
  final String callbackFunction = «javascript:» + contactCallback + «(‘» + json + «‘)»;
  loadURL(callbackFunction);
}

ContactUtility.getContactJSON() возвращает специальную «пустую» строку JSON, если параметр contactId пуст. Эта специальная строка JSON показана ниже.

01
02
03
04
05
06
07
08
09
10
11
{
  «contactId»:»»,
  «firstName»:»»,
  «lastName»:»»,
  «note»:{«rowId»:»»,»text»:»»},
  «ims»:[],
  «phones»:[],
  «emails»:[],
  «organizations»:[],
  «addresses»:[]
}

Во второй части этого руководства мы рассмотрели функцию JavaScript обратного вызова setCurrentContact() в DetailPage.html . Он обработает вышеуказанную строку JSON таким образом, чтобы

  • Элементы пользовательского интерфейса, представленные переменными contactIdVar , firstNameVar , lastNameVar и noteVar , устанавливаются в пустую строку.
  • Другие элементы пользовательского интерфейса, например телефоны, имеют предопределенные типы и пустые поля ввода. Например, четыре различных типа полей ввода телефона создаются с пустыми значениями для следующих типов: Дом, Работа, Мобильный телефон и Прочее.

При сохранении контакта выполняются те же шаги в разделе «Сохранение контакта». Метод ContactUtility.saveOrUpdateContact() может различать существующий и вновь добавленный контакт, проверяя его поле идентификатора. Для вновь добавленного контакта поле id не заполнено; в результате он сохраняется как новый контакт.


Рассмотрим кнопку «Отмена» на рисунке 3 (часть 1), отображаемую на экранах «Пустой контакт» и «Существующий контакт». Когда эта кнопка нажата, пользователь возвращается на экран «Список контактов» без изменений в редактируемом контакте. HTML-листинг в DetailPage.html приведен ниже, где действие кнопки определено как showListPage() .

1
2
3
4
5
6
7
8
    
  …
  <div align=»CENTER» <B>data-role=»controlgroup» data-type=»horizontal»</B>>
    <a href=»javascript:generateJson();return false;»
    <a id=»deleteButton» href=»javascript:showDialog();return false;»
    <a href=»<B>javascript:showListPage();</B>return false;»
  </div>
</div>

Ниже приведен список для функции showListPage() . Он отображает экран «Ход выполнения» и вызывает метод ContactsActivity.showAllContacts() , передавая ListPage.html в качестве страницы обратного вызова для отображения.

1
2
3
4
function showListPage(){
  showProgress();
  contactSupport.showAllContacts(‘ListPage.html’);
}

Метод ContactsActivity.showAllContacts() показан ниже. Он просто загружает страницу обратного вызова без какой-либо обработки данных.

1
2
3
public void showAllContacts(String displayPage){
  loadPage(displayPage);
}

Давайте начнем с com.jquerymobile.demo.contact.ContactUtility класса com.jquerymobile.demo.contact.ContactUtility который предоставляет служебные методы для чтения и управления контактами в базе данных контактов устройства Android.

Вспомните из части 1 этого руководства, что список контактов в формате JSON имеет следующий формат.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
{«contacts»:[
  {«key»:»A»,»values»:[
    {«contactId»:»257″,»displayName»:»Aach Herb»,»key»:»A»},
    …,
    {«contactId»:»256″,»displayName»:»Aaker David»,»key»:»A»}
    ]
  },
  {«key»:»B»,»values»:[
    {«contactId»:»259″,»displayName»:»Belanger Andre»,»key»:»B»},
    …,
    {«contactId»:»260″,»displayName»:»Bohme Jacob»,»key»:»B»}
    ]
  },
  …
  ]
}

Контакты сгруппированы по первому инициалу отображаемого имени контакта, который является значением key атрибута. Отображаемое имя создается путем объединения имени и фамилии контакта. При отображении в пользовательском интерфейсе значение key атрибута будет использоваться в качестве значения разделителя списка, который группирует контакты, первые начальные значения которых соответствуют этому значению. Процессор JSON Джексона создает документ JSON в указанном выше формате из объектов Java, определяя имена и типы полей, например массивы, путем проверки этих объектов. Есть три класса Java, которые представляют список контактов выше. Те

  • ContactDisplay , который представляет данные contactId уровня, а именно contactId , displayName и key
  • ContactGroup , которая имеет коллекцию объектов ContactDisplay для определенного key , например «A»
  • ContactList , который является корневым классом с коллекцией объектов ContactGroup

Эти классы имеют имена полей, точно совпадающие с именами полей в приведенном выше списке в формате JSON. Каркас JSON JSON предоставляет множество опций для генерации текста в формате JSON из объектов Java, включая настройку имен полей. Конкретный API, который мы используем, поддерживает имена полей при генерации строки в формате JSON из объекта Java.

Как показано в листинге ниже, ContactDisplay предоставляет contactId , displayName и key для контакта, где key получен из displayName . Что примечательно в этом классе, так это то, что он реализует интерфейс java.lang.Comparable позволяющий сортировать контакты на основе атрибута displayName . Для этого интерфейса требуется метод compareTo() , который возвращает одно из значений -1, 0 или 1, в зависимости от того, меньше ли первый инициал атрибута displayName контакта, равен ли он или больше, чем у контакта, которым он является. по сравнению с.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.jquerymobile.demo.contact;
 
public class ContactDisplay implements Comparable<Object>{
  private String contactId;
  private String displayName;
   
  public String getContactId() {
    return contactId;
  }
 
  public void setContactId(String contactId) {
    this.contactId = contactId;
  }
 
  public String getDisplayName() {
    return displayName;
  }
   
  public void setDisplayName(String displayName) {
    this.displayName = displayName;
  }
   
  public String getKey(){
    if(displayName == null || «».equals(displayName)){
      return «»;
    }
    else{
      return (String.valueOf(displayName.charAt(0))).toUpperCase();
    }
  }
   
  public int compareTo(Object arg0) {
    if(arg0 == null || !this.getClass().equals(arg0.getClass())){
      return 1;
    }
    String otherDisplayName = ((ContactDisplay)arg0).getDisplayName();
    if(displayName == null){
      if(otherDisplayName == null){
        return 0;
      }else{
        return -1;
      }
    }else{
      if(otherDisplayName == null){
        return 1;
      }else{
        return displayName.compareToIgnoreCase(otherDisplayName);
      }
    }
  }
}

ContactGroup состоит из коллекции объектов ContactDisplay которые имеют одинаковый ключ. ContactGroup key ContactGroup имеет то же значение, что и атрибут ContactDisplay объектов ContactDisplay он содержит.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
package com.jquerymobile.demo.contact;
 
import java.util.Collection;
 
public class ContactGroup {
  private String key;
  private Collection<ContactDisplay> values;
 
  public Collection<ContactDisplay> getValues() {
    return values;
  }
  public void setValues(Collection<ContactDisplay> values) {
    this.values = values;
  }
  public String getKey() {
    return key;
  }
  public void setKey(String key) {
    this.key = key;
  }
}

Список для класса ContactList приведен ниже. Это очень простая структура данных, которая содержит коллекцию объектов ContactGroup .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
package com.jquerymobile.demo.contact;
 
import java.util.ArrayList;
import java.util.Collection;
 
public class ContactList {
  public ContactList() {
    super();
    contacts = new ArrayList<ContactGroup>();
  }
   
  private Collection<ContactGroup> contacts;
 
  public Collection<ContactGroup> getContacts() {
    return contacts;
  }
}

Строка в формате JSON для списка контактов создается в методе ContactUtility.getAllContactDisplaysJSON() как показано ниже.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import java.util.ArrayList;
import java.util.Collections;
import org.codehaus.jackson.map.ObjectMapper;
import java.io.StringWriter;
 
public class ContactUtility {
  public static final String EMPTY_CONTACT_LIST = «{\»contacts\»:[]}»;
  …
  public static String getAllContactDisplaysJSON(…){
    // Obtain all ContactDisplay objects from database and sort them.
    ArrayList<ContactDisplay> list = getAllContactDisplays(…);
    Collections.sort(list);
     
    // Populate the data structure consisting of
    // ContactList-ContactGroup-ContactDisplay objects.
    // Start with initializing some variables.
    ContactList contactList = new ContactList();
    String key = «»;
    ArrayList<ContactDisplay> values = new ArrayList<ContactDisplay>();
    ContactGroup group = null;
    StringWriter writer = new StringWriter();
     
    // Process the list of ContactDisplay objects to construct the data structure.
    if(list != null && !list.isEmpty()){
      for(ContactDisplay display:list){
        if(!display.getKey().equals(key)){
          if(values.size() > 0){
            group = new ContactGroup();
            group.setKey(key);
            group.setValues(values);
            contactList.getContacts().add(group);
          }
          key = display.getKey();
          values = new ArrayList<ContactDisplay>();
        }
        values.add(display);
      }
      // Add the last group
      if(values.size() > 0){
        group = new ContactGroup();
        group.setKey(key);
        group.setValues(values);
        contactList.getContacts().add(group);
      }
    }else{
      return EMPTY_CONTACT_LIST;
    }
     
    // We have the data structure of ContactList-ContactGroup-ContactDisplay objects where
    // contactList is the root level element.
    // org.codehaus.jackson.map.ObjectMapper.
    try{
      ObjectMapper mapper = new ObjectMapper();
      mapper.writeValue(writer, contactList);
    }catch(Exception e){
      return EMPTY_CONTACT_LIST;
    }
    return writer.toString();
  }
  …
 }
  • Первым шагом является получение списка всех контактов из базы данных с помощью getAllContactDisplays() , подробности о котором мы рассмотрим позже. Контакты представлены в виде списка, однако они еще не отсортированы.
  • Метод java.util.Collections.sort() сортирует список контактов, используя метод compareTo() в объекте ContactDisplay .
  • В обычном случае пустого списка возвращается строка JSON без элементов (обратите внимание на константу с именем EMPTY_CONTACT_LIST ). В противном случае отсортированный список повторяется для создания групп на основе ключей объектов ContactDisplay в списке. Для каждого уникального ключа ContactGroup объект ContactGroup и все объекты ContactDisplay с этим ключом хранятся в этой ContactGroup .
  • Каждая группа ContactGroup находится на корневом уровне. ContactList является объектом.
  • Наконец, создается экземпляр класса org.codehaus.jackson.map.ObjectMapper вызывается его метод write() путем передачи объекта ContactList корневого уровня и объекта StringWriter . ContactList рекурсивно просматривает все поля и объекты в ContactList и генерирует текст JSON на основе имен полей этих объектов. Вызов метода StringWriter.toString() создает объект JSON String.

Вспомните из части 2 этого руководства, что в следующем документе JSON представлены сведения о контакте.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
{
  «contactId»:»265″,
  «firstName»:»Aafjes»,
  «lastName»:»Bertus»,
  «note»:{«rowId»:»2265″,»text»:»Author»},
  «ims»:[
    {«rowId»:»2274″,»protocol»:»-1″,»value»:»»},
    {«rowId»:»2275″,»protocol»:»0″,»value»:»bertus@aim»},
    {«rowId»:»2276″,»protocol»:»5″,»value»:»bertus@google»},
    {«rowId»:»2277″,»protocol»:»6″,»value»:»»},
    {«rowId»:»2278″,»protocol»:»7″,»value»:»»},
    {«rowId»:»2279″,»protocol»:»1″,»value»:»bertus@msn»},
    {«rowId»:»2280″,»protocol»:»8″,»value»:»»},
    {«rowId»:»2281″,»protocol»:»4″,»value»:»»},
    {«rowId»:»2282″,»protocol»:»3″,»value»:»»},
    {«rowId»:»2283″,»protocol»:»2″,»value»:»»}
  ],
  «phones»:[
    {«rowId»:»2284″,»type»:»1″,»no»:»111-222-3333″},
    {«rowId»:»2285″,»type»:»2″,»no»:»222-000-9999″},
    {«rowId»:»2286″,»type»:»3″,»no»:»444-787-9900″},
    {«rowId»:»2287″,»type»:»7″,»no»:»555-744-9999″}
  ],
  «emails»:[
    {«rowId»:»2271″,»type»:»1″,»value»:»[email protected]»},
    {«rowId»:»2272″,»type»:»2″,»value»:»[email protected]»},
    {«rowId»:»2273″,»type»:»3″,»value»:»[email protected]»}
  ],
  «organizations»:[
    {«rowId»:»2269″,»type»:»1″,»name»:»Publications Inc.»,»title»:»CEO»},
    {«rowId»:»2270″,»type»:»2″,»name»:»Volunteers Corp.»,»title»:»Member»}
  ],
  «addresses»:[
    {«rowId»:»2266″,»type»:»1″,»street»:»Alhambra st.»,»city»:»Alhambra»,»state»:»MI»,
      «country»:»USA»,»zip»:»48100″,»poBox»:»»},
    {«rowId»:»2267″,»type»:»2″,»street»:»1 Corporation st»,»city»:»Alhambra»,»state»:»MI»,
      «country»:»USA»,»zip»:»48000″,»poBox»:»44456″},
    {«rowId»:»2268″,»type»:»3″,»street»:»»,»city»:»»,»state»:»»,
      «country»:»»,»zip»:»»,»poBox»:»»}
  ]
}

Мы используем инфраструктуру JSON JSON для генерации этой строки JSON из следующих классов Java.

  • Contact представляет данные корневого уровня. Это содержит
    • contactId , firstName , lastName , которые являются типами String
    • note , которое является типом объекта
    • ims , phones , emails , organizations , addresses , которые являются коллекциями объектов
  • Note представляет note и имеет rowId и text поля.
  • IM представляет собой член коллекции ims и имеет rowId , protocol и value .
  • Phone представляет собой член коллекции phones и имеет rowId , type и no полей.
  • Email представляет собой член коллекции emails и имеет rowId , type и value .
  • Organization представляет собой член коллекции organizations и имеет rowId , type , name и title .
  • Address представляет собой член коллекции addresses и имеет rowId , type , street , city , state , country , zip и poBox .

Обратите внимание, что все эти классы являются простыми держателями данных, которые предоставляют только методы получения / установки. Для краткости ниже приведен список только класса корневого уровня Contact .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.jquerymobile.demo.contact;
import java.util.Collection;
 
public class Contact {
  private String contactId;
  private String firstName;
  private String lastName;
  private Collection<Phone> phones;
  private Collection<Email> emails;
  private Collection<Address> addresses;
  private Collection<Organization> organizations;
  private Note note;
  private Collection<Im> ims;
   
  public String getContactId() {
    return contactId;
  }
  public void setContactId(String contactId) {
    this.contactId = contactId;
  }
  public String getFirstName() {
    return ContactUtility.replaceNull(firstName);
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  public String getLastName() {
    return ContactUtility.replaceNull(lastName);
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  public Collection<Im> getIms() {
    return ims;
  }
  public void setIms(Collection<Im> ims) {
    this.ims = ims;
  }
  public Collection<Phone> getPhones() {
    return phones;
  }
  public void setPhones(Collection<Phone> phones) {
    this.phones = phones;
  }
  public Collection<Email> getEmails() {
    return emails;
  }
  public void setEmails(Collection<Email> emails) {
    this.emails = emails;
  }
  public Collection<Address> getAddresses() {
    return addresses;
  }
  public void setAddresses(Collection<Address> addresses) {
    this.addresses = addresses;
  }
  public Note getNote() {
    return note;
  }
  public void setNote(Note note) {
    this.note = note;
  }
  public Collection<Organization> getOrganizations() {
    return organizations;
  }
  public void setOrganizations(Collection<Organization> organizations) {
    this.organizations = organizations;
  }
}

Строка в формате JSON для контактных данных создается в методе ContactUtility.getContactJSON() как показано ниже.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import org.codehaus.jackson.map.ObjectMapper;
import java.io.IOException;
import java.io.StringWriter;
public class ContactUtility {
  …
  private static final String EMPTY_JSON = «{\»contactId\»:\»\»,\»firstName\»:\»\»,\»lastName\»:\»\»,
    \»note\»:{\»rowId\»:\»\»,\»text\»:\»\»},\»ims\»:[],\»phones\»:[],\»emails\»:[],
    \»organizations\»:[],\»addresses\»:[]}»;
  public static final String EMPTY = «»;
  …
  public static String getContactJSON(String id, ContentResolver contentResolver){
    // if id is EMPTY, immediately return an empty json
    if(EMPTY.equals(id)){
      return EMPTY_JSON;
    }
    Contact contact = getContact(id,contentResolver);
    StringWriter writer = new StringWriter();
    if(contact != null){
      try {
        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(writer, contact);
      } catch (IOException e) {
        return EMPTY_JSON;
      }
    }
    String val = writer.toString();
    return val;
  }
  …
}
  • Если id контакта — пустая строка, getContactJSON() возвращает пустую строку JSON, EMPTY_JSON . (Как обсуждалось ранее, это сценарий, когда новый контакт должен быть добавлен через приложение, и у нас еще нет идентификатора контакта.)
  • Если идентификатор не пустой, getContact() метод getContact() чтобы получить экземпляр класса Contact из базы данных контактов на устройстве. (Мы рассмотрим этот метод позже.)
  • Затем, используя класс org.codehaus.jackson.map.ObjectMapper JSON JSON org.codehaus.jackson.map.ObjectMapper , объект Contact преобразуется в строковое представление в формате JSON, и эта строка возвращается вызывающей стороне метода. Как обсуждалось в предыдущем разделе генерации списка контактов, этот конкретный метод создания строки JSON поддерживает имена полей в объектах Java.

В части 4 этого руководства (следующая часть) мы рассмотрим код приложения, который работает с API контактов Android. Перед этим мы хотим дать обзор того, как контактная информация хранится в базе данных на устройстве Android. Различные сущности, связанные с контактом, хранятся в таблицах базы данных, к которым можно обращаться с помощью SQL-запросов. API контактов Android предоставляет различные классы и методы для представления таблиц и столбцов таблиц для хранения контактов, а также специальные запросы, которые можно выполнять для этих таблиц. Ниже мы предоставляем информацию об API контактов Android, используемом в этом учебном приложении.

  • Класс android.content.ContentResolver используется для выполнения запросов на чтение / запись в базе данных контактов.
  • Класс android.database.Cursor используется для итерации набора результатов, возвращенного из запроса на чтение, и чтения отдельных столбцов из определенной строки.
  • Класс android.content.ContentProviderOperation используется для определения операции вставки в базу данных.
  • Класс android.provider.ContactsContract и его поля представляют таблицы базы данных, связанные с контактами. (Подробности смотрите в документации Android по ContactsContract .)

Для получения информации об объекте, связанном с контактом, необходимо три элемента.

  • основанное на URI представление таблицы для извлечения данных из
  • предложение ‘where’ для запроса; это построено с использованием констант в API контактов Android и параметров, созданных приложением
  • имена столбцов для выборки из строки набора результатов; это константы в API контактов Android

Ниже мы приводим сводку этих трех элементов для конкретных запросов на чтение, используемых в учебном приложении. Для всех предложений where, кроме предложения в запросе «Контакты, связанные с учетной записью», приложение предоставляет contactId в качестве параметра. Для запроса с именем «Контакты, связанные с учетной записью» приложение передает константу com.jquerymobile.demo.contact в качестве параметра запроса в предложении where. Для запроса с именем «Идентификатор контакта, отображаемое имя контакта» предложение where отсутствует, поскольку мы выбираем все записи.

Контакты База данных Запросы
  • Запрос: идентификатор контакта, отображаемое имя контакта
    • URI: ContactsContract.Contacts.CONTENT_URI
    • Где пункт: нет
    • Названия столбцов:
      • contactId : ContactsContract.Contacts._ID
      • displayName : ContactsContract.Contacts.DISPLAY_NAME
  • Запрос: Имя, Фамилия
    • URI: ContactsContract.Data.CONTENT_URI
    • Где пункт: ContactsContract.RawContactsEntity.CONTACT_ID = ? AND
      ContactsContract.Data.MIMETYPE = ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
      ContactsContract.RawContactsEntity.CONTACT_ID = ? AND
      ContactsContract.Data.MIMETYPE = ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
    • Названия столбцов:
      • firstName : ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME
      • lastName : ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME
  • Запрос: Адрес
    • URI: ContactsContract.Data.CONTENT_URI
    • Где пункт: ContactsContract.Data.CONTACT_ID = ? AND ContactsContract.Data.MIMETYPE =
      ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE
      ContactsContract.Data.CONTACT_ID = ? AND ContactsContract.Data.MIMETYPE =
      ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE
    • Названия столбцов:
      • street : ContactsContract.CommonDataKinds.StructuredPostal.STREET
      • city : ContactsContract.CommonDataKinds.StructuredPostal.CITY
      • state : ContactsContract.CommonDataKinds.StructuredPostal.REGION
      • poBox : ContactsContract.CommonDataKinds.StructuredPostal.POBOX
      • zip : ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE
      • country : ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY
      • rowId : ContactsContract.CommonDataKinds.StructuredPostal._ID
  • Запрос: электронная почта
    • URI: ContactsContract.CommonDataKinds.Email.CONTENT_URI
    • Где предложение: ContactsContract.CommonDataKinds.Email.CONTACT_ID = ?
    • Названия столбцов:
      • value : ContactsContract.CommonDataKinds.Email.DATA
      • type : ContactsContract.CommonDataKinds.Email.TYPE
      • rowId : ContactsContract.CommonDataKinds.Email._ID
  • Запрос: IM
    • URI: ContactsContract.Data.CONTENT_URI
    • Где пункт: ContactsContract.Data.CONTACT_ID = ? AND ContactsContract.Data.MIMETYPE =
      ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE
      ContactsContract.Data.CONTACT_ID = ? AND ContactsContract.Data.MIMETYPE =
      ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE
    • Названия столбцов:
      • value : ContactsContract.CommonDataKinds.Im.DATA
      • protocol : ContactsContract.CommonDataKinds.Im.PROTOCOL
      • rowId : ContactsContract.CommonDataKinds.Im._ID
  • Запрос: Примечание
    • URI: ContactsContract.Data.CONTENT_URI
    • Где пункт: ContactsContract.Data.CONTACT_ID = ? AND ContactsContract.Data.MIMETYPE =
      ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE
      ContactsContract.Data.CONTACT_ID = ? AND ContactsContract.Data.MIMETYPE =
      ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE
    • Названия столбцов:
      • text : ContactsContract.CommonDataKinds.Note.NOTE
      • rowId : ContactsContract.CommonDataKinds.Note._ID
  • Запрос: Организация
    • URI: ContactsContract.Data.CONTENT_URI
    • Где пункт: ContactsContract.Data.CONTACT_ID = ? AND ContactsContract.Data.MIMETYPE =
      ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE
      ContactsContract.Data.CONTACT_ID = ? AND ContactsContract.Data.MIMETYPE =
      ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE
    • Названия столбцов:
      • name : ContactsContract.CommonDataKinds.Organization.DATA
      • title : ContactsContract.CommonDataKinds.Organization.TITLE
      • type : ContactsContract.CommonDataKinds.Organization.TYPE
      • rowId : ContactsContract.CommonDataKinds.Organization._ID
  • Запрос: Телефон
    • URI: ContactsContract.CommonDataKinds.Phone.CONTENT_URI
    • Где предложение: ContactsContract.CommonDataKinds.Phone.CONTACT_ID = ?
    • Названия столбцов:
      • no : ContactsContract.CommonDataKinds.Phone.NUMBER
      • type : ContactsContract.CommonDataKinds.Phone.TYPE
      • rowId : ContactsContract.CommonDataKinds.Phone._ID
  • Запрос: контакты, связанные с учетной записью
    • URI: ContactsContract.RawContacts.CONTENT_URI
    • Где пункт: ContactsContract.RawContacts.ACCOUNT_TYPE = ?
    • Название столбца:
      • contactId : ContactsContract.RawContacts.CONTACT_ID

Имея в виду вышеупомянутую информацию, мы можем теперь взглянуть на отдельные методы, которые запрашивают базу данных контактов.

Следующий метод в ContactUtility получает список всех контактов в форме коллекции ContactDisplay . Мы видели, что этот метод ContactUtility.getAllContactDisplaysJSON() из ContactUtility.getAllContactDisplaysJSON() . Метод использует запрос «Идентификатор контакта, отображаемое имя контакта», который только что обсуждался выше.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
private static ArrayList<ContactDisplay> getAllContactDisplays(ContentResolver contentResolver){
  Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null,
      null, null, null);
  ArrayList<ContactDisplay> list = new ArrayList<ContactDisplay>();
  if (cursor.getCount() > 0) {
    while (cursor.moveToNext()) {
      String id = cursor.getString(cursor
          .getColumnIndex(ContactsContract.Contacts._ID));
      String displayName = cursor
          .getString(cursor
              .getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
      ContactDisplay display = new ContactDisplay();
      display.setContactId(id);
      display.setDisplayName(displayName);
      list.add(display);
    }
    cursor.close();
  }
  return list;
}
  • Объект ContentResolver используется для выполнения запроса, в котором представление URI для запрашиваемой таблицы передается в качестве параметра.
  • Результат возвращается как экземпляр Cursor . Перебирая курсор, мы получаем нужные поля, используя константы для имен столбцов.
  • В каждой строке курсора соответствующий объект ContactDisplay создается из этих полей и помещается в коллекцию.
  • В конце мы закрываем курсор и возвращаем коллекцию.

Следующий метод в ContactUtility возвращает массив строк, где первый элемент — это имя контакта, а второй — фамилия контакта. Метод использует запрос «Имя, Фамилия», только что рассмотренный выше.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private static String[] getFirstNameLastName(String id, ContentResolver contentResolver){
  String[] retValue = new String[2];
  retValue[0] = «»;
  retValue[1] = «»;
     
  Cursor nameCursor = contentResolver.query(ContactsContract.Data.CONTENT_URI,
      null, ContactsContract.Data.MIMETYPE + » = ? AND » +
        ContactsContract.RawContactsEntity.CONTACT_ID + » = ? «,
      new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE ,id},null);
  while (nameCursor.moveToNext()) {
      String given = nameCursor.getString(nameCursor.getColumnIndex(
        ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
      String family = nameCursor.getString(nameCursor.getColumnIndex(
        ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
      if(given != null){
        retValue[0] = given;
      }
      if(family != null){
        retValue[1] = family;
      }
  }
  nameCursor.close();
  return retValue;
}

Построение запроса и обработка результирующего набора очень похожи на getAllContactDisplays() . Отличие состоит в том, что дополнительные параметры передаются методу query() .

  • Первый параметр для query() — это URI для таблицы.
  • Второй параметр для query() имеет значение null, запрашивая все столбцы. (Для дополнительного повышения производительности можно ограничить количество возвращаемых столбцов. Для целей учебного приложения мы просто запросили все столбцы из запроса, хотя не все столбцы использовались.)
  • Третьим параметром для query() является предложение where, обсуждавшееся ранее.
  • Четвертый параметр для query() — это строковый массив, где каждый элемент массива соответствует соответствующему параметру, обозначенному символом «?» В предложении where.
  • Пятый параметр для query() является нулевым. Этот параметр можно использовать для сортировки набора результатов. Однако мы получаем один результат, соответствующий уникальному идентификатору. Поэтому столбец сортировки не указан.

Следующий метод в ContactUtility возвращает объект Contact с деталями, заполненными из базы данных, где id контакта является входным параметром. Мы видели, что этот метод вызывается из ContactUtility.getContactJSON() .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private static Contact getContact(String id, ContentResolver contentResolver){
  Contact contact = null;
  Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null,
      ContactsContract.Contacts._ID + » = ? «,
      new String[]{id}, null);
  if (cursor.getCount() > 0) {
    contact = new Contact();
    while (cursor.moveToNext()) {
      String contactId = cursor.getString(cursor
          .getColumnIndex(ContactsContract.Contacts._ID));
      contact.setContactId(contactId);
      String[] names = getFirstNameLastName(contactId, contentResolver);
      contact.setFirstName(names[0]);
      contact.setLastName(names[1]);
      contact.setPhones(getPhones(id, contentResolver));
      contact.setEmails(getEmails(contactId, contentResolver));
      contact.setNote(getNote(contactId,contentResolver));
      contact.setAddresses(getAddresses(contactId,contentResolver));
      contact.setIms(getIms(contactId, contentResolver));
      contact.setOrganizations(getOrganizations(contactId, contentResolver));
    }
  }
  cursor.close();
  return contact;
}

Метод использует различные методы внутренних запросов. Из них getFirstNameLastName() был рассмотрен чуть выше. Другие операции, а именно getPhones() , getEmails() , getNote() , getAddresses() , getIms() и getOrganizations() очень похожи на getFirstNameLastName() и поэтому мы опускаем их обзоры для краткости. Заинтересованный читатель ссылается на исходный код учебника. Обратите внимание, что в этих методах используются ранее обсуждавшиеся таблицы, в которых предложения и имена столбцов суммированы в «Контактах базы данных контактов» следующим образом:

  • getPhones() использует телефонный запрос
  • getEmails() использует запрос электронной почты
  • getNote() использует запрос Note
  • getAddresses() использует getAddresses() запрос
  • getIms() использует IM-запрос
  • getOrganizations() использует запрос организации

В третьей части мы продолжили обучение, объяснив, как добавить новый контакт. Мы также обсудили, как использовать API Java Java для доступа и управления контактами на устройстве Android. Часть 4, последняя часть руководства, объясняет удаление и сохранение контакта с помощью Android Java API. В части 4 мы также опишем среду разработки для приложения, обсудим файлы конфигурации для проекта и дадим отдельные шаги для импорта проекта в Eclipse IDE.