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

По сотрудничеству писать @haroncode
Download Telegram
🎩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
Куда можно навесить разрешения и как запрашивать?
👇
😁18👍4🔥4
{1/2} Теперь погнали к более практической части работы с разрешениями. Раньше запрос разрешения выглядел так, проверяем дано ли оно вообще, если нет то сначала при помощи специальной функции запускаем запрос разрешения. Результат такого запроса приходил в метод onActivityResult. В котором нужно было проверить есть ли результат, а тот ли id запроса и самому раскрасить данные, геморройная схема.

С появлением Result API все стало проще, теперь мы просто описываем лямбду куда придет результат. Хоть я и не в восторге от Result API, запрашивать разрешения просто сказка. Скорее всего вы и так это знаете, ведь метод onActivityResult задеприкейтили и result API сейчас это единственный вариант. 

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

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

📱Мобильные системы устроены таким образом, чтобы у клиента было ощущение, что он сидит в одном приложении. Об этом я писал с одной из своих недавних статей. Android так и устроен, мы всегда видим Activity какого-то приложения. Даже когда вы переходите в лаунчер, Activity вашего приложения просто меняется на Activity лаунчера. 

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

Есть такой атрибут, указываемый при объявлении компонента в манифесте, и он показывает, можно ли этим компонентом пользоваться кем-то кроме нашего приложения, называется exported. Делаем exported как false и забываем про какие-либо проблемы с безопасностью, ведь этот компонент можем запустить только мы и никто больше. 

Однако если у компонента настроен intent-filter сделать его НЕ exported, уже не получится. Самый частый кейс использования intent-filter это когда вам нужно сделать deeplink или функциональность для отправки email. В таком случае ваш компонент сможет запустить любое приложение в системе. Однако возможно, вы не хотите, чтобы вас мог использовать любой (двояко получилось согласен). 

🔐И тут уже на сцену выходят кастомные permission. В кейсе с intent-filter все довольно просто. Объявляем кастомное разрешение, ставим ему protectionLevel=“signature” (из прошлого поста) и все. Теперь только ваши приложения, подписанные одним ключом смогут использовать ваши компоненты.

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

Зачем это нужно? Ну смешно жи, представьте в какой растерянности будет пользователь, когда увидит системный диалог с текстом “Разрешите доебаться?”. В реальности разумеется так никто не делает, ибо зачем? Если мы открываем свою Activity мы наоборот всеми правдами и неправдами должны привлекать пользователя и другие приложения нас вызвать, для увеличения конверсии и все такое.
👍29😁5
{2/2} Как упоминал ранее, кастомные разрешения можно повесить на все что угодно, поэтому все что в посте было рассказано про Acitivity работает и с другим компонентами. Еще интересно тут с Broadcast Receiver. Когда вы отправляете событие, можно еще приложить строку в которой будет указано разрешение. Другое приложение обязано иметь это разрешение, чтобы вообще получить это событие. Так можно защитить еще и рассылку событий м/у вашими приложениями, потому как когда вы отправляете событие, его потенциально может получить не только ваше приложение.

Короче совет. Если тема интересна, попробуйте поиграться с кастомными разрешениями, так вы точно поймете как работает эта система и на тех. собесах вам не будет равных по этой теме.
👍38
Что за сложности с разрешениям для ContentProvider?
👇
👍25🔥9
Если вы думали что я пропал, то нет, я просто хренову тучу времени убил на эксперименты с Content Provider, чтобы вам тут не напиздеть не ввести в заблуждение. Теперь у меня есть куча всего интересного чего я могу рассказать, что будет интересно даже прожженными сеньорам.

Content Provider я выделил отдельно вот по какой причине. У него в отличие от других компонентов есть несколько интересных моментов касательно установки разрешения. Так как Content Provider это основной компонент на него, как и на другие можно навесить обычное разрешение. Устанавливаем такое, и теперь только приложение с нужным разрешением сможет получить от нас какие-либо данные. Помимо этого можно exported сделать false и Content Provider получится приватным и только ваше приложение сможет его использовать. Тут все как у всех других компонентов ничего интересного.

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

И самое интересное и запутанная хрень в Content Provider это grantUriPermissions. Лучше всего объяснить на примере. Смотрите, возможно вам когда-либо выпадала задача показать pdf файл в любом другом приложении. Этот файл доступен только вашему приложению, т.е он не лежит в открытой публичной папке. И вот каким образом дать разрешение другому приложению конкретно вот на этот файл?

Если вы пойдете на stackoverflow, там будет дикий запад с костылями про то, как это сделать. Поискав чуть лучше, можно будет найти FileProvider. Суть проста, FileProvider это частный случай Content Provider который работает только с файлами. А нужен он для того, чтобы вы могли раздавать свои приватные файлы другим приложениям. 

Идея тут должна быть понятна, мы не можем перегнать весь файл в bundle и отправить его в другое приложение, мы можем другому приложению передать только путь до нашего файла. Однако, что другое приложение сможет сделать с этим путем? Да ничего, система пошлет его лесом как только он попробует по этому пути перейти. А вот FileProvider позволяет легально обойти это ограничение. 

Если вы зайдете в доку FileProvider, там будет сказано, что вам нужно сделать этот провайдер как exported=false. И тут внимательный читатель задастся вопросом: “Если exported=false то как он вообще что-то может передать другому приложению, ведь провайдер становится приватным“. Все так и есть, FileProvider делается приватным, однако мы также указываем grantUriPermissions=true и вот тут, начинается самое интересное. 

GrantUriPermissions это настройка, которая позволяет другим приложениям выдавать временный доступ до конкретного Uri (если говорим про FileProvider то условно путь до файла). Однако работает она не сама по себе, мы должны явно сообщить об этом системе, и тут два пути:
👉 Первый это когда мы формируем Intent на показ файла, нужно добавить флаг ‘FLAG_GRANT_READ_URI_PERMISSION’  и приложение, которое получит этот Intent получить также право временно(до перезагрузки устройства) обращаться к переданному Uri(к нашему файлу). 
👉 Второй, мы можем программно вызывать метод grantUriPermission, передать в него наш Uri а также пакет конкретного приложения, которому мы это права даем. Ну и есть зеркальный метод revokeUriPermission, который это разрешение отзывает.

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

Однако это не все самое прикольное. Я обнаружил интересную толи багу, толи фичу связанную с FLAG_GRANT_READ_URI_PERMISSION, о которой расскажу в следующем посте.
🔥58👍20
Интересное поведение ACTION_SEND

👇
🔥5