Uploaded by Яблочный Сок

бИЦ-191 Цуканов КП

advertisement
МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ
РОССИЙСКОЙ ФЕДЕРАЦИИ
ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ
ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ
«ВОРОНЕЖСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»
(ФГБОУ ВО «ВГТУ»)
Факультет информационных технологий и компьютерной безопасности
(факультет)
Кафедра Систем автоматизированного проектирования и информационных систем
КУРСОВОЙ ПРОЕКТ
по дисциплине Разработка приложений для мобильных устройств
тема Проектирование и разработка мобильных приложений под ОС Android
Расчетно-пояснительная записка
Разработала студентка
А.В. Цуканов
Подпись, дата
Руководитель
Инициалы, фамилия
Э.И. Воробьев
Подпись, дата
Инициалы, фамилия
Подпись, дата
Инициалы, фамилия
Подпись, дата
Инициалы, фамилия
Подпись, дата
Инициалы, фамилия
Члены комиссии
Нормоконтролер
Защищена ___________________
Оценка ____________________________
дата
2022
МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ
РОССИЙСКОЙ ФЕДЕРАЦИИ
ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ
ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ
«ВОРОНЕЖСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»
(ФГБОУ ВО «ВГТУ»)
Кафедра Систем автоматизированного проектирования и информационных систем
ЗАДАНИЕ
на курсовой проект
по дисциплине Разработка приложений для мобильных устройств
Тема работы Проектирование и разработка мобильных приложений под ОС
Android
Студент группы бИЦ-191
Цуканов Андрей Владимирович
Фамилия, имя, отчество
Вариант: мобильное приложение для организации заметок
Технические условия ОС Android 5.1, ОЗУ 1.5 Гб, размер встроенной памяти 8 гб
Содержание и объем проекта (графические работы, расчеты и прочее):
анализ и описание предметной области (11 страниц); проектирование мобильного
приложения (5 страниц); разработка и реализация мобильного приложения (17
страниц); 33 страницы, 1 таблица, 18 рисунков, 1 приложение.
Сроки выполнения этапов анализ и описание предметной области (24.09 – 12.10);
проектирование мобильного приложения (13.10 – 02.11); разработка мобильного
приложения и реализация программы (03.11 – 07.12); оформление расчтенопояснительной записки (08.12 – 21.12)
Срок защиты курсового проекта
Руководитель
Э.И. Воробьев
Подпись, дата
Задание принял студент
Инициалы, фамилия
А.В. Цуканов
Подпись, дата
2
Инициалы, фамилия
Замечания руководителя
3
Содержание
Задание на курсовой проект ................................................................................................................... 2
Замечания руководителя ........................................................................................................................ 2
Введение .................................................................................................................................................. 5
1 Анализ предметной области ............................................................................................................... 6
1.1 Особенности функционирования мобильных приложений в различных ОС ....................... 6
1.2 Анализ инструментальных средств разработки мобильных приложений ............................ 12
1.3 Постановка цели и задач курсового проекта ............................................................................ 16
2 Проектирование мобильного приложения ...................................................................................... 17
2.1 Обоснование выбора средства разработки ............................................................................... 17
2.2 Проектирование мобильного приложения ............................................................................... 19
3 Разработка мобильного приложения................................................................................................ 22
3.1 Структура мобильного приложения ......................................................................................... 22
3.2 Описание диалога с пользователем ........................................................................................... 23
3.3 Пример работы программы ........................................................................................................ 29
Заключение ............................................................................................................................................ 39
Список литературы ............................................................................................................................... 40
Приложение А Листинг программы.................................................................................................... 41
4
ВВЕДЕНИЕ
В современном мире сложно представить человека, который не пользуется
телефоном. Для нашего удобства их стараются каждый раз сделать всё лучше и
лучше. С их помощью мы можем делать практически всё: начиная от звонков и
поиска нужной нам информации в интернете, и заканчивая учёбой или работой
через смартфон.
Мобильные приложения можно разделить на несколько групп, исходя из
заинтересованности пользователей. Каждой категории мобильных приложений
свойственны свои технические характеристики и особенности реализации. Среди
мобильных приложений можно выделить:
1) Игры для смартфона
2) Промо-приложения – приложения, создаваемые для компаний на заказ.
3) Контентные сервисы – это приложения, которые создаются для быстрого
доступа пользователя к определённому контенту.
4) Социальные сети.
Целью данного курсового проекта является проектирование и разработка
мобильного приложения для чтения электронных книг на базе ОС Android.
В рамках курсового проекта были поставлены следующие задачи:
1. Анализ и описание предметной области.
2. Проектирование мобильного приложения.
3. Реализация и разработка мобильного приложения
5
1 Анализ предметной области
1.1 Особенности функционирования мобильных приложений в различных
ОС
К мобильным устройствам принято относить мобильные телефоны,
смартфоны и коммуникаторы. Разработчики ОС для мобильных устройств
работают над тем, чтобы приблизить возможности этих ОС к возможностям ОС для
настольных и портативных компьютеров. Однако в ОС для мобильных устройств
есть своя специфика. Их основные особенности, следующие:
 Учет более жестких ограничений по памяти мобильных устройств.
 Учет более низкой скорости процессора.
 Учет особенностей экранов и экранных навигаторов конкретных моделей
мобильных устройств.
 Совместимость с основными форматами файлов: .doc/docx, .ppt/.pptx, .pdf,
.jpg и др.
 Мультимедийные
возможности:
рисунки,
видео,
аудио,
обмен
мультимедийными сообщениями.
 Поддержка коммуникационных и сетевых технологий: Wi-Fi / WiMAX,
Bluetooth, GPRS, EVDO, GSM, CDMA.
В настоящее время на рынке мобильных устройств используется несколько
десятков наиболее распространенных ОС. Некоторые из них разработаны на основе
свободно
распространяемого
ядра
Linux.
Ведущие
фирмы-производители
мобильных устройств поддерживают собственные ОС либо ОС, приобретенные
вместе с их фирмами-разработчиками. Рассмотрим три самые популярные ОС для
мобильных устройств.
Android – операционная система для коммуникаторов, планшетных
компьютеров, цифровых проигрывателей, нетбуков и смартбуков, основанная на
ядре Linux. Изначально разрабатывалась компанией Android Inc., которую затем
купила Google. Впоследствии Google инициировала создание Open Handset Alliance
6
(OHA), которая сейчас и занимается поддержкой и дальнейшим развитием
платформы.
Android
позволяет
создавать
Java-приложения,
управляющие
устройством через разработанные Google библиотеки. Android Native Development
Kit создаёт приложения, описанные на Си и других языках [1].
Достоинства ОС Android.
1. Разнообразие приложений и игр. Их число в официальном магазине давно
уже преодолело миллионную отметку. Плееры, браузеры, текстовые редакторы и
многое другое – всего этого в избытке и на любой вкус.
2. Android – операционная система с открытым исходным кодом.
Производство приложений, игр, всяческих поправок и обновлений упрощено до
невозможности. Стремительно набирает обороты новая профессия — программист
приложений для Андроид.
3. В системе хорошо реализована многозадачность, когда без проблем
работает одновременно несколько приложений. Даже на не слишком мощном
устройстве может эффективно работать сразу несколько вкладок браузера,
музыкальный плеер и какое-нибудь ресурсоемкое приложение.
4. Оперативные обновления. Компанией Google ведется непрерывная работа
над улучшением функционала операционной системы, исправляются баги,
вносятся изменения в интерфейс. Кроме того, независимые разработчики тоже
прилагают немало усилий по совершенствованию своих приложений, быстро
адаптируя их под новые версии ОС.
Недостатки [2]:
1. Вне зависимости от того, насколько хорошее в устройстве железо,
смартфон или другой девайс под управлением OС Android приходится довольно
часто подзаряжать. Связано это с тем, что сама система не экономит на
предоставляемых ей аппаратных ресурсах. Частично недостаток можно исправить
настройкой энергосбережения, отключением ненужных функций, но лишь
частично.
2. Проблемы совместимости. Новые версии операционной системы часто
конфликтуют со снятыми с продажи устаревшими устройствами. Таким образом
7
мобильное устройство после обновления начинает вести себя не так, как хотелось
того – батарея быстро садится, начинаются зависания, перезагрузки. Приходится
принудительно откатываться на старую версию и отключать автоматическое
обновление.
3. Обилие настроек. Любителям часами копаться в телефоне, превращая его
в многофункционального помощника, разнообразие настроек придется по душе, а
вот обычные пользователи, у которых на первое место выходит практичность и
скорость работы, могут оказаться недовольны. В этом плане система от Apple
выглядит более привлекательно.
Несмотря на все свои недостатки, операционная система Android была и
будет востребована на рынке мобильных устройств. Основной причиной тому
является лояльное отношение к пользователям.
Широкий ассортимент устройств под управлением Андроид охватывает все
ценовые сегменты – как бюджетные модели, так и премиум класс, позволяя
обзавестись устройством с операционной системой от Google практически
каждому.
iOS (до 24 июня 2010 года - iPhone OS) – мобильная операционная система,
разрабатываемая и выпускаемая американской компанией Apple. В отличие от
Windows Phone и Google Android, выпускается только для устройств,
производимых фирмой Apple. Была выпущена в 2007 году. Первоначально - для
iPhone и iPod touch, позже - для таких устройств, как iPad и Apple TV.
Все пространство экрана состоит из четырех составляющих:
1. Рабочий экран (или Home Screen) - вмещает в себя 16 иконок различного
пользовательского назначения: почта, календарь, фотографии, контакты, заметки,
часы, калькулятор, камера, настройки, App Store и т.д.
2. Строка Dock. Находится в нижней части рабочего экрана, состоит из
четырех элементов.
3. Панель навигации Spotlight с рабочими экранами и поиском - нижняя часть
экрана
8
4. Строка состояния Status Bar - правый верхний угол экрана - отображает
уровень сигнала сети, EDGE, 3G, Wi-Fi, Bluetooth, индикатор заряда батареи,
состояние будильника, воспроизведение музыки и TTY.
Платформа iOS отличается удачно реализованной многозадачностью. Без
каких-либо сложностей можно свернуть и развернуть утилиту. Самое главное
заключается в том, что свернутые программы не оказывают воздействия на
операционную систему и не снижают заряд батареи. Еще неоспоримым
преимуществом является тот факт, что каждый активный процесс легко
закрывается
за
несколько
движений
Удобная
работа
с
инструментами
беспроводной связи [3].
К положительным качествам ОС можно отнести:
1. Интуитивно понятный интерфейс (уменьшается время, затрачиваемое на
запуск программ);
2. Экономность (Apple гарантирует длительное время автономной работы
даже при высоком уровне загруженности аппарата);
3. Отсутствие программных сбоев (нет зависаний и странностей в
поведении);
4. Высокая скорость работы (неважно, запущена игра, работает браузер
google или «тяжёлое» приложение);
5. Практичность (сравнение применяемого софта на iOS с софтом на Android
показывает высокое его качество и продуманность);
6. Защищённость (гаджет на платформе IOS сложно заразить вирусом или
вывести из строя по незнанию);
7. Облачное хранение данных, автоматическое сохранение резервных копий
(первый вариант допускает совместное использование файлов на всех устройствах
Apple, второй обезопасит от потери всех пользовательских данных в случае
поломки или кражи гаджета);
8. Качественная работа в беспроводных сетях (аппарат автоматически
переключается с мобильной передачи данных на Wi-Fi, и наоборот);
9. Многозадачность (свёрнутые приложения не потребляют ресурсы).
9
Недостатками являются:
1. Закрытость файловой системы (невозможность прямой переброски
файлов в Apple iPhone, iPod и iPad, отсутствие возможностей для полного обзора
содержимого устройства);
2. Отсутствие пользовательских настроек;
3. Ограничение памяти (дальнейшее её наращивание невозможно по
причине отсутствия разъёмов);
4. Ограниченность использования софта (формула один почтовый клиент —
один браузер – один магазин приложений);
5. Высокие цены на приложения.
Windows Phone – мобильная операционная система, являющаяся преемником
Windows Mobile, но несовместима с ней. С выходом Windows Mobile версии 6.5
компания Microsoft начала создавать бренд под названием Windows Phone.
Так стали именоваться все телефоны с этой операционной системой, но
первая операционная система Windows Phone (сразу под номером 7 – как
продолжение линейки мобильных систем от Microsoft) вышла 11 октября 2010 года.
Интерфейс пользователя основан на дизайнерской системе Windows Phone под
названием Metro, принципы которой были ранее использованы в дизайне
интерфейса Windows Media Center, Zune и Xbox.
Начальный экран составляют так называемые «живые плитки» которые
отображают информацию в режиме реального времени без участия пользователя.
Плитки также являются ссылками на приложения, различные функции и
индивидуальные объекты (контакты, веб-страницы и т. д.). Пользователь может
добавлять, перемещать или удалять плитки. Начиная с Windows Phone 8 размер
плиток можно регулировать, выбирая между тремя размерами отображения.
Установка приложений и игр на Windows Phone возможна только из
официального интернет-магазина Windows Phone Marketplace. Для энтузиастов
возможна разблокировка телефона при помощи утверждённого Microsoft сервиса
ChevronWP Labs, в результате чего на смартфон можно устанавливать самодельные
10
приложения или использовать его для тестирования в обход Marketplace и
официальной разблокировки телефона в качестве разработчика.
Достоинства Windows Phone:
1. Центр уведомлений. Обеспечивает доступ к расширенному списку
переключателей, удаление отдельных уведомлений, возможность отвечать в
уведомлениях.
2. Наличие удобного и информативного стартового экрана.
3. Поддержка джойстика на клавиатуре. Удобная альтернатива перемещению
курсора с помощью увеличительного стекла у iOS девайсов, которая является
одной из самых удобных.
4. Многопоточная загрузка приложений в магазине. Функция, которой очень
не хватает в других ОС во время восстановления из резервной копии. И в остальном
– это очень грамотный подход к реализации функции.
5. Новые системные приложения. Сюда входят новые офисные приложения,
почта и календарь, музыка, калькулятор, будильники и часы и в особенности новый
браузер.
Недостатки Windows Phone:
1. Ошибки масштабирования. В первую очередь, это непонятные переносы
текста в магазине, очень крупные или наоборот очень мелкие элементы интерфейса
и др.
2. Некорректные сообщения в шторке уведомлений. Часть дополнительных
иконок при опускании шторки внезапно могут исчезнуть.
3. Баги клавиатуры. Когда происходит набор текста вручную вместо
некоторых букв могут вводиться соседние, причем только при определенной
последовательности, т.е. в остальных случаях буква активна. Автозамена
срабатывает часто некорректно и зачастую предлагает слова с большой буквы в
середине предложения.
4. Неправильная фоновая работа приложений. Если правильно не настроить
фоновую работу приложений, то при включённой экономии заряда, они могут не
11
корректно функционировать. И даже отключив фоновую работу приложений,
некоторые из них могут присылать push-уведомления.
5. Медленная анимация закрытия приложений. Также при открытии меню
управления приложениями в горизонтальной ориентации позволят закрывать
приложения только в ней и вертикально не поворачивается.
6. Баг экрана блокировки. Экран после разблокировки может не загореться
или загореться не сразу, при этом дата и время появляются с задержкой.
Таким образом, проведя анализ различных ОС для мобильных приложений,
была выбрана ОС Android для разработки приложения в рамках курсового проекта.
1.2 Анализ инструментальных средств разработки мобильных приложений
В данный момент для создания мобильных приложений существует два вида
средств разработки: средства разработки для создания нативных мобильных
приложений и средства создания web–приложений, адаптированных под
мобильные приложения. Для анализа были выбраны средства разработки нативных
приложений так как в данной среде они более популярны и востребованы. Были
рассмотрены три наиболее популярных средства разработки: Android studio,
Eclipse, NetBeans IDE. Для анализа данных программных продуктов были выбраны
следующие критерии:
 функциональность;
 удобство интерфейса;
 возможность подключения дополнительных модулей;
 требовательность к системе;
 возможность подключения к системам контроля версий;
 наличие встроенных компонентов тестирования приложения.
