Dev Easy Notes
3.17K subscribers
123 photos
1 video
147 links
Работаю в IT уже 8 лет. Рассказываю про разработку простым языком. Полезность скрыта под тупыми шутками и слоем мата. Лучший underground канал про разработку, который вы сможете найти.

По сотрудничеству писать @haroncode
Download Telegram
📝 Инкрементальность конфигурации
👍9
Вторая самая бесячая проблема Gradle, это то, что он не умеет кешировать конфигурации. Напомню, Gradle работает в три этапа:

1️⃣ Инициализация. Когда Gradle бегает по файлам и собирает инфу о том, сколько у нас вообще есть модулей и создает объекты Project.
2️⃣ Конфигурация. Запускаются все скрипты build.gradle, подтягиваются все таски и строится граф этих самых тасок.
3️⃣ Выполнение тасок. Тут все просто, Gradle просто запускает нужные таски в нужном порядке

Ну так и вот, на нашем проекте расчет конфигурации занимает (если верить метрикам) в среднем около 40 сек. Почти минута! Минута пенальти, просто чтобы он вообще начал билдить.

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

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

Помимо отсутствия кеширования и инкрементальности, этап конфигурации не умеет параллелится. Что довольно грустно, у нас сейчас куча ядер в компе, но во время конфигурации используется только одно.

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

Вообщем ситуация такая, каждый раз запуская билд, я сижу в котле ярости, ведь я ничего не менял, а тем не менее опять должен ждать пока рассчитается конфигурация.
👍18👏2🤔1
💽 Кэш Gradle
👍4
Итак. Я немного проебался и не уточнил всю инфу, благо в коментах меня поправили. Более того, слона то я и не заменил, оказывается у нас на проекте оно давно используется.

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

1️⃣ org.gradle.unsafe.configuration-cache. Самая рекомендуемая опция, все довольно очевидно, если input для конфигурации не меняется, т.е не меняются скрипты или другие входные данные все будет закешированно и повторно запускаться не будет. Работает хорошо, но для настройки есть потешные параметры вроде того, сколько ошибок мы можем выдержать прежде чем кэш упадает.

2️⃣ org.gradle.configureondemand. Не совсем кеширование, а скорее мы говорим Gradle, давайка ты не будешь конфигурацию запускать на всем проекте, а только вот на нужных мне модулях. Это будет работать только в том случае, если у вас разработка ведется в небольших sample проектах, т.е когда вы не собираете большой проект со всеми модулями, а только необходимые вам фичи.

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

Однако несмотря на то, что Gradle таки научился сохранять кэш проблема с инкрементацией остается актуальной. В примере с кешированием конфигурации, стоит поменять один скрипт, у вас перезапустится вся конфигурация. Это естестенно приводит к тому, что стоит вам переключится на другую ветку, с большой долей вероятности вы опять будете ждать конфигурацию
👍21
🦚 Groovy
😁5🥰3
Про язык я планировал сделать один пост, но он чет разросся, поэтому я сделаю два поста, один про Groovy и уже второй про Kts.

Бывало у вас такое пытаешься ты написать скрипт для Gradle, и во время его написания, будто магия какая-то происходит. В одном месте так нужно писать, в другом по другому. 

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

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

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

В момент разработки Gradle таких языков было всего 2: Groovy и Clojure. В расчет не берем всяких JPython и подобных монстров. Clojure не стали использовать так как, он вышел буквально за год до выхода Gradle и его никто не воспринимал всерьез. Плюс, писать скрипты в стиле Lisp не каждый захочет. Остался только один единственный вариант – Groovy. 

Groovy отлично подходил под требования. Одновременно и динамический и типизированный, работает на базе JVM и имеет кучу синтаксического сахара. Вот только этот самый сахар и создает ощущение магии для всех, что пытался погрузиться в тему с Gradle. Вот смотрите, на примере, базовая вещь, как можно указать Gradle  где находятся сорцы:

1️⃣ sourceSets {
    main {
        java {
            srcDirs('src')
        }
    }
}


