вторник, 10 июня 2014 г.

Получаем список SMS-сообщений

В этой заметке вы узнаете, как получить список СМС-сообщений на устройстве. Важное замечание: Описанный способ работает на версиях Android до 4.3(включительно), начиная с версии 4.4 работа с СМС-сообщениями была упрощена, доступ реализован через контент-провайдер.












Начнём с того, что СМС-сообщения хранятся в локальной БД, также как и контакты, звонки, календарь и т.д. Однако по какой-то причине в Goggle написали контент-провайдеры для всего, кроме СМС, но они всё-таки исправили ситуация в Android 4.4. В предыдущих статьях/заметках я уже показывал, как получать доступ к спискам контактов и вызов, используя контент-провайдеры, так что думаю, проблем у вас не возникнет. Если появятся вопросы, задавайте, постараюсь (устройства с Android 4.4 не имею) помочь.
Ссылка на официальную документацию «android.provider.Telephony.Sms»

Что необходимо для чтения SMS.
  • Выдать права на чтение СМС-сообщений – «Uses-Permission: Read SMS := true»
  • Т.к. контент-провайдера нет, нужно знать, где хранятся сообщения (этот пункт рассмотрен ниже)
  • Написать код :)
Принцип получения списка почти не отличается от запроса к контент-провайдеру.

По первому пункту всё вроде понятно без объяснения, поэтому рассмотрим второй пункт.
Как я уже говорил, все SMS-сообщения, созданные и отправленные на мобильном устройстве, а также полученные от других абонентов, сохраняются в локальной базе SMS-сообщений. Эти сообщения, в зависимости от их типа, распределены по определенным каталогам, имеющим стандартные названия и URI.
Вот полный список каталогов SMS-сообщений и URI для каждого каталога SMS:
  • Все: «content://sms»
  • Входящие: «content://sms/inbox»
  • Отправленные: «content://sms/sent»
  • Черновики: «content://sms/draft»
  • Исходящие: «content://sms/outbox»
  • Неотправленные: «content://sms/failed»
  • Находящиеся в очереди: «content://sms/queued»
  • Недоставленные: «content://sms/undelivered»
  • Разговоры: «content://sms/conversations»
Наконец-то добрались до третьего пункта. Пишем приложение, которое позволит вывести список сообщений из выбранного каталога.
Компоненты, которые будем использовать:
  • Один TTabControl – 2 вкладки (список каталогов и список сообщений из выбранного каталога)
  • Два TListBox'а – по одному на каждой вкладке TTabControl'а.
  • На вторую вкладку помещаем «TToolBar» и на нём создаём кнопку «Назад»

Структура:

Далее в первый ListBox добавляем 9 ListBoxItem'ов, по одному на каждый каталог SMS-сообщений. Я добавил их в дизайн-тайме. Пишем одну процедуру для всех ListBoxItem'ов, обрабатывающую выбранный каталог.
Код процедуры:
uses
  Androidapi.JNI.GraphicsContentViewText, FMX.Helpers.Android, Androidapi.Helpers;

procedure TForm1.ListBoxItemsClick(Sender: TObject);
var
  cursor: JCursor;
  catalog, SMSListBoxItem: TListBoxItem;
begin
  catalog := TListBoxItem(Sender);
  ListBox2.Clear;
  ListBox2.BeginUpdate;
  try
    cursor := SharedActivity.getContentResolver.query(
     StrToJURI(catalog.ItemData.Detail),
      nil,
       nil,
        nil,
         nil);

    if(cursor.getCount > 0) then
    begin

      while (cursor.moveToNext) do
      begin

        SMSListBoxItem := TListBoxItem.Create(ListBox2);

        SMSListBoxItem.ItemData.Text := JStringToString(cursor.getString(
        cursor.getColumnIndex(StringToJString('ADDRESS'))));

        ListBox2.AddObject(SMSListBoxItem);

      end;
    end;


  finally
    cursor.close;
    ListBox2.EndUpdate;
  end;

  TabControl1.ActiveTab := TabItem2;

end;


Какие поля можно получить:

Данный список лежит в официальной документации: android.provider.Telephony.Sms

В общем-то, всё. Если есть вопросы, то пишите в комменты.

Пример:
Каталог "Входящие"


Исходный код: Скачать с Google Drive

1 комментарий: