Главная » Разработка для Android » ДОБАВЛЕНИЕ ДОПОЛНИТЕЛЬНОЙ СЕТЕВОЙ ПОДДЕРЖКИ

0

Вопросы, рассматриваемые в этом часе:

•     получение доступа к информации о телефонии;

•     использование клиентских НТТР-сервисов;

•     отправка GET-запросов по протоколу HTTP;

•     отправка POST-запросов по протоколу HTTP;

•     добавление в ваш проект JAR-файлов сторонних разработчиков;

•     работа с составными MIME-сообщениями.

В этом часе вы расширите функционал приложения «Been There, Done That!», добавив возможность выгружать данные игрока, включая его настройки, результат игры и аватар, на сервер приложения. Вы также узнаете, как можно получить доступ к информации о статусе телефонии мобильного устройства. Наконец, вы добавите несколько внешних библиотек в Android- проект и будете работать с составными MIME-сообщениями.

ОПРЕДЕЛЕНИЕ ДАННЫХ ДЛЯ ОТПРАВКИ НА СЕРВЕР

До сих пор в приложении «Been There, Done That!» вы только загружали данные с сервера. Теперь настало время выгрузить информацию об игроке на сервер приложения. Для этого вам нужно познакомиться с возможностями HTTP-клиента Apache, доступного на платформе Android, и узнать о том, как добавлять дополнительные библиотеки Apache в проект.

Выгружать данные на сервер приложения должны три части приложения «Been There, Done That!»:

•     QuizSettingsActivity — этот класс должен создавать запись игрока на сервере приложения и выгружать информацию о настройках данного игрока.

•     QuizGameActivity — этот класс должен выгружать результаты игры Для данного игрока.

•     QuizSettingsActivity — этот класс должен выгружать изображение аватара.

Чтобы приложение "Been There, Попе Thai!» могло работать с данными в реальном режиме времени, нам потребуется как доступ к серверу приложения. так и добавление соответствующей сетевой функциональности в клиентское Android -приложение.

КСТАТИ __________________________________________________________________

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

ПОЛУЧЕНИЕ ИНФОРМАЦИИ О СОСТОЯНИИ ТЕЛЕФОНА

Некоторые настройки игрока приложения «Been There, Done That!» будут выгружаться на сервер приложения. Сервер приложения должен иметь возможность определить, с каким игроком (или устройством) он взаимодействует в настоящий момент. По этой причине приложение использует уникальный идентификатор мобильного устройства каждого игрока для отличия игроков друг от друга. Чтобы получить этот уникальный идентификатор, вам потребуется обратиться к информации, предоставляемой классом TelephonyManager.

Помимо разнообразных библиотек для работы с сетевыми возможностями, которые дос­тупны в инструментарии Android SDK и были рассмотрены ранее, вы также можете полу­чить информацию о состоянии телефона и телефонии, используя класс TelephonyManager. Класс TelephonyManager позволяет Android-приложению получать информацию об используемой сотовой сети, подключении, модуле идентификации абонента (SIM — Subscriber Identity Module), а также о самом мобильном устройстве.

ВНИМАНИЕ! ______________________________________________________________

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

Настройка разрешений для получения информации о состоянии телефона

Для получения информации о состоянии телефона Android-приложение должно иметь соответствующие разрешения, устанавливаемые в файле манифеста Android. Android- приложение может получать или изменять информацию о состоянии телефона только в том случае, если в элементе <uses-permission> файла манифеста Android будут указаны необходимые значения.

Ниже перечислены наиболее часто используемые значения разрешений 0я приложений, работающих с информацией о состоянии телефона:

•     android.permission.READ_PHONE_STATE

•     android.permission.MODIFY_PHONE_STATE

Получение информации о телефонии

Разработчики могут использовать класс TelephonyManager(android.telephony. TelephonyManager) для получения информации о состоянии сети на устройстве про­граммным путем. Получить экземпляр класса TelephonyManager можно при помощи знакомого вам метода getSystemService () объекта типа Context приложения:

TelephonyManager telMgr = (TelephonyManager)

getSystemService(Context.TELEPHONYSERVICE);

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