2️⃣ sourceSets.main.java.srcDirs = [‘src’]
3️⃣ sourceSets.main.java.srcDirs('src')

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

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

☝️У разработчиков самой билд системы должна быть возможность проводить оптимизации исходя из того, что есть только один способ что-то сделать. Когда ты точно уверен, что у клиента нет возможности сделать что-то иначе, это развязывает тебе руки в оптимизации.

✌️У разработчиков, которые используют билд систему, не должно быть сложностей в изменении скриптов. С Gradle же ты начинаешь в угадайку играть, перебирая различные варианты скопированные с инета. 

Ну что тут можно сказать. Скорее всего в ближайшие годы мы не слезем с иглы Gradle. Поэтому если хотите уменьшить уровень магии и упростить себе жизнь, посвятите часок другой изучению Groovy.
🔥22👍64
🎩Kts

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

С одной стороны это круто, теперь все действительно очевиднее, так как сложно на Kotlin написать что-то неожиданное. Однако, Kotlin ни разу не скриптовый язык и за все ништяки мы платим тем, что теперь скрипты перед выполнением компилируются. 

Если у вас мелкий проект, разницы вы не заметите. Однако при росте проекта у вас начнутся проблемы. Смотрим на табличку, тест проводили на довольно свежей версии Gradle. Тут явно прослеживается проблема kts, при первом запуске он медленнее Groovy в 1.6 раз. Если конфигурация проекта занимает допустим 30 секунд, теперь будет занимать под 50. Разумеется билд кеш, спасает, однако при переключении с ветку на ветку…

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

В итоге вот вам рецепт:
1️⃣ build.gradle лучше писать на groovy, в них нет и не должно быть никакой логики, а только перечисление плагинов, конвенций и зависимостей для конкретного модуля.

2️⃣ Общие конфигурации выносим в конвенции и их уже можно писать на kts. Они будут компилироваться только в одном месте, это уже не так сильно будет бить по времени конфигурации.

3️⃣ Если появляется какая-то сложная логика, это лучше выносить в плагины. Сам плагин можно и нужно писать на kotlin, его можно будет сделать бинарным и тогда он вообще не будет компилироваться.

P.S Сори за долгое отсутствие, просто был небольшой отпуск, не волнуйтесь на канал я не забил)
32👍15🤔2🤯1
🗿 Ничто не истина, все дозволено
😁17
По какой причине все так не любят C++? Основная причина это недостаток дизайна C++, который слишком многое позволяет разработчику. Одни только макросы могут принести неожиданного поведения (реально можно через define заменить все true на false и потом наслаждаться шоу), а в одном из последних стандартов появилась метаклассы, которые буквально позволяют написать свой язык внутри C++.

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

Это все к чему, Gradle это C++ мира билд систем. В документации Bazel есть интересная фраза про системы вроде Gradle: too much power to engineers and not enough power to the system.

Это пожалуй главная проблема Gradle из которой вырастают все остальные и про которые я писал в прошлых постах. Он как и C++ позволяют  разработчику сделать очень многое, тем самым отстрелив ногу по шею. Легко можно взять и пойти в сеть во время конфигурации или файл или вообще по ssh отправить на удаленный сервер какую-то инфу.

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

tasks.findByPath("assemble")?.enabled = false

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

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

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

Ядро билд системы само решает в каком порядке нужно вызывать Rule и нужно ли их вообще перезапускать. Уже нет проблемы с side-effect потому как их просто невозможно сделать, система ударит вас по рукам.

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

Подводя итог, хотите разобраться в Gradle по лучше, посмотрите эти три доклада:
 👉 Самые базовы вещи
👉 Доклад Зиннатуллина про то, почему в Lift используют Bazel
👉 Также про Gradle, но уже чуть глубже
👍24🔥51
Что за Window и для чего он нужен?
🔥21
Так или иначе вы в коде встречали упоминание Window. Например, чтобы работать с inset самостоятельно, мы можем приказать системе не рассчитывать их за нас вот так:

WindowCompat.setDecorFitsSystemWindows(window, false)

Мне было интересно разобраться в том, что это за Window и что он делает. Сейчас я расскажу как это все работает. 

Window это элемент, который представляет собой прозрачный прямоугольник. К каждому Window прикреплен объект Surface. Surface это просто объект который владеет пикселями. У Surface есть Surface Flinger который уже рисует на девайсе наши View. Грубо говоря, именно на Window и происходит отрисовка всех наших View.

Причем этих Window может быть несколько на экране. Например, статус бар рисуется в своем отдельном Window, у Activity есть свой Window, у NavigationBar свой. Даже AlertDialog отрисовывается в своем отдельном Window, но об этом в другой раз.

Далее, у каждой Window есть ссылка на иерархию наших View. Когда вы в Activity вызываете метод setContentView, View создается и прикрепляется к Window. Вверху иерархии View всегда есть ViewRootImpl. Это специальная View которая ничего не отрисовывает, а только общается с Window. Другими словами наши View взаимодействуют с Window через эту ViewRootImpl. 

Теперь самое интересное, как происходит отрисовка. Когда View нужно перерисоваться, она вызывает invalidate, это по иерархии поднимается наверх до ViewRootImpl. Этот ViewRootImpl сообщает Window что нужно перерисовать View. Window вызывает метод lock у Surface и тот в ответ выдает Canvas. Тот самый Canvas который потом прикидывается в метод onDraw. После мы что-то вызываем на этом Canvas и затем Window вызывает метод unlockAndPost, тем самым отправляя наш Canvas в буфер на прорисовку. 

Интересно тут то, что когда мы что-то вызываем на Canvas, отрисовка происходит не сразу, мы лишь задаем правила того, как это будет нарисовано в будущем.
👍44🔥103
Штош, канал достиг 1000 подписчиков, вы все великолепны, всех обнял 🤗 Честно говоря я даже удивлен, не думал что канал с довольно узкой направленностью тем, наберет такое количество, меньше чем на год. Представьте, еще в апреле этого года на канале было меньше 20 подписчиков. 

Чтобы этот прост, не был просто постом, где я радуюсь циферке подписчиков, я еще раз немного расскажу про идею канала в целом. В частности, почему на канале нет и я надеюсь не будет новостей про разработку и обзора каких-то конкретных библиотек и фреймворков (за исключением Android Framework, но “вы не понимаете – это другое”).

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

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

Серьезно, последний год я почти не читаю статей, только в том случае если мне нужно решить мою проблему или сделать пост. Знаете что изменилось? Ничего, все осталось, как и было, я не отстаю по скорости и качеству от моих коллег. Отстаю только в развитии…

Именно поэтому я не вижу смысла в создании еще одного канала с новостями. Я искренне верю, что некоторые концептуальные знания гораздо важнее. Те знания которые не устаревают через полгода и реально позволяют стать лучше. Поэтому делитесь каналом если вам нравится, и приходите в комменты если что-то не понятно или охото меня поправить 😁
👍83🔥1913👏2
🏔️Ограничения
👍6
Итак, новый год на носу, душнить сложными темами уже не буду. Всем же интересно узнавать чужой опыт? Мне всегда было интересно, ведь можно посмотреть и например не наступать на те же грабли. Надеюсь этим постом я немного упрощу ваш путь в карьере.

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

Если бы я ушел из этой компаний раньше, сейчас бы зарабатывал в разы больше при прочих равных условиях. Почему я не ушел раньше? Раньше я не ушел потому, что мне хотелось уйти в действительно “крутую” компанию. А какой образ рисуется у нас в голове когда мы говорим про крутых ребят работающих в больших крутых компаниях? Правильно, это разработчик с выступлениями на конференциях, у него крутой github с библиотеками которые используют все. Опыта нужно лет 5 и свой подкаст конечно, без него вообще никак.

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

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

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

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

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

