- •Содержание
- •1.1 Тенденции развития технологий разработки приложений 8
- •Введение
- •Тенденции развития технологий разработки приложений
- •Описательная постановка задачи
- •Формальная постановка задачи
- •Декомпозиция задачи
- •Проектирование системы
- •Основные требования, предъявляемые системе
- •Выбор инструментальных средств
- •Проектирование схемы функционирования системы
- •Перечень функциональности.
- •Моделирование структуры системы
- •Проектирование пользовательского интерфейса
- •Методика тестирования конечного продукта.
- •Реализация системы
- •Структура приложения.
- •Описание классов.
- •Описание реализаций основных функций приложения
- •Реализация пользовательского интерфейса
- •Результаты тестирования системы
- •Список использованных источников
Описание реализаций основных функций приложения
1. Взаимодействие с сервером.
Т.к. вся информация получается от сервера, то необходимо организовать метод взаимодействия с сервером, отправка запросов, получение и обработка ответов.
За отправку запросов к серверу отвечает отдельный класс Network. В этом классе содержатся статические методы, которые производят запросы.
Каждый отдельный запрос оформляется в виде метода, в котором необходимые параметры собираются в список пар «имя – значение». В каждый метод необходимо передать подпись пользователя authtoken, с помощью которого на сервере идентифицируется пользователь. Так же необходимо передать объект типа Handler, который отвечает за обработку ответа.
Например, так выглядит метод для получения списка доступных ЦРЗ:
public static void getDSList(String authtoken, Handler handler) {
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("m", "ds"));
params.add(new BasicNameValuePair("act", "myList"));
requestJSONAsync(baseurl, params, authtoken, handler);
}
После того, как все параметры для запроса собраны, они передаются статическому методу requestJSONAsync(), вместе с клиентской подписью и объектом-обработчиком. Кроме того, в этот метод передается URL сервера, к которому будет произведен запрос.
Запрос к серверу является долговременной операцией, поэтому, в версии ОС Android ниже 3.0, основной поток, в котором находятся все объекты управления интерфейса, будет заблокирован до тех, пор, пока запрос не выполнится. Кроме того, в версиях ОС Android 3.0 и выше, попытка произвести http-запрос приведет к аварийному завершению приложения с выбросом соответствующего исключения..
Исходя из этого, в методе requestJSONAsync() создается новый поток, в котором производится вызов метода requestJSON(). Этот метод вызывает метод requestString(), который производит http-запрос и возвращает ответ от сервера в виде строки. Далее эта строка преобразуется в объект JSON, который возвращается методом requestJSON(). Далее, если http-статус ответа 200 или 201, то созданный JSON-объект передаётся на обработку в объект-обработчик handler.
Объекты-обработчики нужны для того, чтобы при получении ответа, выбрать необходимую информацию и отобразить ее на экране. Т. к. http-запрос производится в отдельном потоке, то попытка изменить данные из этого потока в основном (например, изменить текст в метке) приведет к аварийному завершению приложения с выбросом соответствующего исключения. Специально для таких целей существуют объекты-обработчики handler. Handler создается в основном потоке (а значит является его частью), но при к нему можно обратиться из другого потока. Т. о. с помощью Handler один поток может «общаться» с другим.
На разные запросы, приходят разные ответы, поэтому для каждого запроса необходим свой объект-обработчик. Все классы таких объектов собираются в одном классе Handlers. Каждый объект-обработчик наследуется от класса Handler. Чтобы иметь доступ к компонентам интерфейса, в объектах-обработчиках сохраняется ссылка на Activity, в котором эти объекты были созданы. Обработка ответа производится в методе void handleMessage(), в который передается ответ в виде JSON-объекта.
2. Авторизация.
При запуске приложения запускается класс MyCrcActivity, который проверяет состояние авторизации пользователя и отображает список доступных ему ЦРЗ. В случае, если авторизация не производилась, то запускается класc LoginActivity, который производит запрос к серверу, передает ему имя пользователя и пароль, а в ответ получает специальную строку – пользовательскую подпись, с помощью которой на сервере идентифицируется пользователь.
Состояние авторизации определяется наличием строки клиентской подписи. Состояние авторизации должно сохраняться даже после того, как приложение будет завершено, это значит, что строку клиентской подписи надо хранить во внешнем файле. Для этого реализуются специальные методы, приведенные ниже.
void saveText(String name, String value) {
sPref = getPreferences(MODE_PRIVATE);
Editor ed = sPref.edit();
ed.putString(name, value);
ed.commit();
}
String loadText(String name) {
sPref = getPreferences(MODE_PRIVATE);
String savedText = sPref.getString(name, "");
return savedText;
}
Загрузка и сохранение строки происходит с помощью объекта SharedPreferences, доступ к которому получается с помощью метода getPreferences(MODE_PRIVATE). Константа MODE_PRIVATE означает, что сохраненные данные будут доступны только из этого приложения. Если при загрузке указать не существующую строку, то метод вернет пустую строку.
Если пользователь авторизован, то приложение делает запрос к серверу, получает список доступных ЦРЗ и выводит его на экран.
3. Сканер штрих-кодов.
Сканер штрих-кодов представлен отдельным классом Scanner. В этом классе организованна работа с камерой, получение изображения и его обработка.
Для получения изображения с камеры необходимы как минимум 4 объекта: Camera – объект, который предоставляет доступ к камере смартфона; SurfaceView – элемент интерфейса, на который выводится изображение с камеры; SurfaceHolder – объект-посредник между камерой и SurfaceView, отвечает за вывод изображения на SurfaceView; четвертый объект должен реализовать интерфейс SurfaceHolder.Callback. Этот интерфейс обязывает объект реализовать методы жизненного цикла SurfaceHolder, именно в этих методах запускается и останавливается вывод изображения.
Однако для обработки изображения в реальном времени этого недостаточно. Поэтому необходимо реализовать еще один интерфейс – Camera.PreviewCallback, в котором есть только один метод onPreviewFrame(). Этот метод вызывается каждый раз, когда изображение с камеры поступает в SurfaceHolder. Одним из аргументов этого метода является массив байт, который содержит в себе изображение с камеры. В этом методе производится обработка изображение для поиска штрих-кода и получение его номера.
Для обработки изображения используется внешняя библиотека zxing. Алгоритм обработки следующий:
Подготавливаются данные изображения. Создается объект PlanarYUVLuminanceSource, в который передается массив байт исходного изображения, ширина и высота исходного изображения, а так же расположение области, из которой будет обрабатываться изображения. Чтобы сканер нашел штрих-код, необходимо, чтобы изображение-штрих кода попало в эту область.
Далее этот объект в объект BinaryBitmap, который позже будет передан на обработку.
Создается объект MultiFormatReader, который отвечает за обработку изображения штрих-кода.
MultiFormatReader mfr = new MultiFormatReader();
После создания его нужно настроить таким образом, чтобы он искал только те типы штрих-кодов, которые необходимы, т.е. штрих-код типа EAN-13. Для этого создается ассоциативный массив Map<DecodeHintType,Object>, в котором ключ указывает на тип настраиваемого параметра, а объект является параметром. Map<DecodeHintType,Object> hints = new HashMap<DecodeHintType, Object>();
Для настройки на определенный тип штрих-кода в этот массив добавляется элемент Vector<BarcodeFormat> с ключом DecodeHintType.POSSIBLE_FORMATS .
Vector<BarcodeFormat> decodeFormats = new Vector<BarcodeFormat>(1);
decodeFormats.add(BarcodeFormat.EAN_13);
hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
После этого этот массив добавляется в объект MultiFormatReader.
mfr.setHints(hints);