ПОЛУЧЕНИЕ ИНФОРМАЦИИ О СОСТОЯНИИ ЗВОНКА

Вы можете использовать класс TelephonyManager для определения состояния звонка сотового устройства при помощи метода getCallstate () . Этот метод сообщает, нахо­дится ли телефон в состоянии готовности, ожидает ли ответа абонента на вызов или же в настоящий момент принимает входящий звонок.

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

ПОЛУЧЕНИЕ ИНФОРМАЦИИ О ПРОТОКОЛЕ СЕТИ

Вы можете воспользоваться классом TelephonyManager для запроса информации об используемом протоколе сотовой сети при помощи метода getNetworkType () . Этот метод сообщит вам о том, какой протокол используется в текущий момент на устройстве, например, GPRS, EDGE или EVDO. Эти и многие другие протоколы сети определены в виде констант в классе TelephonyManager (например, NETWORK_TYPE_GPRS).

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

ОПРЕДЕЛЕНИЕ ПОДДЕРЖИВАЕМОГО ТЕЛЕФОНОМ СТАНДАРТА: СDМА ИЛИ GSM

ПОЛУЧЕНИЕ ИНФОРМАЦИИ О SIM-KAPTE

Вы можете использовать метод getPhoneType () класса TelephonyManager, чтобы определить, какой стандарт поддерживается мобильным устройством: CDMA или GSM. Более того, вы можете получить уникальный идентификатор мобильного телефона при помощи метода getDeviceId() . Этот метод возвращает IMEI-идентификатор для GSM- телефонов и MEID-идентификатор для CDMA-телефонов. Вы также можете получить уникальный идентификатор абонента (например, IMSI-идентификатор для абонентов GSM-сетей), используя метод getSubscriberId() .

ПОЛУЧЕНИЕ ИНФОРМАЦИИ О SIM-КАРТЕ

Класс TelephonyManager предоставляет ряд методов для получения информации о SIM- карте и соответствующем операторе сотовой связи. Вот некоторые из этих методов:

getSimState () — этот метод возвращает состояние SIM-карты, например, вставлена ли SIM-карта в мобильное устройство, заблокирована ли она (т. е. необходимо ввести PIN- код) или готова к использованию.

getSimSerialNumber () — этот метод возвращает уникальный серийный номер SIM- карты.

getSimOperatorName () — этот метод возвращает имя оператора для данной SIM- карты.

getSimOperator () — этот метод возвращает мобильный код страны и код сети для оператора, выпустившего данную SIM-карту.

ПОЛУЧЕНИЕ ИНФОРМАЦИИ О ГОЛОСОВОЙ ПОЧТЕ УСТРОЙСТВА

Вы можете использовать класс TelephonyManager для получения информации о голосовой почте пользователя телефона. Например, вы можете получить телефонный номер для доступа к голосовой почте при помощи метода getVoiceMailNumber () .

ПОЛУЧЕНИЕ ИНФОРМАЦИИ О РОУМИНГЕ

В часе 15 было рассмотрено, как можно получить информацию о роуминге, используя сетевые сервисы. Вы также можете определить, находится ли абонент в роуминге, используя метод isNetworkRoaming() класса TelephonyManager. Этот подход не позволяет с уверенностью сказать, что пользователь будет нести дополнительные расходы за передачу данных или телефонные звонки, но такая вероятность есть. Приложение может использовать эту информацию, чтобы запросить разрешение у пользователя на передачу данных по сети, находясь в роуминге, отобразив сообщение наподобие следующего: «Ваш телефон находится в роуминге. Вы хотите продолжить?»

ПОЛУЧЕНИЕ ДРУГОЙ ИНФОРМАЦИИ, ОТНОСЯЩЕЙСЯ К ТЕЛЕФОНИИ

ЗНАЕТЕ ЛИ ВЫ, ЧТО… ____________________________________________________

Вы можете использовать класс SmsManager (android.telephony.SmsManager) и класс SmsMessage (android.telephony.SmsMessage) для отправки SMS-сообщений.

ВЫГРУЗКА ДАННЫХ НА УДАЛЕННЫЙ СЕРВЕР ПРИЛОЖЕНИЯ

В часе 10 вы создали экран с настройками и использовали для хранения введенных пользователем данных экземпляр класса SharedPreferences. Теперь вы измените класс этого экрана таким образом, чтобы копия настроек игрока выгружалась на сервер (помимо хранения этих настроек в экземпляре класса SharedPreferences). Благодаря этой реализации клиентское устройство будет всегда иметь последнюю версию данных. Сервер приложения просто сохраняет копию настроек. В этом конкретном приложении отсутствует двухсторонняя синхронизация; рассмотрение этой темы выходит за рамки данной книги и для ее объяснения потребовалось бы больше часа времени.

КСТАТИ __________________________________________________________________

Чтобы упростить понимание кода и продемонстрировать важную сетевую функциональ­ность, мы позволили себе некоторые вольности в отношении архитектуры приложения и не всегда использовали сетевые возможности максимально эффективно. Тем не менее примененные нами подходы позволяют продемонстрировать важный функционал, напри­мер фоновое обновление данных, индикаторы хода выполнения процесса и другие воз­можности класса AsyncTask.

Для взаимодействия с сервером приложения вы можете использовать пакет HttpClient (org.apache.http), включенный в состав инструментария Android SDK. Этот пакет предоставляет классы для реализации большого числа сценариев сетевого взаимодействия по протоколу HTTP в вашем приложении.

Вы узнаете, как использовать класс HttpGet для отправки переменных запроса аналогично тому, как происходит отправка веб-формы с применением GET-метода протокола HTTP. Затем вы познакомитесь, как использовать класс HttpPost для отправки переменных запроса и выгрузки изображения аватара аналогично тому, как происходит отправка веб- формы с применением POST-метода протокола HTTP.

Сервер приложения был написан с прицелом на обычные веб-формы языка HTML. Фактически, до того, как был написан Android-клиент, тестирование сервера производилось с использованием стандартной HTML-формы.

Еели вы разработаете веб-клиента раньше, чем будет разработан Android-клиент, вы сможете убедиться, что протоколы взаимодействия между клиентом и сервером стандартные и кроссрпатформенные. Используя эту процедуру, вы будете знать, что любая платформа — включая платформу Android, способная использовать GET- и POST- методы для отправки данных формы, будет совместима с данным сервером приложения. В этом случае приложение может использовать библиотеки Apache HTTP — в основном, пакет org. apache . http . clien t.

КСТАТИ __________________________________________________________________

Код сервера приложения, используемого в этой книге, доступен в папке /Книга/ Сервер на прилагаемом к книге диске.

ВНИМАНИЕ! ______________________________________________________________

Сетевые операции, связанные с выгрузкой данных на сервер, могут занимать некоторое время. Поэтому вызовы всех методов, подразумевающих работу с сетью, должны выпол­няться асинхронно, отдельно от основного потока, управляющего пользовательским интерфейсом. Это можно сделать при помощи класса Thread платформы Java или при по­мощи класса AsyncTask платформы Android. Также обязательно предупреждайте поль­зователя о длительных операциях, используя, например, элемент ProgressBar. Допол­нительную информацию можно найти в часе 15.

Выгрузка данных игрока при помощи GET-метода протокола HTTP

Отправка данных игрока на сервер приложения посредством GET-метода протокола HTTP осуществляется с использованием класса HttpGet. Поскольку вы отправляете переменные запроса, нужно использовать вспомогательный класс URLEncodedUtils вместе с экземпляром класса List, содержащим объекты типа BasicNameValuePair, что поможет сформировать окончательный адрес URL для данного запроса. Наконец, вся процедура взаимодействия с сетью должна быть представлена в виде объекта типа AsyncTask, чтобы пользовательский интерфейс мог продолжать реагировать на действия пользователя в то время, пока будет обрабатываться сетевой запрос.

СОЗДАНИЕ КЛАССА ASYNCTASK, ПРЕДНАЗНАЧЕННОГО ДЛЯ ВЫГРУЗКИ ДАННЫХ

