Note&Noty — первое приложение на Android

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

Меня не интересовали все обширные возможности shortcuts, моя любовь с первого взгляда в этом приложении — заметки, которые можно вынести на главный экран и по нажатию на ярлык получать уведомление. Сразу же появилась куча идей, как это можно использовать — от вдохновляющий цитат, которые можно получить по одному щелчку, до списка покупок, сразу же отображающиеся в notification bar.

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

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

1. Так как я не располагала никакой яблочной продукцией, то весь желаемый функционал мне пришлось смотреть на том самом видео, упомянутого в начале (стоит ли говорить, что многие вещи мне пришлось додумывать и переделывать под свой вкус?). Как человек, мыслящий визуальными образами, моя первая мысль — быстренько накидать в Figma вид желаемого приложения и его осн функционал (это был только быстрый набросок, так что не все сохранится и кое-что новое добавится)

e2c627cd2ae9ddad91eaab912b1279e6.png

2. Вот тут мы переходим к шагу номер два — просмотр туториалов на ютубе. На удачу жмакнула на первое попавшееся «андроид приложения за n часов» и начала смотреть. За первые 20 минут я наконец-то узнала что такое пресловутое layout, как объявлять переменные и создавать кнопки. Теперь уже за несколько часов был создан вот такой монстр:

0c07b09c74465cff3e53f7fe7a919e33.png

Элементы на левой картинке (ArchiveFrag): SearchView find и ImageButton Plus (плюсик в верхнем правом углу)

Элементы на правой картинке (CreateNote): EditText name_folder, EditText text_body, Button choicebar_split, Button choicebar_get, Button apply (она же create) и ImageButton return

После этого я пошла в ино-ютуб, смотреть более специфичные туториалы и тут в моей голове зазвенели тревожные звоночки (не в плане языка, в нем я бум-бум чуть сильнее, чем в программировании). Выясняется, что «все крутые прогеры» не создают несколько Activity, а используют Fragments. Мое состояние можно было описать лишь как — at this moment he knew he f’cked up. И так как приложения я делала для себя любимой, то естественно надо делать все по красоте. И более продвинутые люди знают, что Activity и Fragments во многом отличаются, начиная от их, собственно, создания, заканчивая способом передачи данных между ними.

В общем, делать было нечего — снесла приложение и начала делать с чистого листа. Благо, все layout можно было скопировать.

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

Здесь же я завожу Adapter для RecycleView, в котором используется GridLayoutManager для отображения элементов.

Adapter самый простой — туториалов куча и код везде +/- одинаковый, но к тому же я создала собственный лист объектов, с которым и работает адаптер — определяется он так:  

8c31956c8025906b52fccb9d5a266c7f.png

Здесь показаны кастомные AlertDialod, которые появляются соответственно при нажатии на кнопки Button choicebar_split, Button choicebar_get. Не хочу и не буду мучить тем, как работают эти кнопки, по сравнению со всем остальным там довольно легко (и этим упущением я только что уменьшила эту статью примерно на 2 листа А4)

81ddf27df2084b3032ece4021bab5b0a.jpg

Небольшое отступление (в который раз): работать с List было временным решением, поэтому добавила базу данных, состоящую из двух листов. И List заполняется именно через БД:  

77692d75ac2436b9ed571628b4b3bbaf.png

4. Я люблю называть этот эпизод — «умей ставить ТЗ правильно»(на самом деле, рабочее название сплошь состояло из нецензурных слов, но ради приличия я их опустила). Внимательный читатель уже мог задаться вопросом: «а после создания заметки, можно ли ее как то открыть и отредактировать?». На это хочу сказать, во-первых, Ваши мысли намного быстрее моих, поздравляю; во-вторых, на данный момент — нет, нельзя.

Но и я в конце концов дошла до этого озарения и создала третий Fragment, который отображал сохранившиеся данные (он открывается при нажатии на folder в ArchiveFrag, тот, что посередине)

25cf9d85fd4e68e7870b7882662c27c6.png

Кстати, это именно тот самый момент, на котором я поняла, что надо использовать базу данных. Чтобы при открытии сохраненной заметки по folder«s id получать нужные данные и отображать их. Ну и еще из примечательного — обновление того же БД, если пользователь изменит/удалит какой-либо текст

25dd736abf2bff7a57bbc86d680f8606.png

Внимательный читатель номер два (или один и тот же читатель, но вдвойне внимательный) может задаться вопросом, а почему, собственно, в этом новом фрагменте отсутствует кнопка для разделения текста (в девичестве choicebar_split). Ответ прост: она мне просто не нужна. При создании заметки в БД уже заносится делитель — двоеточие, точка с запятой или новая строка. И при редактировании в уже сохраненной заметке это деление автоматически применяется. Если же делитель не выбран еще на этапе создании заметки (за что, кстати, дизреспект), то в конечный builder notification будет передана не какая-то фраза из всего написанного пользователем, а все полотно текста (благо, у меня стоит метод отображения для Notification setStyle (new NotificationCompat.BigTextStyle ().bigText (intent.getStringExtra («text»)))) 

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

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

Возвращаемся в родненький ArchiveFrag и видим, что жмакаются не только сами папки, но и кнопки в их правом верхнем углу. И если с delete и choose color (здесь использовала готовую библиотеку AmbilWarnaDialog из 'com.github.yukuku: ambilwarna:2.0.1') все понятно, то с create shortcut не все так радужно, как представлялось (а жаль)

Самое важное и одновременно самое сложное при создании Shortcut это метод setIntent, а точнее описание Intent, который мы передаем. Из EXTRA_TEXT, содержащий id и индекс, будем вытаскивать название папки и фразу из БД соответственно. Важно, что для работы EXTRA_TEXT при создании Intent надо определить метод ACTION_SEND, который позволяет передавать данные между двумя Activity. А откуда же взялось второе Activity, если я работаю исключительно во Fragments (не забываем эпизод великой депрессии из пункта 2)? Через Intent нельзя открыть Service, а мне это было необходимо почти также сильно как кислород. Так что пришлось создать новое activity — ReceivActivity, из которого сервис и открывался.

Builder shortcut:

b11f6538a1921bc38ee5d34140ff6ce5.png

В ReceiverActivity получаем данные из Shortcut«s Intent, с помощью них выделяем необходимые строки из БД и затем передаем в NotyService уже все готовенькое:

d41e663b733b321cff8ca05f30e5003e.png

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

Service тоже описывается вполне стандартно, только в методе onStartCommand вызываю функцию sendNoty, куда передаю intent, полученный еще в ReceiverActivity, и функцию по созданию канала для оповещения. Intent нужен чтобы в Builder Notification во всяких параметров типа setContentTitle, setContentText можно было бы вытащить по ключам (которые мы тоже передавали) необходимые данные из БД: intent.getStringExtra («title»)

5.5 Отдельная головная боль — SearchView, хотя может оно мне больше всего не понравилось, потому что разбиралась с ним на последнем издыхании. Не буду тянуть кота за яи…хвост, и просто скажу, что в Adapter написала метод создающий отфильтрованный список (сам метод вызываю как adapter.getFilter ().filter (parserString) в одном из методов setOnQueryTextListener в ArchiveFrag)

Во всех туториалах, которые я находила, почему-то не использовали готовый элемент дизайна SearchView, а использовали menu. Меня этот подход не устраивал, поэтому пришлось повозиться, но в итоге я победила.

5735d50406416331a9c2f9bd46b8ce62.png

Несколько видео с примерами того, как работает приложение:

Небольшая фан статистика: на проект от идеи до релиза было потрачено около 2-х недель (по 4–6 часа в день примерно) (p.s. хотя я растянула это ровно на месяц), строк написано чуть больше 1300 (без учета файлов в папках drawable и layout)

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

3104a8bc72466c30ccf28d90afdd02d6.png

Легенда:  

  • зеленая стрелка — означает, что процесс происходит в Parent файле

  • голубая стрелка — по нажатию на определенную кнопку/или автоматически открывается новый JavaClass с layout (например, это Fragments и AlertDialogs)

  • оранжевый цвет — все, связанное с базой данных

Итоги: по ощущениям в этом, казалось бы, небольшой проекте я изучила разнообразный функционал Java доступный для Android. Все началось с простейших идей — объявление переменных, запоминание информации, вводимой пользователем, и различные события, происходящее по нажатию на кнопки, а потом появились Adapter, Service, SearchView (да, он мне сильно нервы помотал, по этому стоит в одном ряду с вещами, для которых создаются отдельные Java-файлы), разобрала работу двух разных Builder — для Notification и для Shortcut, а также работала с собственным классом и базой данных. Кажется, буду я сама себе устроила курс по Java, от простых задач к сложным, покрывающий довольно обширный пласт знаний (особенно как для абсолютного новичка). Конечно, код не идеальный, не совсем чистый и есть что оптимизировать и куда расти, но самое главное — я получила свое желанное приложение.

© Habrahabr.ru