Электронная библиотека » Евгений Сенько » » онлайн чтение - страница 2


  • Текст добавлен: 16 сентября 2017, 19:40


Автор книги: Евгений Сенько


Жанр: Компьютеры: прочее, Компьютеры


Возрастные ограничения: +12

сообщить о неприемлемом содержимом

Текущая страница: 2 (всего у книги 8 страниц) [доступный отрывок для чтения: 2 страниц]

Шрифт:
- 100% +

Далее происходит загрузка битового массива. И во время этой загрузки, периодически публикуется её прогресс методом setProgress другого runnable.



Далее создается новый Runnable, который устанавливает только что загруженный битовый массив на экран. И заканчивается все, созданием последнего Runnable, который делает шкалу прогресса невидимой.



А теперь рассмотрим вторую версию этого приложения, которое отправляет сообщения вместо runnable – ThreadingHandlerMessages. Откроем основную Activity этого приложения. Во-первых, этот код создает новый обработчик. И как в предыдущем примере, этот обработчик будет создаваться основным UI потоком. И соответственно работа, которую выполняет этот обработчик, будет выполняться в UI потоке. У этого обработчика есть метод handleMessage, в котором он реализует различные виды работ. Этот метод вначале проверяет код сообщения, содержащийся в этом сообщении, и затем выполняет действие, определенное для этого кода сообщения.



Например, если код – set_progress_bar_visibility, то будет установлено состояние видимости шкалы прогресса. Если код – progress_update, то будет установлено значение прогресса на шкале прогресса. Если код – set_bitmap, то этот код выводит битовый массив на дисплей.

Теперь перейдем к «слушателю» кнопки «Load Icon». Как и в предыдущих примерах, когда пользователь нажимает кнопку, этот код, создает и запускает новый поток, чей метод run определен runnable-объектом LoadIconTask.



Выполнение этого метода начинается при получении сообщения с кодом set_progress_bar_visibility с параметром, указывающим, что шкала прогресса должна стать видимой. Тогда это сообщение отправляется в обработчик, который и сделает шкалу прогресса видимой.

Далее происходит загрузка битового массива. И одновременно с этим, периодически обновляется прогресс, при помощи сообщения с кодом progress_update и с параметром, который указывает процент выполненной работы. Это будет результатом вызова обработчиком метода setProgress объекта progressBar.



Затем принимается и отправляется сообщение, чтобы вывести только что загруженное изображение на дисплей. И наконец, отправляется последнее сообщение, чтобы сделать шкалу прогресса невидимой.

Работа с сетью

Одной из определяющих характеристик современных мобильных устройств является то, что они могут обеспечить нас связью и сетевым подключением, то есть он-лайн, не привязывая нас к определенному местоположению. Смартфоны и планшеты комбинируют мощные процессоры с быстрым сетевым соединением по WiFi и сотовым сетям. Мобильные приложения должны уметь использовать эти сетевые возможности, чтобы обеспечить нас данными и предоставить доступ к службам. Android включает в себя поддержку множества сетевых классов при помощи пакетов Java.net, org. appache и android.net.

В текущей главе мы рассмотрим некоторые из этих классов, используя каждый из них для реализации одного и того же примера приложения. Это приложение взаимодействует с интернет-службой для получения информации о землетрясениях, произошедших в определенном географическом регионе. Чтобы заставить это приложение работать, код должен создать http-запрос, отправить его на сервер, получить результаты и затем отобразить эти результаты.

Для реализации этого, мы будем использовать три класса, это класс сокетов (Socket), класс HttpURLConnection и AndroidHttpClient.

Если запустить приложение, использующее класс socket, первоначально мы увидим одну кнопку с надписью «Load Data». И, если нажать эту кнопку, приложение отправит запрос HTTP GET на внешний сервер, и этот сервер ответит сложным текстом, содержащим запрошенные данные о землетрясениях.



Давайте рассмотрим исходный код, чтобы узнать, что нужно для получения этих данных. Откроем основную Activity этого приложения, и здесь мы видим «слушателя» кнопки загрузки данных. Когда эта кнопка нажата, приложение создает и затем выполняет AsyncTask с именем HttpGetTask.