Для выгрузки информации о настройках пользователя на сервер приложения вам потребу­ется добавить еще один класс AccountTask, производный от класса AsyncTask, в класс QuizSettingsActivity. Класс AccountTask может выполняться в результате вызова метода execute () при каждом изменении значения на экране с настройками (рис. 16.1). Вы также можете выполнять эту задачу при первом запуске приложения пользователем, чтобы настроить уникальный идентификатор игрока на сервере приложения для данного игрока на данном устройстве, даже если пользователь не ввел свой ник или адрес электронной почты. Вы также можете получить значения настроек с сервера (путем использования двухсторонней синхронизации).

Рис. 16.1 Использование индикатора непрерывного хода выполнения процесса в верхнем правом углу строки меню (анимированный круг)

Реализация произвольного класса AccountTask во многом похожа на другие произвольные классы, унаследованные от класса AsyncTask, над которым вы работали на протяжении последних двух часов. (В следующем примере для простоты понимания и краткости был удален код, обрабатывающий исключения.) Здесь заслуживает внимания метод doInBackground (), в котором происходит передача настроек игрока на сервер приложения:

@Override

protected Boolean doInBackground(Object… params) { Boolean succeeded = false;

Integer playerId =

mGameSettings.getInt(GAME_PREFERENCES_PLAYER_ID, -1); String nickname =

mGameSettings.getString(GAME_PREFERENCES_NICKNAME, ""); String email =

mGameSettings.getString(GAME_PREFERENCES_EMAIL, ""); String password =

mGameSettings.getString(GAME_PREFERENCES_PASSWORD, ""); Integer score =

mGameSettings.getInt(GAME_PREFERENCES_SCORE, -1); Integer gender =

mGameSettings.getInt(GAME_PREFERENCES_GENDER, -1); Long birthdate =

mGameSettings.getLong(GAME_PREFERENCES_DOB, 0); String favePlaceName =

mGameSettings.getString( GAME_PREFERENCES_FAV_PLACE_NAME, "");

Vector<NameValuePair> vars = new Vector<NameValuePair>();

if (playerId == -1) {

TelephonyManager telManager =

Using an indeterminate

progress indicator

in the top

right of the

menu bar (faint

circle).

(TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); String uniqueId = telManager.getDeviceId(); vars.add(new BasicNameValuePair("uniqueId", uniqueId));

} else {

vars.add(

new BasicNameValuePair("updateId", playerId.toString())); vars.add(

new BasicNameValuePair("score", score.toString()));

}

vars.add(new BasicNameValuePair("nickname", nickname)); vars.add(new BasicNameValuePair("email", email)); vars.add(new BasicNameValuePair("password", password)); vars.add(new BasicNameValuePair("gender", gender.toString())); vars.add(new BasicNameValuePair("faveplace", favePlaceName)); vars.add(new BasicNameValuePair("dob", birthdate.toString()));

String url =

TRIVIA_SERVER_ACCOUNT_EDIT+ "?" + URLEncodedUtils.format(vars, null

HttpGet request = new HttpGet(url); ResponseHandler<String> responseHandler =

new BasicResponseHandler(); HttpClient client = new DefaultHttpClient();

String responseBody = client.execute(request, responseHandler);

if (responseBody != null && responseBody.length() > 0) { Integer resultId = Integer.parseInt(responseBody); Editor editor = mGameSettings.edit();

editor.putInt( GAME_PREFERENCES_PLAYER_ID, resultId);

editor.commit();

succeeded = true;

}

return succeeded; }

Пусть этот относительно большой фрагмент кода вас не обескураживает. На самом деле в нем нет ничего сложного: вы создаете вектор, состоящий из пар имя/значение для каждой отдельно взятой настройки игрока (сохраненных в экземпляре класса SharedPreferences), которые вы хотите передать на сервер.

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

Установив все необходимые переменные запроса, вы можете приступать непосредственно к генерации запроса. Для преобразования вектора переменных в GET-запрос вы можете использовать удобный метод URLEncodedUtils . format () . Наконец, вы инициализи­руете объект типа HttpGet, передаете в него сформированную строку GET-запроса и осуществляете отправку запроса при помощи экземпляра класса HttpClient.

Класс HttpClient предоставляет вспомогательные инструменты в виде классов ResponseHandler для разбора ответа от сервера. В данном случае класс BasicResponseHandler используется для простого получения типа String. В этом случае объект типа String содержит уникальный идентификатор игрока, который может быть сохранен в экземпляре класса SharedPreferenees для дальнейшего использования.

кстати _____________________________________________________________________________

В большинстве случаев следует избегать отправки конфиденциальных данных по сети в открытом виде. Например, идентификатор устройства может быть использован злоумыш­ленником в выгодных для него целях. Поскольку все, что нужно для данного приложения, — это некий уникальный, но многократно отправляемый на сервер идентификатор, вы можете использовать однонаправленную хеш-функцию, например, алгоритм Secure Hash Algorithm (SHA), для криптозащиты идентификатора устройства. Класс Mes- sageDigest, являющийся частью пакета java. security, предоставляет необходимую функциональность:

MessageDigest sha = MessageDigest.getlnstance("SHA" ); byte[] enc = sha.digest(uniqueId.getBytes());

В полной реализации данного примера, которую можно найти на диске, прилагаемом к данной книге, на сервер происходит отправка хешированного значения.

ВЫГРУЗКА ИНФОРМАЦИИ О НАБРАННЫХ ОЧКАХ ИГРОКА

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

Вы можете просто добавить информацию о набранных очках игрока в виде переменной запроса, отправляемого на сервер из метода doInBackground() класса QuizTask. Для этого используется следующий код:

SharedPreferences settings =

getSharedPreferences(GAME_PREFERENCES, Context. MODE_PRIVATE); Integer playerld = settings.getInt(GAME_PREFERENCES_PLAYER_ID, -1); if (playerld != -1) {

Log. d(DEBUG_TAG, "Updating score");

Integer score = settings.getInt(GAME_PREFERENCES_SCORE, -1); if (score != -1) { pathToQuestions +=

"&updateScore=yes&updateId="+playerId+"&score="+score;

}

}

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

ЗНАЕТЕ ЛИ ВЫ, ЧТО… _____________________________________________________

Вы также могли бы использовать контейнер типа List, содержащий объекты типа

BasicNameValuePair, вместе с методом URLEncodeUtils . format () . Тем не менее для простых значений, например целых чисел, дополнительное кодирование не требуется.

Выгрузка аватаров пользователей при помощи POST-метода протокола HTTP

Для выгрузки двоичных данных, например изображения аватара, вместо GET-запроса вам потребуется воспользоваться POST-запросом протокола HTTP. Это позволяет отправлять изображение аватара наподобие того, как происходит отправка файлов при использовании обычной веб-формы языка HTML. Сервер приложения затем может обработать POST- запрос соответствующим образом и сохранить копию аватара игрока (рис. 16.2).

Рис. 16.2. Выгрузка аватара

ВНИМАНИЕ! ______________________________________________________________

При сохранении данных непримитивных типов принимайте во внимание лучшие практики построения хранилищ данных, используемых вашим сервером приложения. Например, при программировании SQL-ориентированных баз данных принято хранить в базе данных адреса изображений, но не их содержимое (в виде значения типа BLOB).

ДОБАВЛЕНИЕ JAR-ФАЙЛОВ В ВАШ ANDROID-ПРОЕКТ

В идеальном случае для выгрузки изображения аватара и другой важной информации на сервер приложения в виде составного MIME-сообщения удобно использовать класс HttpClient. Тем не менее, на момент написания данной книги поддержка класса Apache HttpClient в инструментарии Android SDK была неполной. Инструментарий Android SDK пока еще не имеет поддержки составных MIME-сообщений, но высока вероятность, что этот функционал появится в одной из будущих версий инструментария SDK. Пока же, если вы хотите добавить поддержку составных MIME-сообщений, необходимо включить несколько библиотек Apache в ваш проект в виде JAR- файлов. В частности, нужно добавить следующие JAR-файлы в ваш проект:

•            Mime4j (james.apache.org/mime4j/index.html);

•            HttpMime 4.0 (hc.apache.org/httpcomponents-client-ga/httpmime/index. html);

•             Apache Commons 10 (commons.apache.org/io/).

КСТАТИ __________________________________________________________________

Все вышеперечисленные библиотеки можно найти на компакт-диске, прилагаемом к дан­ной книге, в папке /Книга/Час 15 и 16/libs.

ЗНАЕТЕ ЛИ ВЫ, ЧТО… _____________________________________________________

Не знаете, что такое составные MIME-сообщения? Отличное описание доступно на сайте Wikipedia: en.wikipedia.org/wiki/MIME#Multipart_messages. По существу, составное MIME-сообщение — это способ представления нескольких фрагментов данных, включая бинарные данные, в виде одного текстового сообщения. Для генерации составных MIME- сообщений при помощи HTML-формы атрибут enctype тега form должен быть установлен в значение multipart/form-data. Использование составных MIME-сообщений не ограничено только протоколом HTTP. Например, составные MIME-сообщения часто применяются в электронной почте.

ВЫПОЛНИТЕ САМОСТОЯТЕЛЬНО

ДОБАВЛЕНИЕ JAR-ФАЙЛА В ANDROID-ПРОЕКТ ______________________

Чтобы добавить JAR-файл в Android-проект, выполните следующие шаги:

1.                                 Загрузите JAR-файл(ы), который вы хотите включить в ваш проект.

2.                                  Создайте каталог с именем /libs в вашем проекте. Эта папка должна находиться на том же уровне, что и папки /src и /res.

3.                                 Скопируйте JAR-файлы) в каталог/libs.