В итоге: я потратил кучу времени на вылизывание профиля в linkedin, где рассписывал все что делал. Красиво оформил GitHub с петпроектами, на которые также потратил кучу времени на рефакторинг, чтобы было все красиво. Потратил кучу времени на решение литкода. Пригодилось ли что-то из этого? Ну наверное только профиль в Linkedin. В мой Github никто не заглядывал и алгоритмы никто не спрашивал из всех 6 компаний куда я проходил собес.

Часто мы пытаемся соотвествовать виртуальным требованиям. Поэтому, в новом году, перестаньте надумывать. Пробуйте, смотрите на результат и пробуйте еще раз.
🔥53👍204
Мета пост

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

Посты разделил на три лагеря:

1️⃣ полезные для практики, которые могут повлиять на ваш код уже сейчас
2️⃣ просто теоретические, которые может быть будут полезны, но это не точно
3️⃣ софтскильные, скорее некоторые мысли на околоайтишные темы

🧑‍💻Посты, как-то применимые на практике:
👉 Основы функционального программирования
👉 Принцип разделения запросов и команд
👉 В чем разница м/у смертью Activity и смертью процесса?
👉 Фрагменты, фрагменты, фрагменты
👉 Разница между IO и Сomputation
👉 Неблокирующая синхронизация
👉 Мысли про многомодульность
👉 Что не так с Result API
👉 LiveData, плюсы минусы
👉 История ViewModel
👉 Хватит делать, проксирующие интеракторы

📚Теоретические посты:
👉 Немного про Compose
👉 Как работает LeakCanary?
👉 Как система ловит ANR?
👉 Что такое DRM и как работает?
👉 Серия постов про то, как работает Android
👉 Gradle и что с ним не так (отнес в теорию, потому как просто жаловался на него и практического так довольно мало)
👉 Что за Window и для чего он нужен?

🗣 Софткильные посты:
👉 Прокрастинация идеального кода
👉 Немного про собесы
👉 Скорочтение
👉 Фича команды vs Отдельные команды(Хабы, Гильдии, Вертикали т.д)
👉 Ограничения которые мы сами себе придумываем
🔥45👍143🥰3😁1
Активности на канале пока нет, просьба понять и простить)

Я понемного выхожу из пост-новогодней депрессиии и начинаю приходить в себя. Уже есть пара идей для постов, но пишутся пока они со скрипом. Пишу просто чтобы, успокоить вас если вдруг переживали.
👍5231🥰5🤯1
🔐 Разрешения

Начнем 2023 год с разговора о разрешениях. Казалось бы, что там такого сложного в этих разрешениях в Android? Два основных типа, одни запрашиваем, вторые даются при установке. Однако когда начинаешь копать, оказывается, что их там больше 2 типов. Еще какие-то разрешения по подписи, про которые любят спрашивать в Яндексе. Оказывается, что можно навесить разрешение на любой компонент, а на ContentProvider вообще можно навесить хренову тучу на любой чих и поди разберись в этой каше. 

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

👉 Как развивались разрешения в Android?
👉 Какие типы есть и как они работают?
👉 Куда их можно навесить и как запрашивать?
👉 Что за сложности с разрешениями для ContentProvider?
🔥62👍93
🕰️ Как развивались разрешения в Android?
👍25😁14
В первых версиях Android о разрешениях вообще мало кто задумывался. Был только один тип разрешений (на самом деле два, но в сейчас не важно). Просто указываешь их в манифесте и все, дело в шляпе. Однако пользователям это было не очень удобно. Допустим есть крутое приложение, которое тебе очень нравится, а оно требует разрешения на гео локацию, и вообще не понятно зачем. И ты либо даешь разрешение, либо идешь лесом и ищешь другое приложение, которое уважает твою приватность.

Причем на заре Android, мало кто вообще обращал внимание на то, что там приложение просит. Ну считывает оно локацию, ну и что, что оно сделает с этими данными? Потом конечно пришел Facebook и понеслась) 