Класс HttpGetTask сначала объявляет некоторые переменные, которые используются при создании запроса HttpGet.






Первым вызывается метод doInBackground. Этот метод создает новый сокет, который будет соединен с хостом api.geonames.org по стандартному http-порту: 80.



Затем код получает исходящий поток сокета, записывает в него http_get_command, и эта строка будет отправлена хосту, который интерпретирует его как запрос HTTP GET, а затем ответит, отправив обратно соответствующие данные ответа. Далее код получает входящий поток сокета, передавая его методу readStream, который считывает данные ответа из входящего потока сокета, и возвращает ответ в виде строки.

Затем эта строка передается методу onPostExecute, который выполняется в главном потоке, и который отображает ответ в текстовой вью.




Вернемся к приложению. Текст ответа включает в себя не только данные землетрясения, но и заголовки ответа HTTP. Но вы, возможно, не хотели бы показывать здесь этот избыточный текст, а хотели бы вывести на экран только данные землетрясения. Поэтому вы должны будете проанализировать ответ и извлечь только те данные, которые хотели бы вывести на экран. Кроме того, здесь отсутствует код обработки ошибок, который сделал бы это приложение более надежным. Использование сокетов – это компромиссный вариант, сходный с программированием низкого уровня. Вы можете записать в сокет все, что хотите, но взамен вы должны будете обрабатывать все многочисленные детали создания HTTP-запросов, прописать всю обработку ошибок и всю обработку HTTP-ответов.

В следующей реализации используется класс HttpURLConnection. Этот класс предоставляет интерфейс более высокого уровня, который обрабатывает больше деталей сетевого соединения, чем класс сокетов, но он также имеет менее гибкий API, чем другой вариант – класс Android HTTP client. Также необходимо отметить, что команда Android больше не работает над клиентом Android HTTP, отложив улучшения этого класса на будущее.

Итак, давайте рассмотрим пример приложения, реализованного на этот раз с классом HttpURLConnection. Приложение NetworkingURL внешне выглядит и работает также как и приложение из предыдущего примера, но после нажатия кнопки «Load Data» в текстовом выводе отсутствуют Http заголовки, они были удалены.

Давайте рассмотрим исходный код и посмотрим, как это работает. Откроем основную Activity этого приложения, и здесь мы увидим «слушателя» кнопки загрузки данных. Как и ранее, при нажатии этой кнопки приложение создаст и выполнит AsynchTask с именем httpGetTask.



Давайте рассмотрим этот класс. Когда в HttpGetTask срабатывает метод execute, вызывается метод doInBackground. Этот метод начинается с создания нового объекта URL и передачи строки URL-адреса для требуемой службы в качестве параметра.




Затем код вызывает метод openConnection для объекта URL, который возвращает Http соединение. Этот объект затем сохраняется в переменной httpUrlConnection.

Код продолжается, получая поток входящих данных (input stream) Http-соединения и передавая его в метод readStream. А метод readStream считывает данные ответа из сокета входящего потока, а затем возвращает ответ в виде строки. Однако на этот раз httpUrlConnection лишает заголовков http-ответ и обрабатывает проверку ошибок.

Далее эта строка передается методу onPostExecute, который выводит на экран ответ в текстовую вью.



Третий класс – AndroidHTTPClient. Этот класс является реализацией DefaultHttpClient проекта Apache. Он позволяет многое настроить. В частности, класс разбивает транзакцию HTTP на объект запроса и объект ответа. Это дает возможность создавать подклассы, которые настраивают обработку запросов и их ответов.

Пример приложения выглядит так же, поэтому перейдем прямо к коду и посмотрим на реализацию в приложении NetworkingAndroidHttpClient.



Откроем основную Activity этого приложения и перейдем к классу HttpGetTask. Этот класс начинается с создания нового объекта AndroidHttpClient, вызывая метод newInstance.




Далее вызывается метод doInBackground, код создает объект HttpGet, передавая в запросе URL-строку.

Затем создается объект ResponseHandler – обработчик ответа. В этом случае для запроса HttpGet обработчик ответа имеет тип BasicResponseHandler, который возвращает тело ответа.



