Дипломная работа на тему Разработка приложения для смартфонов под управлением операционной системы Android

Министерство образования Республики Беларусь

Учреждение образования

«Гомельский государственный университет

имени Франциска Скорины»

Математический факультет

Кафедра математических проблем управления

Дипломная работа

Разработка приложения для смартфонов под управлением операционной системы Android

Исполнитель

студент группы ПМ-51 ____________ В.П. Кацубо

Научный руководитель

к.т.н., доцент кафедры МПУ ____________ В.А. Короткевич

Гомель 2013

Содержание

  • Введение
  • 1. Назначение разработанного приложения
    • 1.1 Основные функции приложения
    • 1.2 Особенности разработанного приложения
  • 2 Особенности и специфика разработки
    • 2.1 Ключевые особенности Android
    • 2.2 Общая схема работы приложения Android
    • 2.3 Среда разработки
  • 3. Взаимодействие пользователя с приложением
    • 3.1 Экран загрузки приложения
    • 3.2 Начальный экран приложения
    • 3.3 Экран новостей
    • 3.4 Экран обзора команды
    • 3.5 Экран информации об игроках
    • 3.6 Экран онлайн-TV
    • 3.7 Экран онлайн-радио
    • 3.8 Экран информации о лиге
    • 3.9 Экран статистики игр
    • 3.10 Экран онлайн заказа билетов
    • 3.11 Экран живой ленты
    • 3.12 Экран дополнительной информации
  • 4. Структура приложения
    • 4.1 Основные компоненты приложения
    • 4.2 Модуль настроек приложения
    • 4.3 Сервис фоновых процессов
    • 4.4 Модуль работы с ресурсами
    • 4.5 Система шифрования и защиты данных
    • 4.6 Модуль конвертации данных
    • 4.7 Система улучшения пользовательского интерфейса
    • 4.8 Система кэширования
    • 4.9 Менеджер данных
  • 5. Тестирование и публикация
    • 5.1 Тестирование
    • 5.2 Публикация и внедрение
  • Заключение
  • Список используемых источников
  • ПРИЛОЖЕНИЕ А
  • ПРИЛОЖЕНИЕ Б

Введение

Человеческие потребности быть всегда в курсе дел выводят информационные технологии на прямую линию по созданию все новых девайсов и гаджетов. Неудобство эксплуатации компьютеров и ноутбуков обуславливает появление различных мини-компьютеров, смартфонов и коммуникаторов, в основе которых лежит все та же операционная система. Лидирующие позиции на сегодняшний день занимают платформы Android и iPhone. Но эти платформы могут работать полноценно только при одном условии – если была для них осуществлена разработка мобильных приложений

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

Android – операционная система для коммуникаторов, планшетных компьютеров, цифровых проигрывателей, цифровых фоторамок, наручных часов, нетбуков и смартбуков, основанная на ядре Linux. Основным языком для разработки служит Java, однако существуют библиотеки позволяющие вести разработку на языке С++.

Целью дипломной работы является разработка приложения для смартфонов под управлением операционной системы Android. Требовалось разработать масштабируемое приложение с поддержкой всех современных устройств на базе Android версии 2.2 и выше. Основной характеристикой разрабатываемого приложения являлось использование сервисов и процессов не зависящих от основного приложения и выполняющих обработку данных в фоновом режиме.

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

– Были улучшены знания о принципах разработки для мобильных платформ (xml разметка, команды генерации векторной графики, принципы работы приложений, особенности работы с мобильными приложениями, разработка сервисов и фоновых задач). Целевой платформой была платформа Android версии 2.3. Целевым языком для разработки – язык Java 1.6 расширенное издание;

– Для реализации поставленной задачи была использована среда IntelliJ IDEA Community Edition 12.02 (Free edition). В процессе выполнения курсовой работы было разработано соответствующее приложение, подробнее о котором будет описано ниже. Разработанное приложение было протестировано, и будет использоваться на время проведения фестиваля.

1. Назначение разработанного приложения

1.1 Основные функции приложения

Основные функции приложения:

– Предоставление информации о ближайших мероприятиях;