4.                                     В меню среды разработки Edipse выберите команду Project=>Properties (Проект => Свойства), чтобы открыть диалоговое окно со гвАисгвами вашего Android- проекта. Выберите категорию Java Build Path (Путь сборки Java) в левой части диалогового окна и откройте вкладку Libraries (Библиотеки).

5.                                     Нажмите на кнопку Add JARs (Добавить JAR-файлы) и в открывшемся диалоговом окне JAR Selection (Выбор JAR-файлов) выберите JAP-файлы, которые вы хотите добавить в проект. Нажмите на кнопку ОК.

6.                                     При необходимости обновите проект. Теперь вы можете приступать к программированию!

Чтобы добавить полнофункциональную поддержку составны/ MIME-сообщений в приложение «Been There, Done That!», вы должны добавить все три JAR-фэйла, перечисленных выше. Эти пакеты также содержат другие полезные инструменты, например, класс lOUtils, который предоставляет ряд удобных методов для работы с потоками данных.

СОЗДАНИЕ КЛАССА ASYNCTASK ДЛЯ ВЫПОЛНЕНИЯ ВЫГРУЗКИ ИЗОБРАЖЕНИЯ АВАТАРА

Для выгрузки изображения аватара на сервер приложения вам потребуется добавить класс QuizSettingsActivity еще один класс ImageUploadTask, производный от класса AsyncTask. Выполнение методов класса imageUploadTask может быть запушено с использованием метода execute () при каждом изменении игроком изображения аватара на экране с настройками.