Android Studio – продукт компании Google. Основана на программном
обеспечении IntelliJ IDEA от компании JetBrains, официальное средство разработки
Android приложений. Актуальная на данный момент версия приложения 2.2.
Данная среда разработки доступна для Windows, OS X и Linux [4].
12
Функционал данного приложения использует язык Java для написания
программного кода. Разработка интерфейса производится drag–n–drop методом, но
также имеется возможность использовать XML. Для удобства разработки
интерфейса так же существуют шаблоны, ориентируемые на задачу, которую
должно выполнять приложение.
Интерфейс данного ПО перегружен. Интерфейс библиотек приложения
имеет вид выпадающего древа и под него приходится отводить очень много места
в общем интерфейсе, в противном случае, информация становится нечитаемой. Та
же самая ситуация и с окном отладки. В функционале Android Studio возможность
подключения дополнительных плагинов отсутствует.
Данное
составляющей
средство
ЭВМ,
разработки
по
очень
сравнению
с
требовательно
другими
к
средствами
технической
разработки.
Минимальное количество ОЗУ, требуемое для данного продукта 2 гигабайта. Но
для комфортной работы с данной программой рекомендуемое количество памяти 8
гигабайт, что не является проблемой для современных компьютеров, но на ПК
старше 2014 года данная среда функционирует очень медленно, не говоря о
параллельном запуске других, даже не очень требовательных, приложений.
Полностью отсутствует возможность прямого подключения к сервисам
контроля версий, что сильно усложняет работу над одним приложением группой
лиц. Имеет встроенный модуль для эмуляции Android-устройства. Данный
эмулятор
требует
отдельных
ресурсов,
что
еще
сильнее
повышает
требовательность ПО к ЭВМ.
Eclipse – среда разработки, созданная компанией Eclipsefoundation.
Актуальная на данный момент версия Eclipse 4.6(Neon). Используемый язык для
написания мобильных приложений – Java. Включает в свой функционал не только
средства для разработки мобильных приложений, но и web – приложений,
поддерживает языки C++ и PHP.
Для разработки интерфейса нет шаблонов, или готовых объектов. Имеется
возможность синхронизации разных ПК для разработки одного проекта
посредствам облачных сервисов. Простой и удобный интерфейс. Панель библиотек
13
имеет древовидную структуру, но проблема предыдущего продукта здесь решена
просто – существует возможность полностью сворачивать неиспользуемые в
данный момент окна.
Существует встроенный помощник для написания простого Hello world
приложения. Есть возможность подключения дополнительных плагинов для
расширения функционала. Для этого в продукте предусмотрен целый модуль
Eclipse Marketplace, предоставляющий на выбор сразу три «Рынка» плагинов:
Eclipse Marketplace, Obeo Marketplace и RedHat.
Так же существует возможность написания собственных плагинов и их
использования без получения лицензии или обязательного предоставления
разработки на рынке. Системные требования для данного ПО не описаны
разработчиком, но при использовании на ПК средней производительности 2012
года затруднений замечено не было. Ввиду наличия синхронизации с облаком в
системе полностью отсутствуют какие-либо интегрированные средства для
подключения к системам контроля версий. Эмуляция устройства отсутствует
полностью.
NetBeans IDE – продукт компании NetBeans Community. Актуальная на
данный момент версия приложения 8.2. В данном программном продукте
функционал полностью реализуется посредствам плагинов. Вследствие этого, ПО
поддерживает большое количество используемых языков.
Для разработки нативных мобильных приложений используется Java, но
существует возможность создания web–приложения написанного на HTML5 или
JS+PHP. Встроенный отладчик полностью отсутствует, но имеется возможность
подключения удаленного отладчика через сеть «Интернет».
Интерфейс очень похож на интерфейс Eclipse, за исключением отсутствия
окна отладки, и наличия разметки номеров строк. Требования к ЭВМ либеральные.
Для минимальной работы продукта требуется 512 мегабайт ОЗУ, для более
комфортной работы рекомендуется использовать компьютер с 2 гигабайтами.
Имеет встроенную возможность подключения к системам контроля версий.
14
Взаимодействует с GitHub, Mercurial и Subversion. Встроенные компоненты для
тестирования приложения полностью отсутствуют.
Таким образом, анализ средств разработки мобильных приложений можно
свести в таблицу, оценивая рассмотренные критерии по пятибалльной шкале
(таблица 1).
Таблица 1 – Анализ средств разработки мобильных приложений
Средства разработки мобильных
приложений
Критерии оценки
AndroidStudio
Eclipse
NetBeansIDE
Функциональность
5
4
3
Удобство интерфейса
4
3
5
2
4
4
2
5
4
2
1
5
3
1
1
Возможность подключения
дополнительных модулей
Требовательность к системе
Возможность подключения к
системам контроля версий
Наличие встроенных
компонентов тестирования
приложений
Следуя заключениям, описанным выше, каждый из данных программных
продуктов подходят для разных направленностей и предпочтений в разработке
мобильных приложений. Если необходим мощный инструмент, который не требует
временных затрат для поиска или разработки дополнительных модулей, то стоит
выбрать Android studio. Если необходима более гибкая и мобильная разработка, то
рекомендуется выбрать NetBeans IDE. Если разработчика интересует нечто среднее
между двумя первыми, отличным выбором будет разработка в Eclipse.
В рамках данного курсового проекта будет использоваться среда разработки
Android studio.
15
1.3 Постановка цели и задач курсового проекта
Целью курсового проекта является проектирование и разработка мобильного
приложения под ОС Android, в рамках предметной области – приложение для
чтения электронных книг.
Для данного приложения необходимо создать функционал, позволяющий:
 Просматривать существующие файлы формата PDF;
 Открывать файлы для чтения;
 Сортировать файлы жанрам;
 Приближать текст во время чтения