И, наконец, запрос и обработчик ответа передаются в метод execute, который отправляет запрос, получает ответ, передавая его через обработчик ответа. Результат всего этого затем передается в onPostExecute, который выводит ответ в текстовую вью.



До сих пор примеры приложения запрашивали данные, а затем просто отображали эти данные в текстовой вью в том виде, в котором получили. Но эти данные имеют сложный формат и неудобны для восприятия человеку, поэтому нуждаются в дополнительной машинной обработке.

По сути, это все более популярный способ передачи текстовых данных через интернет, и многие веб-сервисы сейчас предоставляют данные в таких форматах. В частности, два формата, о которых мы будем говорить, это JavaScript Object Notation – JSON и Extensible Markup Language – XML. Рассмотрим каждый из них по отдельности.

Первый формат, это JavaScript Object Notation – JSON. Этот формат предназначен для небольших объемов и напоминает структуры данных, встречающиеся в традиционных языках программирования. Данные JSON упаковываются в два типа структур данных. Один – карты, которые являются наборами пар ключ – значение, и два – упорядоченные списки.

Теперь вернемся к примеру приложения, которое обращается к веб-службе за информацией о землетрясениях. Ответ, который вернулся, фактически был отформатирован в JSON.



Вот эти данные, давайте разобьем их на части.



Во-первых, данные содержат один объект JSON, и этот объект является картой, которая имеет одну пару ключ – значение. Ключ называется «earthquakes», а значение – это упорядоченный список. Этот список имеет несколько объектов, и каждый из этих объектов сам является картой, содержащей пары ключ – значение.

Например. Есть ключ под названием «eqid» и его значением является id землетрясения. Далее идет ключ «magnitude» с некоторым числовым значением. Затем ключ «lng», его значение – это долгота, на которой произошло землетрясение. Кроме того, есть множество других ключей, и все вместе эти значения являются данными для одного землетрясения.

Давайте посмотрим на пример приложения, которое получает эти данные из интернета, а затем обрабатывает их так, чтобы создать более читабельный для пользователя вид. Запустим приложение NetworkingAndroidHttpClientJSON. Как и ранее, это приложение первоначально отображает единственную кнопку с пометкой «Load Data» и, как и ранее, при нажатии этой кнопки приложение отправляет HTTP-запрос на внешний сервер, и этот сервер будет отвечать сложным текстом, содержащим запрошенные данные о землетрясениях. Однако на этот раз данные будут обработаны и представлены в виде списка.



Давайте рассмотрим исходный код, чтобы увидеть, как это работает. Сразу переходим к классу HttpGetTask.







Здесь метод doInBackground аналогичен тому, что мы видели раньше, но на этот раз он использует класс JSONResponseHandler для обработки ответа. Ключевым методом в этом классе является метод handleResponse. Этот метод начинается с передачи необработанного ответа через базовый обработчик ответа – BasicResponseHandler, который просто возвращает тело ответа без заголовков ответа HTTP.



Затем код использует JSONTokener для разбора JSON-ответа в объект Java, чтобы затем возвратить этот объекта верхнего уровня, который в данном случае является картой.



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



Затем код перебирает список землетрясений. И для каждого элемента этого списка он получает данные, связанные с одним землетрясением, и эти данные сохранены в картах.



Затем код суммирует различные части данных землетрясения, преобразуя их в одну строку и добавляя эту строку в список с именем result.



И затем, наконец, результат возвращается обратно вызывающему методу.

Второй формат данных, который мы рассмотрим – это Extensible Markup Language – XML. XML – это язык разметки для создания XML-документов. XML-документы содержат разметку и контент. Разметка кодирует описание структуры хранения в документе и логической структуры при помощи тегов и атрибутов. Контент – это все остальное. И, в частности, контент содержит данные ответа, когда XML используется для кодирования ответа HTTP.

Теперь вернемся к примеру приложения. Если мы зададим немного другой URL, то веб-сервис вернет данные землетрясения в формате XML, а не в формате JSON. Итак, вот эти данные.