– Предоставления статистики по прошедшим матчам;

– Общая информация о команде;

– Статистика матчей в лигах;

– Обновление данных с сервера в фоновом режиме;

– Просмотр новостей и комментариев во время матча.

Общая функциональная схема представлена на рисунке 1

Рисунок 1 – Общая функциональная схема приложения

1.2 Особенности разработанного приложения

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

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

Как видно из рисунка 1, процесс обновления данных происходит независимо от основного приложения. Функционал обновлений был реализован с помощью сервисов. Был разработан сервис, в котором происходит работа основного менеджера обновлений. Также данный сервис предоставляет данные основному приложению по его требованию. Ввиду особенностей работы сервисов, не зависимо от состояния приложений, данный сервис будет работать всегда, до полной либо ручной остановки приложения, что позволяет получать актуальные данные в любой момент времени.

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

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

2. Особенности и специфика разработки

2.1 Ключевые особенности Android

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

– Приложение требует для установки в два раза (или даже в четыре) больше места, чем оригинальный размер приложения;

– Скорость работы с файлами на встроенной флеш-карте падает в десятки раз при уменьшении свободного места;

– Каждый процесс может использовать до 16 Мб (иногда 24 Мб) оперативной памяти.

Android основан на Linux. Между приложением и ядром лежит слой API и слой библиотек на нативном коде. Приложение выполняется на виртуальной машине Java (Dalvik Virtual Machine).

В Android можно запускать много приложений. Но одно из них есть главным и занимает экран. От текущего приложения можно перейти к предыдущему или запустить новое. Это похоже на браузер с историей просмотров.

Каждый экран пользовательского интерфейса представлен классом Activity в коде. Различные Activity содержатся в процессах. Activity может даже жить дольше процесса. Activity может быть приостановлена и запущена вновь с сохранением всей нужной информации.

Android использует специальный механизм описания действий основанный на Intent. Когда нужно выполнить действие (сделать звонок, послать письмо, показать окно), вызывается Intent.

Также Android содержит сервисы подобные демонам в Linux для выполнения нужных действий в фоновом режиме (например, проигрывание музыки). Для обмена данными между приложениями используются Content providers (провайдеры содержимого).

Для данной работы были использованы провайдер данных о местоположении и положении в пространстве пользовательского устройства.

2.2 Общая схема работы приложения Android

Приложения для Android в своей работе использует окна(аналогично Windows), однако в данной системе вышеуказанные окна носят иное название – Activity. Как и в Windows, каждое окно имеет свой жизненный цикл и свои особенности. При создании нового окна вызывается метод onCreate(), при разработке данный метод переопределяется и в нем происходит инициализация приложения и его компонентов. Далее вызываются методы onStart() и onResume(). Оба метода вызываются перед отображением окна при его создании, либо восстановлении(при переключении из другого приложения, при разворачивании свернутого приложения и тп). При сворачивании вызываются методы onPause() и onStop(). При закрытии приложения и окна вызывается onDestory(), в данном методе можно сохранить пользовательские данные и параметры. Полное описание и последовательность вызова методов можно найти на официальном сайте. Общая схема жизненного цикла приложения для Android представлена на рисунке 2.

Рисунок 2 – Жизненный цикл приложения для системы под управлением Android 2.3.1

2.3 Среда разработки

В качестве среды для разработки приложения была выбрана Intellij Idea компании JetBrains. Существует множество сред разработки, но данная была выбрана по многочисленным рекомендациям среди программистов и ввиду ее удобного графического интерфейса и средств отладки. На рисунках 3,4 представлен внешний вид среды разработки.

Рисунок 3 – Внешний вид среды разработки приложения

На рисунке выше представлен базовый вид среды разработки. Как видно из рисунка, среда разделена на 2 рабочих области, колонка слева содержит менеджер фалов проекта и предоставляет быстрый доступ и удобную навигацию по разрабатываемому приложению, классам и ресурсам. Блок справа содержит вкладки с открытыми на редактирование файлами.