Для достижения поставленной цели необходимо решить следующие задачи:
1. Проведение анализа предметной области
2. Выбор средств разработки
3. Проектирование структуры приложения
4. Разработка мобильного приложения
5. Опробация результатов
В ходе выполнения данного курсового проекта будут выполнены все
поставленные задачи.
16
2 Проектирование мобильного приложения
2.1 Обоснование выбора средства разработки
В качестве среды для разработки приложения была выбрана программа
Android Studio. Она основана на программном обеспечении IntelliJIDEA от
компании JetBrains. Существует множество сред разработки, но данная была
выбрана ввиду ее удобного графического интерфейса и средств отладки. Также
основными особенностями Android Studio является возможность вёрстки в
реальном времени, доступно множество вариантов размеров и разрешений экранов.
Главные возможности среды разработки, которые были отмечены в ходе
выполнения курсового проекта:
1. Включены все «интеллектуальные» возможности по редактированию кода
– автодополнение, рефакторинг и анализ кода;
2. Есть возможность визуального просмотра будущего приложения;
3. Сборка проекта работает быстрее, чем в альтернативных средах
разработки;
4. Удобный конструктор интерфейсов;
5. Встроенный SDK Manager;
6. При выборе ресурса, его содержимое отображается во всплывающих
JavaDoc;
7. Возможность создания одним кликом layout, сразу привязанным к activity;
8. Управление локализацией и переводами;
9. Предпросмотр приложений на разных разрешениях, языках, и версиях API
во встроенном эмуляторе;
10. Мониторинг используемой памяти;
11. Система сборки позволяет собирать приложение как внутри Android
Studio, так и за его пределами, и собирать разные версии.
Выделенные минусы среды разработки Android Studio:
1. Долгая компиляция проекта
17
2. Подвисание программы
Таким образом, данное программное решение имеет больше преимуществ,
чем недостатков.
С помощью встроенного в Android Studio SDK Manager была установлена
библиотека AndroidPdfViewerV1, которая необходима для отображения PDFдокументов на Android с поддержкой animations. Она основана на PdfiumAndroid
для декодирования файлов PDF. Работает на API 11 (Android 3.0) и выше.
Для разработки данного мобильного приложения был выбран язык
программирования
Java.
Java
–
сильно
типизированный
объектно-
ориентированный язык программирования, разработанный компанией Sun
Microsystems (в последующем приобретённой компанией Oracle). Приложения Java
обычно транслируются в специальный байт-код, поэтому они могут работать на
любой компьютерной архитектуре, с помощью виртуальной Java-машины.
Программы на Java транслируются в байт-код Java, выполняемый
виртуальной машиной Java (JVM) – программой, обрабатывающей байтовый код и
передающей инструкции оборудованию как интерпретатор.
Достоинством подобного способа выполнения программ является полная
независимость байт-кода от операционной системы и оборудования, что позволяет
выполнять Java-приложения на любом устройстве, для которого существует
соответствующая виртуальная машина. Другой важной особенностью технологии
Java является гибкая система безопасности, в рамках которой исполнение
программы полностью контролируется виртуальной машиной. Любые операции,
которые превышают установленные полномочия программы (например, попытка
несанкционированного доступа к данным или соединения с другим компьютером),
вызывают немедленное прерывание.
Основные классы программного средства:
 RealmHelper – класс, ответственный за работу с БД;
 RepositoryImpl
–
класс,
реализующий
ответственнен за хранение и получение данных;
18
паттерн
«репозиторий»,
 SupportLangsGetter
–
класс,
ответственный
за
получение
списка
поддерживаемых языков;
 TranslationGetter – класс, ответственный за получение перевода;
2.2 Проектирование мобильного приложения
Проектирование – важный этап, на котором принимается решение о том,
какой функционал реализовать в приложении, какие технологии использовать для
мобильной разработки, как правильно продумать его структуру, а также уместить
все это в оговоренные сроки.
Проектирование помогает сформировать понимание того, что должно быть
разработано, зачем, как и в какой срок. Существенно снижаются риски и
облегчается организация процессов, уточняется важная информация:
 какие ресурсы необходимы;
 куда движется разработка, что получится в итоге;
 в какой срок будет завершена разработка;
 снижается риск создать продукт, который никому не нужен.