Реализация класса ImageUploadTask очень похожа на реализацию других классов, производных от класса AsyncTask, которые были написаны в течение последних двух часов. Единственный действительно интересный момент в этой новой задаче — код метода doInBackground(), осуществляющий выгрузку файла аватара на сервер (из кода для простоты понимания и краткости удалена обработка исключений):

@Override

protected Boolean doInBackground(Object… params) { String avatar =

mGameSettings.getString(GAME_PREFERENCES_AVATAR, ""); Integer playerld =

mGameSettings.getInt(GAME_PREFERENCES_PLAYER_ID, -1);

MultipartEntity entity =

new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); File file = new File(avatar); FileBody encFile = new FileBody(file); entity.addPart("avatar", encFile);

entity.addPart("updateId", new StringBody(playerId.toString()));

HttpPost request = new HttpPost( TRIVIA_SERVER_ACCOUNT_EDIT); request.setEntity(entity);

HttpClient client = new DefaultHttpClient(); ResponseHandler<String> responseHandler =

new BasicResponseHandler(); String responseBody = client.execute(request, responseHandler);

if (responseBody != null && responseBody.length() > 0) { Log. w(DEBUG_TAG,

"Unexpected response from avatar upload: " + responseBody);

}

return null;

}

Вам потребуется создать составной MIME-объект, аналогичный MIME-объектам, создаваемым браузерами, при помоши класса MultipartEntity, и добавить в него две части: одна часть будет представлять содержимое файла аватара, а другая — уникальный идентификатор игрока, которому принадлежит данный аватар. Далее вы генерируете объект типа HttpPost с адресом URL сервера приложения. Наконец вы передаете созданный MIME-объект в объект типа HttpPost, используя метод setEntity(). Чтобы отправить запрос на сервер и получить ответ, вы, как обычно, используете классы HttpClient и ResponseHandler.