Вначале есть элемент – тег, называемый geonames. В этот элемент вложен ряд элементов землетрясения и каждый из элементов землетрясения содержит другие элементы, которые обеспечивают данные для одного землетрясения.

Подобно тому, что мы видели в формате JSON, есть элемент eqid, его значение является идентификатором землетрясения. Есть также элемент lng, его значение – долгота, на которой землетрясение произошло, и точно так же, как в примере JSON, есть и множество других элементов.

Таким образом, если приложение получает XML-данные из интернета, ему нужно будет разобрать XML-документ, чтобы создать список для вывода на экран. Для разбора XML-документов Android предоставляет несколько различных типов парсеров XML.

Парсер DOM – Document Object Model (объектный). Парсеры DOM читают весь XML-документ и преобразуют его в структуру объектной модели документа – дерево, а затем приложение обрабатывает эту древовидную структуру. Этот парсер требует больше памяти, но позволяет приложению делать многопроходную обработку документа.

SAX – Simple API for XML (событийные) парсеры читают XML-документ как поток. И когда они сталкиваются с новым тегом в документе, они производят возврат в приложение, которое и обрабатывает информацию в этом теге. Эти парсеры используют меньше памяти, чем DOM-парсеры, но они ограничены выполнением обработки за один проход документа.

Pull-парсеры, так же как и SAX-парсеры, читают документ как поток, но используют подход, основанный на итераторах, где приложение, а не парсер, решает, когда следует переходить к следующему шагу синтаксического анализа. Pull-парсеры также используют меньше памяти, чем DOM, но они в дополнение дают приложению больший контроль над процессом синтаксического анализа, чем SAX-парсеры.

Пример приложения выглядит точно так же, как тот, который мы рассмотрели при разборе ответов JSON. Поэтому перейдем к исходному коду этого приложения.

Рассмотрим сразу класс HTTPGetTask. Метод doInBackground похож на тот, что мы видели ранее. Но теперь он использует класс XML response handler для обработки ответа. Ключевым методом в этом классе является метод handleResponse, он начинается с создания объекта PullParser.




Затем код устанавливает вход парсера в качестве XML-документа, который был возвращен телом HTTP-ответа. После этого код получает первое событие парсера и затем начинает перебирать XML-документ.



Внутри цикла while есть 3 события, наличие которых этот код проверяет: стартовый XML-тег, конечный XML-тег и содержимое элемента. После определения какое событие наступило, происходит вызов соответствующего метода.

Вызывается метод startTag, в качестве параметра получая элемент, который начинается. Этот метод идентифицирует, является ли полученный элемент данных тем, который необходимо сохранить, и если это так, он сохраняет его, задавая значения определенным переменным.



Метод endTag получает в качестве параметра заканчивающий элемент. И этот метод так же определяет, является ли полученный элемент данных тем, который должен быть сохранен, и если это так, он его сохраняет. Кроме того, если это конечный тег землетрясения, тогда в список результатов добавляется результирующая строка для этой части данных землетрясения.



Когда событие является контентом, вызывается метод text. В качестве параметра передается содержимое элемента. Этот метод определяет, какой тег в настоящее время обрабатывается, и сохраняет содержимое для последующего использования.



После завершения метода doInBackground в основной Activity, как и в предыдущих примерах, вызывается метод onPostExecute c результатом, переданным в качестве параметра.



Этот метод создает и устанавливает адаптер списка для вывода на экран, передавая в качестве параметра результирующий список, который был вычислен при работе метода handleResponse.

И последнее. Чтобы ваше приложение могло работать с интернетом, ему необходимо предоставить соответствующее разрешение:


Broadcast Receivers – приемники широковещательных сообщений

BroadcastReceiver – базовый класс для кода, который получает и обрабатывает рассылки (сообщения, упакованные в Intent), отправленные методом sendBroadcast (Intent) для компонентов, целью которых является ожидание определенных событий, чтобы принимать эти события и реагировать на них. И способ, которым все это работает, состоит в том, что отдельные широковещательные приемники регистрируются для получения конкретных событий, в которых они заинтересованы.