В любом случае все понимали, что с этим нужно что-то делать. Нужно дать возможность пользователям устанавливать приложение, и при этом выбирать к каким данным приложение имеет доступ, а к каким не имеет. Чтобы решить эту проблему, далеко ходить не нужно, достаточно подглядеть у конкурентов. В iOS чуть ли не с первых версий была поддержка разрешений, которые пользователь давал в процессе использования приложения. Android решили пойти тем же путем и появились runtime permission.

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

В 11 Android появились “one time permission” – разрешения которые можно дать один раз. Также система теперь может отобрать у вас разрешение, если вашим приложением давно не пользовались. 

В целом это вся история развития разрешений в Android. Как можно догадаться сильно резких поворотов с ними не было и  главным изменением в истории стало именно появление runtime permission. Однако изменились API взаимодействия с разрешениями, это мы рассмотрим в следующих постах.
👍50🔥1
Какие типы разрешений есть и как они работают?
👇
👍16🔥10
Итак, у нас всего 4 типа разрешений. Все эти 4 типа можно разделить на две основные группы:

 👉 Install-time - которые даются во время установки 
 👉 Runtime - которые нужно запросить во время работы приложения

Перед тем, как идти дальше важно понимать, что помимо разрешений, которые уже встроены в систему (как например интернет или локация) можно создавать свои разрешения. И свои разрешения могут быть как Install-time, так и Runtime. Зачем это нужно мы разберем далее, главно держать это в голове.

В группу Install-time входят 🤙Normal и ✍️ Signature Permissions. Первые это самые обычные разрешения, которые не дают доступа к критичным данным, и список таких разрешений мы можем увидеть в google play. Со вторыми, которые Signature уже интереснее. Эти разрешения система дает автоматически, для приложений которые подписаны одним ключом. Допустим есть приложение A которое создало разрешение типа Signature и есть приложение B, которое прописало в своем манифесте это самое разрешение. Если оба этих приложения подписаны одним и тем же ключом, значит приложение B автоматически получает это разрешение, если же ключи разные, то соответственно это разрешение не дается. 

✍️ Для чего нужен Signature Permissions? Этот механизм позволяет создавать экосистемы из приложений, когда на всех один и тот же аккаунт. Яркий пример тут Яндекс со своим Яндекс плюсом, логинясь в одном приложении, вы автоматически логинитесь во всех остальных. Другими словами, Signature Permissions один из механизмов, как можно расшарить данные вашего приложения только тем, кому вы доверяете.

В группе Runtime тоже есть два вида разрешений: ❗️Danger и 🦚 Special Permissions. Формально Special не относится к Runtime, но мне показалось что они стоят очень близко и так проще. 

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

🦚 И последние это Special Permissions. Это уже довольно экзотические разрешения, которые используют всякие приложения утилиты. Сюда относится разрешение рисовать UI поверх других приложений, что например используют приложения для записи экрана. Получить их можно также только с позволения пользователя, и причем довольно не просто. Дело не обойдется одним системным диалогом, тут нужно отправить пользователя в конкретное место в настройках, да еще и рассказать чего он там должен сделать. С некоторых пор и отправка Pending Intent в точно заданное время тоже теперь относится к специальным разрешениям. Насколько я понимаю это попытка гугла убрать с рынка сторонние будильники. 

Независимо от того, какой это тип разрешений работают они по одной и той же схеме, которая базируется на системе привилегий Unix. Про этот механизм писал тут. Если вдруг лень читать, то давайте вкратце. Каждому приложению в системе назначается свой пользователь (не реальный, а просто абстракция) у которого есть свой UID. Далее в системе Unix для раздачи прав есть такая вещь как группы, в которую входят эти пользователи. Назначаем какие права конкретной группе и все участники получают эти права. 

Каждый раз, когда пользователь дает приложению разрешение на те или иные данные, UID этого приложения добавляется в соответствующую группу, у которой есть права на эти данные. Иии собственно все, когда вы запрашиваете данные о локации, в сервисе проводится проверка, входит ли UID вашего приложения в нужную группу, и если нет, то отпинывает с ошибкой.
🔥38👍13👏3🥰1