ИТОГИ

В этом часе вы изменили приложение «Been There, Done That!» таким образом. чтобы оно могло выгружать данные игры, включая настройки игрока, изображение аватара и набранные очки, на удаленный сервер приложения. Также вы узнали, как получать информацию, относящуюся к телефонии, например, информацию об используемой сотовой сети и информацию о нахождении абонента в роуминге, при помощи класса TelephonyManager. Кроме того, было рассмотрено использование GET- и POST-методов протокола HTTP для выгрузки данных на сервер при помощи класса HttpClient.

ВОПРОСЫ И ОТВЕТЫ

Вопрос: Как можно избежать передачи данных пользователя по сети в открытом виде?

Ответ: Существует множество способов защитить данные пользователя в процессе передачи по сети. Например, вы можете зашифровать все данные, передаваемые по протоколу Н П Р, с использованием крипшрафиче- ского протокола SSL (протокол HTTPS представляет собой расширение протокола HTTP, поддерживающее шифрование). Пароли которые уже были отправлены по защищенному каналу, в дальнейшем могут отправ­ляться в хешированном виде с использованием класса MessageDigest.

Вопрос: На платформе Android доступна поддержка формата JSON (JavaScript Object Notation)?

Ответ: Да, библиотеки, предназначенные для работы с форматом JSON. доступны в пакете org. json, входящем в состав инструментария Android SDK,

ПРАКТИКУМ Контрольные вопросы

1.                                  Какие из перечисленных ниже сведений может предоставить класс

TelephonyManager?

A.                                Состояние звонка.

B.                                Используемая сотовая сеть.

C.                                Имя абонента.

2.                                   Верно ли это? Инструментарий Android SDK предоставляет полнофунк­циональную поддержку составных MIME-сообщений.

3.                                 Верно ли это? Сетевые операции всегда должны выполняться в потоке, управляющем пользовательским интерфейсом, поскольку эти операции очень быстрые.

4.                                 Какие из нижеперечисленных классов или объектов не могут быть ис­пользованы для выполнения задач в фоновом режиме?

A.                               BackgroundTask.

B.                                AsyncTask.

C.                                Thread.

D.                               AsyncActivity.

Ответы

А и B. Класс TelephonyManager позволяет получать информацию о состоянии звонка и об используемой сотовой сети.

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

Неверно. Операции, дли выполнения которых фебуетси некоторое время. например сетевые онераиин. никогда не должны выполнять в потоке. управляющем пользовательским ина’рфейсом, чтобы мобильный телефон мог оперт ивно реагировать на действия пользователя.

A и D. Фактически класс AsyncTask — это вспомогательный класс, который упрощает использование класса Thread. Использоваться могут оба класса. Два других класса не входят в состав инструментария SDK, а может и не существуют вовсе.

относящееся к вопросу), при этом для обработки данных изображения может использоваться тот же подход, который применялся для обработки данных изображения аватара (как было рассмотрено ранее в этом часе).

Литература: Дэрси JI., Android за 24 часа. Программирование приложений под операционную систему Google/ ДэрсиЛ., КондерШ. — М.: Рид Групп, 2011. — 464 с. — (Профессиональные компьютерные книги). ISBN 978-5-4252-0318-2

По теме:

  • Комментарии