Например, в Android есть широковещательный приемник, задачей которого является прослушивание входящих SMS-сообщений. Затем где-то в еще, некий компонент совершает какое-то действие, о котором он хочет сообщить вещательным приемникам, например отправить SMS. Тогда он создает интент, представляющий это событие, и передает этот интент, как будто в радиоэфир. Когда Android получит широковещательный интент, содержащий SMS-сообщение, он проверяет какие службы (или приложения) зарегистрированы в системе на его получение, тогда в них происходит вызов метода onReceive, где интент присутствует в качестве одного из параметров.

Итак, первое – широковещательный приемник должен быть зарегистрирован для получения конкретных интентов. Во-вторых, какой-либо компонент генерирует интент и передает его в систему. В-третьих, Android доставляет этот интент получателям широковещательных сообщений, которые зарегистрированы для его получения. И четвертое – в приемниках затем происходит вызов их метода onReceive, в котором они и обрабатывают входящее событие.

Теперь поговорим о каждом из этих шагов по порядку. Для регистрации широковещательного приемника у разработчиков есть два варианта. Первый, они могут статически зарегистрировать широковещательный приемник, помещая информацию о нем в файл AndroidManifest. xml приложения, которому принадлежит широковещательный приемник. И второй, они могут регистрировать широковещательный приемник динамически, вызывая определенные методы во время выполнения программы.

Чтобы зарегистрировать широковещательный приемник статически, необходимо добавить в манифест тег «receiver», и затем внутри этого тега необходимо поместить по крайней мере один тег интент-фильтра. По содержимому интент-фильтра Android и определяет, соответствует ли полученный интент этому широковещательному приемнику. Формат тега выглядит примерно так.



Вначале стоит ключевое слово receiver, а затем добавляются некоторые из следующих атрибутов.

android: enabled позволяет включать или отключать определенный приемник.

android: exported, если установлено значение true, этот приемник может принимать широковещательные передачи от других приложений, в то время как если он установлен в значение false, то только те интенты, которые передаются другими компонентами внутри приложения.

android: name дает имя класса, реализующего этот приемник.

android: permission определяет строку разрешения, которое отправитель интента должен иметь, чтобы этот приемник получил интент от них. Как уже говорилось, необходимо указать хотя бы один тег интент-фильтра, которые были рассмотрены в главе Permissions. Теги этого интент-фильтра так же могут указывать на действия (action), данные (data) и категории (categories).

Если регистрировать приемник статически, эта информация будет считана и обработана при установке приложения и во время каждой загрузки системы. Рассмотрим приложение, которое статически регистрирует один широковещательный приемник, который получает пользовательский интент, называемый show toast intent. Это приложение отображает одну кнопку с надписью «Broadcast Intent». Нажатие этой кнопки вызывает отправку интента, а затем его прием широковещательным приемником, который выводит на экран тост-сообщение.



Теперь откроем основную Activity. Этот код сначала определяет строку – действие интента, которая будет использоваться для идентификации этого интента.



Далее идет «слушатель» кнопки, который вызывает метод sendBroadcast, передавая в интенте строку разрешения.



Этот интент будет сопоставлен с зарегистрированными в системе интент-фильтрами. Строка разрешения custom_intent указывает, что этот интент может быть доставлен только тем приемникам широковещательной передачи, у которых есть конкретно это разрешение.



Вы также можете программно регистрировать широковещательные приемники во время выполнения программы, например, если хотите, чтобы ваш широковещательный приемник реагировал только тогда, когда Activity находится на переднем плане. Тогда вы можете динамически регистрировать и отменять регистрацию приемников непосредственно в Activity, например в методах onResume и onPause.

Для этого сначала необходимо создать объект интент-фильтра, указав интенты, которые вы хотите зарегистрировать. Затем необходимо создать широковещательный приемник и зарегистрировать его, вызвав метод registerReceiver. У этого метода есть различные реализации. Одна из них находится в классе LocalBroadcastManager и используется для трансляций внутри одного приложения. Другая реализация находится в классе Context и используется для трансляции интентов по всей системе. Таким образом, эти интенты могут быть получены любым приложением на устройстве. Затем, в случае необходимости, можно вызвать метод unregisterReceiver, чтобы отменить регистрацию этих широковещательных приемников.