Среда поддерживает систему «Code injetion», данная система похволяет редактировать фрагменты кода с привязкой к различным языкам. Для примера: в приложении используется база данных, в этом случае пожно подключить язык «SQL» к проекту, и редактировать запросы, хранимые как строки в java коде, как в редакторе sql запросов. Аналогично можно редактировать html фрагменты и тд.

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

– Панель инструментов для отладки приложения(c);

– Панель контроля потоков приложения(b);

– Консоль;

– Панель лога(отображает лог приложения(d);

– Панель системы контроля версий(e);

– Результат поиска «использование элементов»(a);

– Системные сообщения;

– Панель элементов ToDo(f).

На рисунке ниже представлены некоторый из перечисленных панелей.

Рисунок 4 – Элементы UI среды разработки в расширенном режиме

3. Взаимодействие пользователя с приложением

3.1 Экран загрузки приложения

Данный экран отображается при запуске приложения. Во время его демонстрации программа проводит ряд операций по подготовке контента, а именно:

– В случае первого запуска программы производится распаковка базовых(начальных) данных приложения;

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

– Производится инициализация элементов управления и некоторых экранов;

– По окончании вышеперечисленных шагов производится запуск фоновых сервисов обновления и переход к экрану новостей.

Рисунок 5 – Экран загрузки приложения

3.2 Начальный экран приложения

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

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

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

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

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

Данный экран предоставляет возможность перехода на побочные экраны приложения:

– Экран новостей;

– Экран обзора команды;

– Экран информации об игроках;

– Экран онлайн-TV;

– Экран онлайн-радио;

– Экран информации о лиге;

– Экран статистики игр;

– Экран онлайн заказа билетов;

– Экран живой ленты;

– Экран дополнительной информации;

– Экран навигации к мету проведения матча;

– Экран онлайн магазина;

– Экран живой ленты;

– Экран расположения участников матча;

– Экран состава команды в текущем матче;

– Экран статистики забитых и пропущенных мячей;

– Экран статистики текущего матча;

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

Скриншот экрана представлен на рисунке ниже.

Рисунок 6 – Начальный экран

3.3 Экран новостей

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

Варианты фильтрации:

– По дате;

– По популярности;

– По типу новостей(о команде, о матчах).

Рисунок 7 – Экран новостей

3.4 Экран обзора команды

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

Рисунок 8 – Экран обзора команды

3.5 Экран информации об игроках

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

Рисунок 9 – Экран информации об игроке

3.6 Экран онлайн-TV

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

Варианты фильтрации:

– По дате;

– По популярности;

– По типу новостей(о команде, о матчах).

Рисунок 10 – Экран vfbtv

3.7 Экран онлайн-радио

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

Рисунок 11 – Экран радиостанций и программ

3.8 Экран информации о лиге

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

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

Рисунок 12 – Экран информации о лиге

3.9 Экран статистики игр

программное обеспечение android

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

Рисунок 13 – Экран статистики игр

3.10 Экран онлайн заказа билетов

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

Рисунок 14 – Экран онлайн заказов

3.11 Экран живой ленты

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

Рисунок 15 – Экран живой ленты

3.12 Экран дополнительной информации

Данный экран предоставляет контактную и общую информацию клуба.

Рисунок 15 – Экран контактной информации

4. Структура приложения

4.1 Основные компоненты приложения

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

Список разработанных компонентов:

– Модуль настроек приложения;

– Сервис фоновых процессов;

– Менеджер данных;

– Система шифрования и защиты данных;

– Модуль конвертации данных;

– Модуль интеграции социальных сетей;

– Модуль работы с ресурсами;

– Модуль навигации по приложению;

– Система улучшения пользовательского интерфейса;

– Модуль работы с интернетом;

– Модуль работы с файловой системой;

– Система кэширования.

В данном разделе будут более подробно описаны основные идеи вложенные в наиболее важные модули и системы.

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

– Контроль локализации;

– Контроль разрешения предоставляемых графических элементов пользовательского интерфейса;

– Система анимации;

– Система построения пользовательского интерфейса (частично);

– Система контроля разрешений и прав доступа приложения и его данных;

– Система интеграции сторонних приложений;

– Система организации фоновых процессов.

Подробности о каждой из систем можно найти на официальном сайте.

4.2 Модуль настроек приложения

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

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

Был разработан класс Settings.java. Рассмотрим основные его функции.

public static Settings instance() – данная функция инициализирует класс. Класс является синглтон паттерном.

public static <Type> read<Type>(String key,<Type> def) – данная функция получает значение параметра, в случае неудачи(не существует такого параметра, ошибка чтения) возвращается значение по умолчанию.

public static <Type> write<Type>(String key,<Type> def) – данный метод производит сохранение параметра и немедленную запись обновленных данных в файловую систему.

4.3 Сервис фоновых процессов

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

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

Вторая – фоновый сервис, работающий независимо от первой части, и предоставляющий последние обновленные данные первой части по ее первому требованию.

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

Подробнее о менеджере данных будет рассмотрено в следующем разделе.

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

private class TimeReceiver extends BroadcastReceiver {

@Override

public void onReceive(Context context, Intent intent) {

AppHandler.instance().postDelayed(new Runnable() {

@Override

public void run() {

// Log.d(TAG, “obeying the time-tick”);

ManagersController.instance().updateAll();

}

}, timeOffset);

}

}

4.4 Модуль работы с ресурсами

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

while (true) {

CacheData obj = get();

if (obj != null) { //Есть ли запросы на загрузку

Message msg = new Message();

Bitmap img; //есть ли в оперативной памяти?

if (isLoaded(obj.name, obj.section)) img =

getLoaded(obj.name, obj.section); //загружаем в память

else img = ImageManaer.instance().getImage(obj.name, obj.section);

//выполняем синхронное возвращение в

//запасивший загрузку поток

msg.obj = new Duplex<Long, Bitmap>(obj.timestamp, img);

obj.handler.sendMessage(msg);

} else try {

sleep(1000);

} catch (Exception ignored) {

}

}

4.5 Система шифрования и защиты данных

Данное приложение использует персональные данные устройства для авторизации на сервере обновлений, что означает передачу данных. Так как передача данных не гарантирует защищенности данных, было принято решение шифровать данные. Алгоритм шифрования применяемый в приложении – SHA1. Разработанный класс SimpleCrypto предоставляет 3 основных метода.

private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception – Данный метод выполняет шифрование данных по набору байт данный и ключу.

private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception – Данный метод выполняет дешифрование данных по набору байт данный и ключу.

private static byte[] getRawKey(byte[] seed) throws Exception – Данный метод генерирует ключ шифрования для последующих операций шифрование и дешифрования. Данный функционал выполнен в режим подключаемой библиотеке, так как должен выполнятся как на клиентском устройстве, так и на серверной части.

4.6 Модуль конвертации данных

Так как приложение получает данные из интернета, требуются методы разбора данных и занесения их в соответствующие переменные. Данные получаются приоритетно в формате JSON, однако часть данных приходит в форматах XML и RAW. Для преобразования и парсинга(парсинг – разбор и преобразование данных из одного формата в другой) были разработанные соответствующие классы: JsonToObjectsConverter, XmlToObjectConverter, RawToObjectConverter. Как понятно из названий, каждый класс выполняет конвертации соответствующего типа данных. Также каждый класс является паттеном синглтон, что позволяет в значительной степени избежать утечки и лишних затрат памяти.

Каждый класс предоставляет метод конвертации данных, для примера класс JsonToObjectsConverter содержит метод

public Object makeObjectFromJsonString(String json, Class objectClass){…} – Как видно в качестве параметров принимается строка данных в фомате JSON, а также тип данных к которым нудно привести.

4.7 Система улучшения пользовательского интерфейса

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

– HorizontalAutoAlignScrollView – данный виджет позволяет выполнять горизонтальную прокрутки элементов с последующим автоматическим выравниванием по последнемц активному элементу;

– HorizontalScrollWithIndicator – аналогично предыдущему, однако в дополнение содержит индикаторы указывающие номер отображаемого элемента;

– ImageSpinnerView – данный виджет является контейниром и производит вращение дочерних контейнеров;

– LazyImageView – Данный виджет расширяет стандартный элемент отображения изображений, однако расширен до возможности асинхронной подгрузки изовражений;

– MovingBar – Данный элемент является контейнером и реализует «передвигаемый» элемент пользовательского интерфейса;

– VerticalAutoAlignScrollView – Аналогично первому пункту, однако прокрутка происходит вертикально;

– ZoomImageView – Элемент расширяющий виджет отоброжения изображений, добавляя возможнасть масштабирования изображения.

4.8 Система кэширования

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

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

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

4.9 Менеджер данных

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

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

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

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

Все 3 уровня менеджеров реализуются как расширение одного из базовых классов менеджеров.

DataManager<T> – базовый абстрактый класс требующий реализации методов предоставления начальных данных, предоставление текущих данных, обновления.

JsonDataManager<T> extends DataManager<T> – данный класс реализует процесс обновления «простых» данных, не требующих дополнительных данных для получения (к примеру новости). Данный класс реализует все необходимый методы и требует при наследовании определить периоды обновления а также источник обновления.

JsonMultiDataManager<T, V> extends JsonDataManager<T> – Данный класс реализует процесс обновления «сложных» данных, требующих дополнительную информацию для получения, а также хранящих информацию с ограниченным сроком жизни (для примера счет во время матча, статистика последних матчей во время их проведения).

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

5. Тестирование и публикация

5.1 Тестирование

Тестирование разработанного приложения проводилось на различных версиях операционной системы, краткий список:

– Android Google API 2.3;

– Android Google API 2.3.1;

– Android Google API 2.4.1;

– Android Google API 3.6;

– Android Google API 4.0 (Ice Cream).

Тестирование происходило на устройстве Android Google Nexus One Developer Phone 2.0, Amazon Kindel Fire а также при использовании эмулятора Android устройств поставляемого в составе Android SDK. Интерфейс эмулятора представлен на рисунке ниже

Рисунок 16 – интерфейс эмулятора Android

Тестирование проводилось для различных разрешений экранов:

– 320×280;

– 400×240;

– 800×420;

– 800×480;

– 1024×600.

5.2 Публикация и внедрение

Разработанное приложение было успешно опубликовано в онлайн сервисе приложений «Google Play», и доступно для бесплатного скачивания по ссылке: https://play.google.com/store/apps/details?id=de.vfb.android

На момент написания дипломной работы статистика приложения следующая:

– Средняя оценка приложения(5-ти бальная система): 4,5;

– Количество проголосовавших: 251;

– Количество скачиваний за последние 30 дней: 30 000-50 000;

– Общее количество скачиваний: ~140 000;

– Дата последнего обновления: 19 Январь 2013 г.

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

На рисунке ниже представлена страничка данного приложения.

Рисунок 17 – страничка приложения в Google Play

Заключение

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

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

Задание на дипломную работу были выполнено в полном объёме.

Список используемых источников

1 Блог на хабре о разработке под Android [Электронный ресурс]

// URL: http://habrahabr.ru/blogs/android_development/

2 Официальная справка для Android разработчиков[Электронный ресурс]

// URL http://developer.android.com/index.html

3 Программирование для Android. Самоучитель /

Колисниченко Д. – СПб.: Санкт-Петербург, 2011. – 736 с.

4 Android 2. Программирование приложений для планшетных компьютеров и смартфонов / Рето Майер . – СПб.: Санкт-Петербург, 2011. – 672 с.

5 Статьи о программировании для Android [Электронный ресурс]

// URL: http://flashbot.ru/android-dev

6 Официальная справка по среде программирования [Электронный ресурс]

// URL: http://www.jetbrains.com

7 Форум о программировании для Android [Электронный ресурс]

// URL: http://www.cyberforum.ru/android-dev/

8 Форум о программировании для мобильных устройств [Электронный ресурс]

// URL: http://www.4pda.ru

9 Программирование под Android / Блэйк Мик . – СПб.: Санкт-Петербург, 2012. – 496 с.

10 Смартфоны Android без напряга. Руководство пользователя / Андрей Жвалевский . – СПб.: Санкт-Петербург, 2012. – 224 с.

11 Программирование для Android. Самоучитель / Денис Колиснеченко . – СПб.: Санкт-Петербург, 2011. – 272 с.

ПРИЛОЖЕНИЕ A

Листинг JsonDataManager.java

package de.vfb.android.managers;

import android.content.Context;

import android.content.Intent;

import android.util.Log;

import de.vfb.android.Settings;

import de.vfb.android.interaction.JsonToObjectsConverter;

import de.vfb.android.support.AppSettings;

import de.vfb.android.support.Internet.DataRequester;

import de.vfb.android.support.Internet.HeaderResponse;

import de.vfb.android.support.Utils.FileUtils;

import java.io.*;

import java.util.ArrayList;

/**

* User: Vkatz Date: 20.07.12 Time: 3:36

*/

public abstract class JsonDataManager<T> extends DataManager<T> {

private static String TAG = “JSONDataManager”;

private String fileName;

private String lastUpdateKey;

private String etagKey;

private String url;

protected Long updateDelayMatchDay;

protected Long updateDelayNoMatchDay;

protected Long updateDelayMatchDayExt;

protected Long updateDelayMatchTime;

private T data;

private ArrayList<OnUpdate<T>> listeners;

private String updateIntentActionName = null;

public static boolean forceUpdate = false;

@SuppressWarnings(“unchecked”)

protected JsonDataManager(String fileName, String lastUpdateKey,

String etagKey, String url) {

this.fileName = fileName;

this.lastUpdateKey = lastUpdateKey;

this.url = url;

this.etagKey = etagKey;

listeners = new ArrayList<OnUpdate<T>>();

parse();

}

protected JsonDataManager(String fileName, String lastUpdateKey,

String etagKey, String url, String pUpdateIntentActionName) {

this(fileName, lastUpdateKey, etagKey, url);

updateIntentActionName = pUpdateIntentActionName;

}

protected JsonDataManager() {

}

@Override

public void unpack() throws Exception {

File f = AppSettings.appContext.getDir(Settings.FOLDER_JSON_DATA,

Context.MODE_PRIVATE);

if (!f.exists() && !f.mkdir())

throw new Exception(“Cant create dir:” + Settings.FOLDER_JSON_DATA);

try {

FileUtils.writeFile(AppSettings.app.getAssets().open(fileName),

f.getAbsolutePath() + File.separator + fileName);

} catch (Throwable e) {

Log.e(“JsonDataManager”, “Can’t unpack ” + fileName

+ ” from asset to ” + f.getAbsolutePath());

}

Log.d(TAG, “finished with unpacking: ” + getClass().getName());

}

public T get() {

if (data == null)

parse();

return data;

}

private String getRealFileName() {

return AppSettings.appContext.getDir(Settings.FOLDER_JSON_DATA,

Context.MODE_PRIVATE).getAbsolutePath()

+ File.separator + fileName;

}

@Override

@Deprecated

/**

* use get()

*/

public T get(String key) {

return data;

}

public String getUpdateUrl() {

return url;

}

@Override

public synchronized void update() {

long lastUpdate = Settings.readLong(lastUpdateKey, 0);

long currentTimeMillis = System.currentTimeMillis();

long delay = getDelay();

// if (getClass().getName().contains(“Liti”)){

// Log.d(TAG, “currentTimeMillis – lastUpdate: ” + (currentTimeMillis – lastUpdate) + “, delay: ” + delay);

// }

if (delay == 0 && !forceUpdate) return;

if (currentTimeMillis – lastUpdate > delay) {

String url = getUpdateUrl();

if (url == null)

return;

HeaderResponse response = DataRequester.requestEtagData(url,

Settings.readString(etagKey, “”));

if (response.code == 304) {

Settings.writeLong(lastUpdateKey, currentTimeMillis);

return;

}

if (response.code == 200) {

// Log.d(getClass().getName(), “There were data to update …”);

String file = getRealFileName();

try {

FileUtils.writeFile(response.steam, file);

Settings.writeLong(lastUpdateKey,

currentTimeMillis);

Settings.writeString(etagKey, response.responseEtag);

parse();

if (updateIntentActionName != null) {

//Log.d(getClass().getName(), “sending update broadcast”);

sendTheBroadcast();

}

} catch (Exception e) {

Log.e(getClass().getName(), “Error writing json file “

+ file + ” Error:” + e.getLocalizedMessage());

}

}

}

}

public void setUpdateDelay(Long delay) {

updateDelayNoMatchDay = delay;

updateDelayMatchDayExt = delay;

updateDelayMatchDay = null;

updateDelayMatchTime = null;

}

public void setUpdateDelay(Long delayInMatchDayExt, Long delayInNonMatchDay) {

updateDelayNoMatchDay = delayInNonMatchDay;

updateDelayMatchDayExt = delayInMatchDayExt;

updateDelayMatchDay = null;

updateDelayMatchTime = null;

}

public void setUpdateDelay(Long delayInMatchDayExt,

Long delayInNonMatchDay, Long delayMatchDay) {

updateDelayNoMatchDay = delayInNonMatchDay;

updateDelayMatchDayExt = delayInMatchDayExt;

updateDelayMatchDay = delayMatchDay;

updateDelayMatchTime = null;

}

public void setUpdateDelay(Long delayInMatchDayExt,

Long delayInNonMatchDay, Long delayMatchDay, Long delayMatchTime) {

updateDelayNoMatchDay = delayInNonMatchDay;

updateDelayMatchDayExt = delayInMatchDayExt;

updateDelayMatchDay = delayMatchDay;

updateDelayMatchTime = delayMatchTime;

}

public long getDelay() {

long delay = 0;

if (!MatchDayManager.instance().isExtendedMatchDay()) {

//Log.d(TAG, “It’ non-matchday”);

delay = (updateDelayNoMatchDay == null) ? 0 : updateDelayNoMatchDay;

} else {

//Log.d(TAG, “It’s matchday”);

if (MatchDayManager.instance().isMatchTime()) {

if (updateDelayMatchTime != null) {

delay = updateDelayMatchTime;

} else if (updateDelayMatchDay != null){

delay = updateDelayMatchDay;

}

// Log.d(TAG, “It’s matchtime and there’s a delay set for it”);

} else if (MatchDayManager.instance().isMatchDayToday() && updateDelayMatchDay != null) {

delay = updateDelayMatchDay;

} else {

delay = (updateDelayMatchDayExt == null) ? 0 : updateDelayMatchDayExt;

}

}

return delay;

}

protected void parse() {

T temp = parse(getRealFileName());

if (temp != null) {

data = temp;

notifyUpdates();

}

}

@SuppressWarnings(“unchecked”)

protected T parse(String file) {

try {

InputStreamReader isr = new InputStreamReader(new FileInputStream(

file));

StringBuilder sb = new StringBuilder();

char[] buffer = new char[1024];

int c;

while ((c = isr.read(buffer, 0, 1024)) > 0)

sb.append(buffer, 0, c);

//Log.d(TAG, “JSON for ” + getClassOfData() + “: ” + sb.toString());

return (T) JsonToObjectsConverter.instance()

.makeObjectFromJsonString(sb.toString(), getClassOfData());

} catch (FileNotFoundException e) {

Log.e(getClass().getName(), “File not found ” + fileName);

} catch (IOException e) {

Log.e(getClass().getName(), “Cant read file ” + fileName

+ “nError:” + e.getLocalizedMessage());

} catch (Exception e) {

// Log.d(getClass().getName(),

// “JsonConvertError: ” + e.getLocalizedMessage());

}

return null;

}

public void subscribeToUpdates(OnUpdate<T> listener) {

listeners.add(listener);

}

public void unSubscribeFromUpdates(OnUpdate<T> listener) {

listeners.remove(listener);

}

public void notifyUpdates() {

for (OnUpdate<T> i : listeners)

i.onUpdate(data);

}

public static interface OnUpdate<T> {

public void onUpdate(T data);

}

protected void sendTheBroadcast() {

Intent updateIntent = new Intent(updateIntentActionName);

AppSettings.appContext.sendBroadcast(updateIntent);

}

protected abstract Class<T> getClassOfData();

}

ПРИЛОЖЕНИЕ Б

Листинг ManagersController.java

package de.vfb.android.managers;

import android.util.Log;

import de.vfb.android.managers.ImageManager.ImageDataManager;

import de.vfb.android.managers.ImageManager.ImageManager;

import de.vfb.android.managers.LivetickerManager.*;

import de.vfb.android.managers.MatchReportsManager.BerichtManager;

import de.vfb.android.managers.MatchReportsManager.MatchReportsManager;

import de.vfb.android.managers.scheduleManager.ScheduleManager;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

/**

* User: Vkatz

* Date: 19.07.12

* Time: 8:23

*/

public class ManagersController {

private static ManagersController _this;

public static ManagersController instance() {

if (_this == null) _this = new ManagersController();

return _this;

}

/**

* It’s method create all managers if it’s still not created<br/>

* must be use before unpack all data at first run if app

*/

public void instanceAll() {

ImageDataManager.instance();

managers = Arrays.asList(ImageManager.instance(),

NewsDataManager.instance(),

StaticHtmlManager.instance(),

MatchDayManager.instance(),

TeamDataManager.instance(),

ScheduleManager.instance(),

PodcastDataManager.instance(),

VfbTvDataManager.instance(),

MatchReportsManager.instance(),

StandingsDataManager.instance(),

GoalgettersManager.instance(),

LitiHeaderManager.instance(),

LitiActionsManager.instance(),

LitiStatisticsManager.instance(),

BerichtManager.instance(),

LitiTeamManager.instance(),

LitiLineupManager.instance(),

LitiStandingsManager.instance()

);

}

/**

* List of managers for initial unpacking

*/

private List<DataManager> managers;

/**

* list of managers running and participating in the update cycle

*/

private ArrayList<DataManager> runningManagers;

private ManagersController() {

runningManagers = new ArrayList<DataManager>();

}

public void addManager(DataManager manager) {

runningManagers.add(manager);

}

public synchronized void removeManager(DataManager manager) {

runningManagers.remove(manager);

}

public boolean managerIsRunning(DataManager manager){

return runningManagers.contains(manager);

}

public void updateAll() {

//This is fix for the problem with UI not responding when multiple updates are performed.

//The cause of the probled is that implementation of update() method in all data managers is not async,

//i.e. update operations (downloading, unpacking etc) are performed in UI thread that is absolutely incorrect.

//I think this fix is not good enough and maybe in the future we’ll need to make update methods async instead of

//creating thread here, but this fix is rathre quick, so i’m leaving it as is for now.

//TODO: remove this thread and make update methods in manager async.

if (managers != null) {

Thread updateThread = new Thread() {

@Override

public void run() {

for (DataManager i : managers) i.update();

}

};

updateThread.setPriority(Thread.MIN_PRIORITY);

updateThread.start();

}

}

public void unpackAll() {

for (DataManager i : managers)

try {

//Log.d(“ManagersController”, “unpacking for ” + i.getClass().getName());

i.unpack();

} catch (Exception e) {

Log.e(i.getClass().getName(), “Error in unpack: ” + e.getLocalizedMessage());

}

}

}

Поделиться статьёй
Поделиться в telegram
Поделиться в whatsapp
Поделиться в vk
Поделиться в facebook
Поделиться в twitter
Леонид Федотов
Леонид Федотов
Окончил НИУ ВШЭ факультет компьютерных наук. Сам являюсь кандидатом наук. По специальности работаю 13 лет, за это время создал 8 научных статей и 2 диссертации. В компании подрабатываю в свободное от работы время уже более 5 лет. Нравится помогать школьникам и студентам в решении контрольных работ и написании курсовых проектов. Люблю свою профессию за то, что это направление с каждым годом становится все более востребованным и актуальным.

Ещё статьи

Нет времени делать работу? Закажите!
Вид работы
Тема
Email

Отправляя форму, вы соглашаетесь с политикой конфиденциальности и обработкой ваших персональных данных.