Для лучшего понимания функционала приложения составим диаграмму
вариантов использования.
Диаграммы вариантов использования описывают взаимоотношения и
зависимости между группами вариантов использования и действующих лиц,
участвующими в процессе.
Важно понимать, что диаграммы вариантов использования не предназначены
для отображения проекта и не могут описывать внутреннее устройство системы.
Диаграммы
вариантов
использования
предназначены
для
упрощения
взаимодействия с будущими пользователями системы, с клиентами, и особенно
пригодятся для определения необходимых характеристик системы. Другими
словами, диаграммы вариантов использования говорят о том, что система должна
делать, не указывая сами применяемые методы.
19
При создании диаграммы вариантов использования был выбран один актор
(пользователь). В его возможные действия входят: открытие приложения, выбор
жанра, просмотр всех книг, открытие самой книги. Итоговая диаграмма показана
на рисунке 1.
Рисунок 1 – Диаграмма вариантов использования
Для лучшего понимания логики работы с программой была реализована
диаграмма деятельности.
Диаграмма деятельности – это технология, позволяющая описывать логику
процедур, бизнес-процессы и потоки работ. Во многих случаях они напоминают
блок-схемы, но принципиальная разница между диаграммами деятельности и
нотацией блок-схем заключается в том, что первые поддерживают параллельное
процессы.
В созданной диаграмме деятельности были выявлены два основных пути:
выбор жанра и выбор всех книг. В первом варианте пользователь входит в
приложение, переходит к жанрам, выбирает жанр, выбирает книгу и открывает ее.
Во втором случае выпадают пункты с переходом и выбором жанра. Итоговая
диаграмма показана на рисунке 2.
20
Рисунок 2 – Диаграмма деятельности
21
3 Разработка мобильного приложения
3.1 Структура мобильного приложения
В данном курсовом проекте было реализовано мобильное приложение для
организации заметок с использованием языка программирования Java в среде
разработки Android Studio. Модульная структура приложения показана на
рисунке 6.
Рисунок 3 – Модульная диаграмма приложения
На данной диаграмме показаны четыре основных модуля:
1. Модуль графического взаимодействия с пользователем – отвечает за
отображение всех кнопок и переход между страницами;
2. Модуль создания и редактирования заметок – отвечает за добавление
заметок на главный экран, а также за изменение и сохранение данных внутри
заметок.
22
3. Модуль создания и редактирования профилей – отвечает за добавление и
изменение информации в профиле пользователя, а также за обновление фотографии
пользователя.
4. Модуль связи с БД – отвечает за сохранение заметок и профиля в БД
SQLite.
При запуске приложения первым запускается модуль графического
взаимодействия с пользователем. С его помощью пользователь может перейти к
созданию заметок или открыть боковое меню и перейти к изменению профиля
пользователя.
3.2 Описание диалога с пользователем
На стартовом экране изображен значок и сообщение о том, что в данный
момент пользователь не добавил никаких заметок. Сверху имеется заголовок с
названием программы «Мой ежедневник».
В нижнем правом углу находится кнопка «плюс», при нажатии на которую
открывается окно добавления заметок, представленное на рисунке 8.
23
Рисунок 4 - Главное окно
В окне добавления заметки можно ввести заголовок, добавить дату для
заметки, и ввести описание заметки. После чего заметку можно сохранить.
24
Рисунок 5 – Окно добавление заметки
В боковом меню есть вкладки «Мой профиль» для просмотра и
редактирования профиля, «Оставить отзыв» для отправления отзыва по почте.
Также при нажатии на икноку сверху, можно задать фотографию профиля.
25
Рисунок 6 – Боковое меню
В окне добавления фотографии можно добавить фотографии для профиля,
нажав на значок фотоаппарата в верхнем правом углу и выбрав способ добавления
фотографии: сделать фото или загрузить существующее.
26
Рисунок 7 – Окно добавления фотографии
В окне «Мой профиль» можно заполнить данные профиля пользователя – имя,
email и «о себе». После чего данные можно сохранить нажав на значок сохранения
в правом верхнем углу.
27
Рисунок 8 – Окно «Мой профиль»
При нажатии кнопки «Отправить отзыв» возникает всплывающее окно
Google Почты, в котором автоматически заполняются поля адресата и темы.
28
Рисунок 9 – Окно отправки отзыва о приложении
3.3 Пример работы программы
Ниже приведен пример заполнения заметки.
29
Рисунок 10 – Создание заметки
После сохранения заметки, она будет отображаться в главном окне, как
показано на рисунке 14.
30
Рисунок 11 – Сохранённая заметка
Ниже приведён пример заполнения профиля пользователя.
31
Рисунок 12 – Заполнение пользовательского профиля
После сохранения профиля в боковом меню обновится отображение
профиля – появится имя и email.
32
Рисунок 13 – Обновлённое боковое меню
Для того чтобы добавить в профиль фотографию, нажмём на иконку свеху от
имени профиля и выберем способ добавления фотографии (см. рисунок 17)
33
Рисунок 14 – Окно добавления фотогафии
Для примера нажмём «Сделать фото». Так как программа открыта при
помощи эмулятора, после открытия камеры нам показывается анимация как на
рисунке 18.
34
Рисунок 15 – Фотография для профиля
После нажатия на значок «Сохранить» в правом верхнем углу, фотография
сохранится и появится в боковом меню (рисунок 19).
35
Рисунок 16 – Боковое меню с фотографией пользователя
Чтобы удалить все заметки, нажмём в главном окне на значок в правом
верхнем углу, а после на кнопку «Удалить все».
36
Рисунок 17 – Кнопка «Удалить все»
После этого, появится подтверждение об удалении всех заметок.
37
Рисунок 18 – Подтверждения удаления
38
ЗАКЛЮЧЕНИЕ
В результате реализации данного курсового проекта был выполнены анализ
предметной области, проектирование и реализация мобильного приложения в
указанной предметной области.
В рамках курсовой работы были выполнены следующие задачи:
1. Проведение анализа предметной области
2. Выбор средств разработки
3. Проектирование структуры приложения
4. Разработка мобильного приложения
5. Опробация результатов
39
СПИСОК ЛИТЕРАТУРЫ
1. Коматинени С. Android для профессионалов. [Текст] / С. Коматинени, Д.
Маклин. — М.: «Вильямс», 2011. – 231 c.
2. Голощапов А. Google Android: программирование для мобильных
устройств. [Текст] / А. Голощапов. — CПб.: БХВ-Петербург, 2010. — С. 448.
3. Конвэй Дж. Программирование под iOS. Для профессионалов. [Текст] / Дж.
Конвэй, А. Хиллегасс. – СПб.: Питер, 2013. – 608 с.
4. «Android Studio is the official IDE for Android application development, based
on IntelliJ IDEA» [Электронный ресурс] – электронный справочник, режим доступа
– https://android-developers.googleblog.com/2022/09/android-studio-dolphin.html (дата
обращения: 12.12.2022).
5. Meet Android Studio [Электронный ресурс] – электронный справочник,
режим доступа – https://developer.android.com/studio/intro (дата обращения:
12.12.2022).
6. AndroidDeveloperGuide. Официальный сайт для разработчиковAndroid.
[Электронный
ресурс]
–
электронный
справочник,
режим
http://developer.android.com/guide/basics/what-is-android.html
(дата
доступа
–
обращения:
12.12.2022).
7. Все о мобильной технике и технологиях. [Электронный ресурс] –
электронный
справочник,
режим
доступа
–
URL:http://android.mobile-
review.com/news/4657/(дата обращения: 12.12.2022).
8. Электронный учебник Android. [Электронный ресурс] – электронный
справочник, режим доступа – http://startandroid.ru/ru/sdk/
9. Коматинэни С. Google Android: программирование для мобильных
устройств [Текст] / С. Коматинэни, Д. Маклин, С. Хэшими. – СПб.: Питер, 2011. –
736 с.
40
ПРИЛОЖЕНИЕ A
(Обязательное)
(Листинг программы)
MainActivity.java
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
android.app.AlertDialog;
android.app.LoaderManager;
android.content.ContentUris;
android.content.CursorLoader;
android.content.DialogInterface;
android.content.Intent;
android.content.Loader;
android.database.Cursor;
android.graphics.Bitmap;
android.net.Uri;
android.os.Bundle;
android.speech.tts.TextToSpeech;
android.support.design.widget.FloatingActionButton;
android.support.design.widget.NavigationView;
android.support.v4.view.GravityCompat;
android.support.v4.widget.DrawerLayout;
android.support.v7.app.ActionBarDrawerToggle;
android.support.v7.app.AppCompatActivity;
android.support.v7.widget.Toolbar;
android.view.Menu;
android.view.MenuItem;
android.view.View;
android.widget.AdapterView;
android.widget.ImageView;
android.widget.ListView;
android.widget.TextView;
android.widget.Toast;
import com.diary.ishita.mydiary.data.DiaryContract.DiaryEntry;
import com.diary.ishita.mydiary.data.DiaryDbHelper;
import java.util.Locale;
public class MainActivity extends AppCompatActivity implements
NavigationView.OnNavigationItemSelectedListener,LoaderManager.LoaderCallbacks<Cursor>{
private DiaryDbHelper mDbHelper;
private ListView listView;
private DiaryCursorAdapter mAdapter;
private View EmptyView;
public static TextView user_nav_name;
public static TextView user_nav_email;
public static ImageView user_nav_image;
public static boolean has_set_image = false;
TextToSpeech textToSpeech;
public void toSpeak(String s){
textToSpeech.speak(s,TextToSpeech.QUEUE_FLUSH,null);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
textToSpeech=new TextToSpeech(this, new TextToSpeech.OnInitListener() {
@Override
public void onInit(int i) {
if(i!=TextToSpeech.ERROR) {
textToSpeech.setLanguage(Locale.UK);
}
}
41
});
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,DetailActivity.class);
startActivity(intent);
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
mDbHelper = new DiaryDbHelper(this);
listView = (ListView)findViewById(R.id.list_view);
EmptyView = (View)findViewById(R.id.empty_view);
listView.setEmptyView(EmptyView);
mAdapter = new DiaryCursorAdapter(this,null);
listView.setAdapter(mAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Uri uri= ContentUris.withAppendedId(DiaryEntry.CONTENT_URI,id);
Intent intent= new Intent(MainActivity.this,DetailActivity.class);
intent.setData(uri);
startActivity(intent);
}
});
getLoaderManager().initLoader(URL_LOADER,null,this);
View header=navigationView.getHeaderView(0);
user_nav_name = (TextView)header.findViewById(R.id.user_name);
user_nav_email = (TextView)header.findViewById(R.id.user_email);
user_nav_image = (ImageView)header.findViewById(R.id.User_photo);
user_nav_image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,UserImageActivity.class);
startActivity(intent);
}
});
String[] projrction =new
String[]{DiaryEntry._USER_ID,DiaryEntry.USER_COLUMN_NAME,DiaryEntry.USER_COLUMN_EMAIL};
Cursor cur = getContentResolver().query(DiaryEntry.USER_CONTENT_URI,projrction,null,null,null);
if(cur.getCount()!=0) {
cur.moveToFirst();
user_nav_name.setText(cur.getString(cur.getColumnIndex(DiaryEntry.USER_COLUMN_NAME)));
user_nav_email.setText(cur.getString(cur.getColumnIndex(DiaryEntry.USER_COLUMN_EMAIL)));
}
String[] projection = new String[]{ DiaryEntry._IMAGE_ID,DiaryEntry.COLUMN_USER_IMAGE_DATA};
Cursor c= getContentResolver().query(DiaryEntry.IMAGE_URI,projection,null,null,null);
if((c.getCount()!=0)&&(c!=null)){
c.moveToFirst();
if(c.getBlob(1)!=null) {
byte[] image = c.getBlob(1);
Bitmap b = DbBitmapUtils.getImage(image);
user_nav_image.setImageBitmap(b);
}
}
}
2
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
public static boolean has_diary= true;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_delete_all) {
if(has_diary)
showDeleteConfirmationDialog();
else{
Toast toast= Toast.makeText(this,"Нечего удалять!",Toast.LENGTH_SHORT);
toast.show();
}
return true;
}
return super.onOptionsItemSelected(item);
}
private void showDeleteConfirmationDialog(){
AlertDialog.Builder builder= new AlertDialog.Builder(this);
builder.setMessage("Удалить все заметки?");
builder.setPositiveButton("Удалить", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
deleteAll();
}
});
builder.setNegativeButton("Назад", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
if(dialog!=null){
dialog.dismiss();
}
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
private void deleteAll() {
getContentResolver().delete(DiaryEntry.CONTENT_URI,null,null);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id){
case R.id.user_profile:
Intent intent = new Intent(MainActivity.this,UserProfileActivity.class);
startActivity(intent);
return true;
case R.id.nav_send:
emailIntent();
return true;
}
3
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
private void emailIntent() {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_SUBJECT,"Отзыв о приложении \"Мой ежедневник\"");
intent.putExtra(Intent.EXTRA_EMAIL,new String[]{"tsukanov.official@gmail.com"});
if(intent.resolveActivity(getPackageManager())!=null){
startActivity(intent);
}
}
private final static int URL_LOADER= 0;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = {DiaryEntry._ID, DiaryEntry.COLUMN_TITLE, DiaryEntry.COLUMN_DATE,
DiaryEntry.COLUMN_IMAGE_DATA};
switch (id){
case URL_LOADER:
return new CursorLoader(this,DiaryEntry.CONTENT_URI,projection,null,null,null);
default:
return null;
}
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
if(data.getCount()==0){
has_diary=false;
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
}
ImageActivity.java
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
android.app.Activity;
android.app.AlertDialog;
android.app.LoaderManager;
android.content.CursorLoader;
android.content.DialogInterface;
android.content.Intent;
android.content.Loader;
android.content.pm.PackageManager;
android.database.Cursor;
android.graphics.Bitmap;
android.graphics.drawable.BitmapDrawable;
android.net.Uri;
android.os.Bundle;
android.os.Environment;
android.provider.MediaStore;
android.support.v7.app.AppCompatActivity;
android.view.Menu;
android.view.MenuItem;
android.widget.ImageView;
android.widget.Toast;
com.diary.ishita.mydiary.data.DiaryContract;
java.io.ByteArrayOutputStream;
java.io.File;
java.io.FileNotFoundException;
java.io.FileOutputStream;
java.io.IOException;
public class ImageActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>{
private int REQUEST_CAMERA = 0, SELECT_FILE = 1;
private String userChoosenTask;
4
private ImageView imageView ;
private Uri CurrentUri;
private static final int LOADER_ID= 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image);
Intent intent = getIntent();
CurrentUri= intent.getData();
imageView= (ImageView)findViewById(R.id.add_an_image);
if(CurrentUri==null){
setTitle("Добавить изобржание");
invalidateOptionsMenu();
imageView.setImageResource(R.mipmap.person_image);
}
else {
setTitle("Редактировать изоображение");
getLoaderManager().initLoader(LOADER_ID,null,this);
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if (CurrentUri == null) {
MenuItem menuItem = menu.findItem(R.id.delte_image);
menuItem.setVisible(false);
}
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.image_menu,menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.image_edit:
if(CurrentUri==null){
addImage();
}
else {
imageEdit();
}
return true;
case R.id.save_image:
saveImage();
return true;
case R.id.delte_image:
deleteImage();
return true;
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
private void saveImage() {
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap= drawable.getBitmap();
byte[] byte_for_image = DbBitmapUtils.getBytes(bitmap);
DetailActivity.setImagebyte(byte_for_image);
Toast toast=Toast.makeText(this,"Изобрражение сохранено",Toast.LENGTH_SHORT);
toast.show();
}
private void deleteImage() {
imageView.setImageResource(R.mipmap.person_image);
}
private void imageEdit() {
5
final CharSequence[] items = { "Сделать фото", "Выбрать изображение",
"Назад" };
AlertDialog.Builder builder = new AlertDialog.Builder(ImageActivity.this);
builder.setTitle("Change Photo!");
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
boolean result=Utility.checkPermission(ImageActivity.this);
if (items[item].equals("Сделать фото")) {
userChoosenTask="Сделать фото";
if(result)
cameraIntent();
} else if (items[item].equals("Выбрать изображение")) {
userChoosenTask="Выбрать изображение";
if(result)
galleryIntent();
} else if (items[item].equals("Назад")) {
dialog.dismiss();
}
}
});
builder.show();
}
private void addImage() {
final CharSequence[] items = { "Сделать фото", "Выбрать изображение",
"Назад" };
AlertDialog.Builder builder = new AlertDialog.Builder(ImageActivity.this);
builder.setTitle("Добавить фото!");
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
boolean result=Utility.checkPermission(ImageActivity.this);
if (items[item].equals("Сделать фото")) {
userChoosenTask="Сделать фото";
if(result)
cameraIntent();
} else if (items[item].equals("Выбрать изображение")) {
userChoosenTask="Выбрать изображение";
if(result)
galleryIntent();
} else if (items[item].equals("Назад")) {
dialog.dismiss();
}
}
});
builder.show();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case Utility.MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if(userChoosenTask.equals("Сделать фото"))
cameraIntent();
else if(userChoosenTask.equals("Выбрать изображение"))
galleryIntent();
} else {
}
break;
}
}
private void galleryIntent()
{
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Выбрать файл"),SELECT_FILE);
}
private void cameraIntent()
{
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,REQUEST_CAMERA);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
6
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == SELECT_FILE)
onSelectFromGalleryResult(data);
else if (requestCode == REQUEST_CAMERA)
onCaptureImageResult(data);
}
}
private void onCaptureImageResult(Intent data) {
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.PNG, 90, bytes);
File destination = new File(Environment.getExternalStorageDirectory(),
System.currentTimeMillis() + ".png");
FileOutputStream fo;
try {
destination.createNewFile();
fo = new FileOutputStream(destination);
fo.write(bytes.toByteArray());
fo.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
imageView.setImageBitmap(thumbnail);
}
@SuppressWarnings("deprecation")
private void onSelectFromGalleryResult(Intent data) {
Bitmap bm=null;
if (data != null) {
try {
bm = MediaStore.Images.Media.getBitmap(getApplicationContext().getContentResolver(),
data.getData());
} catch (IOException e) {
e.printStackTrace();
}
}
imageView.setImageBitmap(bm);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projecton = {DiaryContract.DiaryEntry._ID,
DiaryContract.DiaryEntry.COLUMN_IMAGE_DATA};
return new CursorLoader(this,CurrentUri,projecton,null,null,null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if(data.getCount()==0)
return;
data.moveToFirst();
byte[] byte_image =
data.getBlob(data.getColumnIndex(DiaryContract.DiaryEntry.COLUMN_IMAGE_DATA));
Bitmap bitmap = DbBitmapUtils.getImage(byte_image);
imageView.setImageBitmap(bitmap);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
}
UserImageActivity.java
import android.app.Activity;
import android.app.AlertDialog;
7
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
android.app.LoaderManager;
android.content.CursorLoader;
android.content.DialogInterface;
android.content.Intent;
android.content.Loader;
android.content.pm.PackageManager;
android.database.Cursor;
android.graphics.Bitmap;
android.graphics.drawable.BitmapDrawable;
android.net.Uri;
android.os.Bundle;
android.os.Environment;
android.provider.MediaStore;
android.support.v7.app.AppCompatActivity;
android.view.Menu;
android.view.MenuItem;
android.widget.ImageView;
android.widget.Toast;
com.diary.ishita.mydiary.data.DiaryContract;
java.io.ByteArrayOutputStream;
java.io.File;
java.io.FileNotFoundException;
java.io.FileOutputStream;
java.io.IOException;
public class ImageActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>{
private
private
private
private
private
int REQUEST_CAMERA = 0, SELECT_FILE = 1;
String userChoosenTask;
ImageView imageView ;
Uri CurrentUri;
static final int LOADER_ID= 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image);
Intent intent = getIntent();
CurrentUri= intent.getData();
imageView= (ImageView)findViewById(R.id.add_an_image);
if(CurrentUri==null){
setTitle("Добавить изобржание");
invalidateOptionsMenu();
imageView.setImageResource(R.mipmap.person_image);
}
else {
setTitle("Редактировать изоображение");
getLoaderManager().initLoader(LOADER_ID,null,this);
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if (CurrentUri == null) {
MenuItem menuItem = menu.findItem(R.id.delte_image);
menuItem.setVisible(false);
}
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.image_menu,menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.image_edit:
if(CurrentUri==null){
addImage();
}
else {
imageEdit();
}
return true;
case R.id.save_image:
8
saveImage();
return true;
case R.id.delte_image:
deleteImage();
return true;
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
private void saveImage() {
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap= drawable.getBitmap();
byte[] byte_for_image = DbBitmapUtils.getBytes(bitmap);
DetailActivity.setImagebyte(byte_for_image);
Toast toast=Toast.makeText(this,"Изобрражение сохранено",Toast.LENGTH_SHORT);
toast.show();
}
private void deleteImage() {
imageView.setImageResource(R.mipmap.person_image);
}
private void imageEdit() {
final CharSequence[] items = { "Сделать фото", "Выбрать изображение",
"Назад" };
AlertDialog.Builder builder = new AlertDialog.Builder(ImageActivity.this);
builder.setTitle("Change Photo!");
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
boolean result=Utility.checkPermission(ImageActivity.this);
if (items[item].equals("Сделать фото")) {
userChoosenTask="Сделать фото";
if(result)
cameraIntent();
} else if (items[item].equals("Выбрать изображение")) {
userChoosenTask="Выбрать изображение";
if(result)
galleryIntent();
} else if (items[item].equals("Назад")) {
dialog.dismiss();
}
}
});
builder.show();
}
private void addImage() {
final CharSequence[] items = { "Сделать фото", "Выбрать изображение",
"Назад" };
AlertDialog.Builder builder = new AlertDialog.Builder(ImageActivity.this);
builder.setTitle("Добавить фото!");
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
boolean result=Utility.checkPermission(ImageActivity.this);
if (items[item].equals("Сделать фото")) {
userChoosenTask="Сделать фото";
if(result)
cameraIntent();
} else if (items[item].equals("Выбрать изображение")) {
userChoosenTask="Выбрать изображение";
if(result)
galleryIntent();
} else if (items[item].equals("Назад")) {
dialog.dismiss();
}
}
});
builder.show();
}
@Override
9
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case Utility.MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if(userChoosenTask.equals("Сделать фото"))
cameraIntent();
else if(userChoosenTask.equals("Выбрать изображение"))
galleryIntent();
} else {
}
break;
}
}
private void galleryIntent()
{
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Выбрать файл"),SELECT_FILE);
}
private void cameraIntent()
{
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,REQUEST_CAMERA);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == SELECT_FILE)
onSelectFromGalleryResult(data);
else if (requestCode == REQUEST_CAMERA)
onCaptureImageResult(data);
}
}
private void onCaptureImageResult(Intent data) {
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.PNG, 90, bytes);
File destination = new File(Environment.getExternalStorageDirectory(),
System.currentTimeMillis() + ".png");
FileOutputStream fo;
try {
destination.createNewFile();
fo = new FileOutputStream(destination);
fo.write(bytes.toByteArray());
fo.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
imageView.setImageBitmap(thumbnail);
}
@SuppressWarnings("deprecation")
private void onSelectFromGalleryResult(Intent data) {
Bitmap bm=null;
if (data != null) {
try {
bm = MediaStore.Images.Media.getBitmap(getApplicationContext().getContentResolver(),
data.getData());
} catch (IOException e) {
e.printStackTrace();
}
}
imageView.setImageBitmap(bm);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
10
String[] projecton = {DiaryContract.DiaryEntry._ID,
DiaryContract.DiaryEntry.COLUMN_IMAGE_DATA};
return new CursorLoader(this,CurrentUri,projecton,null,null,null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if(data.getCount()==0)
return;
data.moveToFirst();
byte[] byte_image =
data.getBlob(data.getColumnIndex(DiaryContract.DiaryEntry.COLUMN_IMAGE_DATA));
Bitmap bitmap = DbBitmapUtils.getImage(byte_image);
imageView.setImageBitmap(bitmap);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
}
UserProfileActivity.java
import
import
import
import
import
import
import
import
import
import
import
import
import
import
android.app.AlertDialog;
android.app.LoaderManager;
android.content.ContentValues;
android.content.CursorLoader;
android.content.DialogInterface;
android.content.Loader;
android.database.Cursor;
android.net.Uri;
android.os.Bundle;
android.support.v7.app.AppCompatActivity;
android.view.Menu;
android.view.MenuItem;
android.widget.EditText;
android.widget.Toast;
import com.diary.ishita.mydiary.data.DiaryContract.DiaryEntry;
public class UserProfileActivity extends AppCompatActivity implements
LoaderManager.LoaderCallbacks<Cursor>{
private
private
private
private
static
static
static
static
EditText user_name;
EditText user_email;
EditText user_note;
boolean has_saved= false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_profile);
setTitle("Мой профиль");
user_name=(EditText)findViewById(R.id.user_name_edit_text_view);
user_email=(EditText)findViewById(R.id.user_email_edit_text_view);
user_note =(EditText)findViewById(R.id.user_notes_edit_text_view);
String[] projection = {DiaryEntry._USER_ID, DiaryEntry.USER_COLUMN_NAME,
DiaryEntry.USER_COLUMN_EMAIL, DiaryEntry.USER_COLUMN_NOTES};
Cursor cursor
=getContentResolver().query(DiaryEntry.USER_CONTENT_URI,projection,null,null,null);
if(cursor.getCount()!=0) {
getLoaderManager().initLoader(URL_LOADER, null, this);
has_saved = true;
}
else{
invalidateOptionsMenu();
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if (!has_saved) {
MenuItem menuItem = menu.findItem(R.id.action_delete);
11
menuItem.setVisible(false);
}
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.add_note, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_delete) {
showDeleteConfirmationDialog();
return true;
}
else if (id == R.id.action_save){
save();
finish();
return true;
}
else if(id==android.R.id.home)
finish();
return super.onOptionsItemSelected(item);
}
private void save() {
ContentValues values = new ContentValues();
String name = user_name.getText().toString();
String email = user_email.getText().toString();
String notes = user_note.getText().toString();
values.put(DiaryEntry.USER_COLUMN_NAME,name);
values.put(DiaryEntry.USER_COLUMN_EMAIL,email);
values.put(DiaryEntry.USER_COLUMN_NOTES,notes);
Toast toast;
String message=null;
if(!has_saved) {
Uri uri = getContentResolver().insert(DiaryEntry.USER_CONTENT_URI, values);
if(uri!=null)
has_saved=true;
message="Профиль сохранён!!";
}
else{
int rows=getContentResolver().update(DiaryEntry.USER_CONTENT_URI,values,null,null);
if(rows!=0)
message="Профиль обновлён!!";
}
toast= Toast.makeText(this,message,Toast.LENGTH_SHORT);
toast.show();
MainActivity.user_nav_name.setText(name);
MainActivity.user_nav_email.setText(email);
}
private void showDeleteConfirmationDialog(){
AlertDialog.Builder builder= new AlertDialog.Builder(this);
builder.setMessage("Удалить профиль?");
builder.setPositiveButton("Удалить", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
delete();
}
});
builder.setNegativeButton("Назад", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
if(dialog!=null){
dialog.dismiss();
}
}
12
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
private void delete() {
getContentResolver().delete(DiaryEntry.USER_CONTENT_URI,null,null);
Toast toast= Toast.makeText(this,"Профиль удалён!!",Toast.LENGTH_SHORT);
toast.show();
MainActivity.user_nav_name.setText("Неизвестно");
MainActivity.user_nav_email.setText("Email");
has_saved=false;
finish();
}
private final static int URL_LOADER= 2;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = {DiaryEntry._USER_ID, DiaryEntry.USER_COLUMN_NAME,
DiaryEntry.USER_COLUMN_EMAIL, DiaryEntry.USER_COLUMN_NOTES};
switch (id){
case URL_LOADER:
return new CursorLoader(this,DiaryEntry.USER_CONTENT_URI,projection,null,null,null);
default:
return null;
}
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if(data.getCount()==0){
return;
}
data.moveToFirst();
user_name.setText(data.getString(data.getColumnIndex(DiaryEntry.USER_COLUMN_NAME)));
user_email.setText(data.getString(data.getColumnIndex(DiaryEntry.USER_COLUMN_EMAIL)));
user_note.setText(data.getString(data.getColumnIndex(DiaryEntry.USER_COLUMN_NOTES)));
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
}
13
Download