Рассмотрим исходный код приложения с динамической регистрацией. Это приложение выглядит так же, как и предыдущее приложение. Есть кнопка «Broadcast Intent» и при её нажатии, транслируется интент. Широковещательный приемник получает этот интент, а затем отображает на экране тост-сообщение, но внутренне его реализация несколько отличается.

Этот код начинается с создания строки действия интента, а затем создается интент-фильтр с только что созданной строкой действия. После этого создается экземпляр широковещательного приемника, называемый receiver. А затем в методе onCreate код получает экземпляр менеджера LocalBroadcastManager, который используется для трансляции и получения интентов в рамках только этого приложения. Затем код использует этого менеджера, чтобы зарегистрировать приемник интента, показывающего тост-сообщение.



И после этого, если нажата кнопка Broadcast Intent, «слушатель» кнопки вызывает метод sendBroadcast менеджера, передавая интент как параметр.



Когда кнопка нажата, менеджер отправляет интент объекту-приемнику, который работает так же, как в предыдущем приложении, создавая и отображая тост-сообщение.

До сих пор наш пример просто передавал один интент одному приемнику. Но Android поддерживает и множество других способов, с помощью которых можно транслировать интенты. Например, интенты могут транслироваться нормально или по очереди.

Нормальная широковещательная передача доставляется подписанным широковещательным приемникам в неопределенном порядке. Таким образом, если у вас есть два широковещательных приемника, которые должны получить один интент, то возможно, что оба приемника смогут обработать этот интент одновременно.

Упорядоченная широковещательная передача, с другой стороны, доставляет интент нескольким широковещательным приемникам по одному в приоритетном порядке.

Трансляции также могут быть липучими или нелипучими. Липучий интент, после того как был транслирован, «крутится поблизости». Таким образом, широковещательный приемник, который был зарегистрирован позже произошедшей трансляции интента, все равно сможет принять его. Эта функция полезна, например, для записи изменений состояния системы, таких как, изменения уровня заряда батареи или состояния зарядки. В этих случаях для приемников не имеет значения, когда состояние изменилось, а только то, в каком текущем состоянии находится система.

Нелипучие трансляции после их первоначальной трансляции отменяются. Эти трансляции больше подходят для сообщения о том, что произошло определенное событие. В этих случаях, если приемник не был зарегистрирован для приема широковещательной передачи до того как она произошла, тогда он и не получит её.

И, наконец, как видно в примерах, некоторые методы трансляции также принимают строковый параметр – разрешение. Это ограничивает широковещательную рассылку теми приемниками, которые имеют указанное разрешение.

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

Другое – использовать инструмент ADB, чтобы узнать, какие широковещательные приемники были зарегистрированы. Можно использовать команду dumpsys для отображения широковещательных приемников, которые зарегистрированы динамически:



Или чтобы показать те, которые зарегистрированы статически:



Теперь, после того, как интент передан, он будет доставлен соответствующему широковещательному приемнику путем вызова его метода onReceive. Этот метод имеет два параметра. Один – Context, в котором работает приемник, и два – интент, который был передан. Поэтому при написании кода, который обрабатывает входящие трансляции, следует учитывать некоторые вещи.

Во-первых, для доставки широковещательной передачи, возможно, системе придется запустить процесс приложения приемника, потому что во время передачи интента он может не работать. И пока onReceive запущен, этот процесс будет иметь высокий приоритет. Таким образом, вещание интента, особенно если оно направлено нескольким приложениям, может быть относительно ресурсоёмкой операцией.

Во-вторых, метод onReceive запускается в главном потоке процесса, следовательно, он должен работать кратковременно, чтобы не блокировать основной поток. В частности, если обработка, которую необходимо сделать в ответ на широковещательную рассылку, занимает много времени, следует подумать о запуске сервиса (нового потока) для этой работы, вместо того, чтобы выполнять её в onReceive.

Фактически, именно это делает приложение SMS, когда приходит SMS-сообщение. Широковещательный приемник принимает широковещательную рассылку и в своем методе onReceive, он немедленно передает это сообщение другой службе, которая проделает всю работу по загрузке сообщения, сохранению его в базе данных и т. д.

Последний вопрос, который следует учитывать, заключается в том, что широковещательный приемник считается действующим только до тех пор, пока запущен OnReceive. На самом деле, как только произойдет возврат из функции OnReceive, Android завершит работу вызвавшего её приемника. В частности, это означает, что широковещательный приемник не может запускать асинхронные операции, которые необходимо будет выполнить в более позднее время.

Рассмотрим несколько примеров приложений, использующих широковещательные приемники. Запустим приложение Compound Broadcast. На экране имеется кнопка, обозначенная «Broadcast Intent», которая при нажатии будет использовать метод sendBroadcast для трансляции интента ShowToast.



Однако на этот раз есть три широковещательных приемника, которые получат этот интент.

Если теперь нажать эту кнопку, ниже появится тост-сообщение от приемника 1, затем второе от приемника 2 и третье от приемника 3. Это происходит потому, что используемое приложение отправило широковещательную рассылку. Передачи рассылались нормально. Это означает, что порядок поступления и обработки данных не был определен. В этом случае вещание обрабатывалось в одном конкретном порядке. В других случаях или на другом устройстве, или если Android изменит свое состояние в будущем, этот порядок может отличаться.

Поэтому, если необходимо, чтобы широковещательные приемники принимали широковещательные передачи в определенном порядке или если необходимо, чтобы каждый широковещательный приемник имел в процессе эксклюзивный доступ к интенту, тогда придется сделать трансляцию упорядоченной. Это делается при помощи метода sendOrderedBroadcast или используя некоторые из методов класса Context. Первый отправляет интент для приемников, у которых есть указанное разрешение в порядке приоритета.



Второе, делает то же самое, но предоставляет дополнительные параметры для большего контроля.



Рассмотрим приложения, которые используют некоторые варианты метода sendOrderedBroadcasts. Приложение Compound Ordered Broadcast отображает кнопку с надписью «Broadcast Intent», и при нажатии этой кнопки, транслируется интент showToast.

У этого приложения есть три зарегистрированных широковещательных приемника: Receiver 1, Receiver 2 и Receiver 3. Все имеют разный приоритет для приема широковещательной передачи. Второй приемник имеет наивысший приоритет, следующим идет первый приемник, а третий приемник имеет самый низкий приоритет. Поэтому ожидается, что приемники получат широковещательную передачу в таком порядке: приемник два, приемник один, приемник три. Тем не менее, в первый приемник помещен некоторый код, который прерывает трансляцию. Таким образом, только приемник два, а затем приемник один должны получить широковещательную рассылку.

Рассмотрим, как это работает. При нажатии кнопки Broadcast Intent появляется тост-сообщение, что интент был получен приемником два, потом еще одно сообщение, что интент получен приемником один. А до бедного приемника три рассылка не дошла.

Рассмотрим исходный код этого приложения. Начнем с открытия файла manifest. xml. Видно, что Receiver2 статически зарегистрирован с приоритетом 10, а Receiver3 зарегистрирован с приоритетом 1.



Теперь перейдем в основную Activity. Код создает экземпляр Receiver1, затем создает интент-фильтр для интента show_toast, а затем присваивает приоритету значение три. Таким образом, любой экземпляр приемника Receiver2 имеет приоритет 10. Этот экземпляр приемника Receiver1 имеет приоритет 3. А приемник три в качестве приоритета имеет 1.

Внимание! Это не конец книги.

Если начало книги вам понравилось, то полную версию можно приобрести у нашего партнёра - распространителя легального контента. Поддержите автора!

Страницы книги >> Предыдущая | 1 2
  • 0 Оценок: 0

Правообладателям!

Данное произведение размещено по согласованию с ООО "ЛитРес" (20% исходного текста). Если размещение книги нарушает чьи-либо права, то сообщите об этом.

Читателям!

Оплатили, но не знаете что делать дальше?


Популярные книги за неделю


Рекомендации