Так или иначе вы в коде встречали упоминание Window. Например, чтобы работать с inset самостоятельно, мы можем приказать системе не рассчитывать их за нас вот так:
Мне было интересно разобраться в том, что это за 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 вызывает метод
Интересно тут то, что когда мы что-то вызываем на Canvas, отрисовка происходит не сразу, мы лишь задаем правила того, как это будет нарисовано в будущем.
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🔥10❤3
Штош, канал достиг 1000 подписчиков, вы все великолепны, всех обнял 🤗 Честно говоря я даже удивлен, не думал что канал с довольно узкой направленностью тем, наберет такое количество, меньше чем на год. Представьте, еще в апреле этого года на канале было меньше 20 подписчиков.
Чтобы этот прост, не был просто постом, где я радуюсь циферке подписчиков, я еще раз немного расскажу про идею канала в целом. В частности, почему на канале нет и я надеюсь не будет новостей про разработку и обзора каких-то конкретных библиотек и фреймворков (за исключением Android Framework, но “вы не понимаете – это другое”).
У нас в обществе и особенно в индустрии складывается культ продуктивности. Существует миф, что хорошим разрабом ты можешь стать только если ты знаешь всех селебрити разработки, и постоянно следишь на всеми новинками, читаешь все статьи из новостных каналов и т.д. Этот миф исходит из нашей гормональной системы которая очень просто взламывается. Сама эта система работает исключительно для нашего выживания, и из-за мифа о том, что в разработке все очень быстро меняется она, считает что для нашего выживания нужно всегда следить за новостями.
Все это просто миф, чтение статей не сделает вас хорошими разработчиками, просмотр докладов о том, как работает та или иная библиотека тоже. Сами вдумайтесь, что делает разработчика крутым? Если так подумать, то наверное хорошо выполненные задачи, сделанные быстро и качественно. Помогает ли тут чтение статей, ну частично да, но не сильно. Помогает именно процесс решения задач.
Серьезно, последний год я почти не читаю статей, только в том случае если мне нужно решить мою проблему или сделать пост. Знаете что изменилось? Ничего, все осталось, как и было, я не отстаю по скорости и качеству от моих коллег. Отстаю только в развитии…
Именно поэтому я не вижу смысла в создании еще одного канала с новостями. Я искренне верю, что некоторые концептуальные знания гораздо важнее. Те знания которые не устаревают через полгода и реально позволяют стать лучше. Поэтому делитесь каналом если вам нравится, и приходите в комменты если что-то не понятно или охото меня поправить 😁
Чтобы этот прост, не был просто постом, где я радуюсь циферке подписчиков, я еще раз немного расскажу про идею канала в целом. В частности, почему на канале нет и я надеюсь не будет новостей про разработку и обзора каких-то конкретных библиотек и фреймворков (за исключением Android Framework, но “вы не понимаете – это другое”).
У нас в обществе и особенно в индустрии складывается культ продуктивности. Существует миф, что хорошим разрабом ты можешь стать только если ты знаешь всех селебрити разработки, и постоянно следишь на всеми новинками, читаешь все статьи из новостных каналов и т.д. Этот миф исходит из нашей гормональной системы которая очень просто взламывается. Сама эта система работает исключительно для нашего выживания, и из-за мифа о том, что в разработке все очень быстро меняется она, считает что для нашего выживания нужно всегда следить за новостями.
Все это просто миф, чтение статей не сделает вас хорошими разработчиками, просмотр докладов о том, как работает та или иная библиотека тоже. Сами вдумайтесь, что делает разработчика крутым? Если так подумать, то наверное хорошо выполненные задачи, сделанные быстро и качественно. Помогает ли тут чтение статей, ну частично да, но не сильно. Помогает именно процесс решения задач.
Серьезно, последний год я почти не читаю статей, только в том случае если мне нужно решить мою проблему или сделать пост. Знаете что изменилось? Ничего, все осталось, как и было, я не отстаю по скорости и качеству от моих коллег. Отстаю только в развитии…
Именно поэтому я не вижу смысла в создании еще одного канала с новостями. Я искренне верю, что некоторые концептуальные знания гораздо важнее. Те знания которые не устаревают через полгода и реально позволяют стать лучше. Поэтому делитесь каналом если вам нравится, и приходите в комменты если что-то не понятно или охото меня поправить 😁
👍83🔥19❤13👏2
Итак, новый год на носу, душнить сложными темами уже не буду. Всем же интересно узнавать чужой опыт? Мне всегда было интересно, ведь можно посмотреть и например не наступать на те же грабли. Надеюсь этим постом я немного упрощу ваш путь в карьере.
Расскажу про одну из первых работ. Меня захантили знакомые ребята в свою недавно созданную галеру в небольшом городке Сибири. В самом начале было весело, крутые проекты печеньки в офисе. Однако со временем понимаешь, что в мелкой галере ты быстро упираешься в потолок, потому как у модели взять джуна подевешве и продать как сеньора подороже есть ограничения и пора бы искать место по круче. Однако я очень долго не уходил с той компании и это бездействие было ошибкой.
Если бы я ушел из этой компаний раньше, сейчас бы зарабатывал в разы больше при прочих равных условиях. Почему я не ушел раньше? Раньше я не ушел потому, что мне хотелось уйти в действительно “крутую” компанию. А какой образ рисуется у нас в голове когда мы говорим про крутых ребят работающих в больших крутых компаниях? Правильно, это разработчик с выступлениями на конференциях, у него крутой github с библиотеками которые используют все. Опыта нужно лет 5 и свой подкаст конечно, без него вообще никак.
Все эти ограничения были лишь в моей голове, которые родились из-за того, что я слушал подкасты именитых чуваков и ходил на конференции. Когда ты видишь ребят на конференциях, все из которых работают на больших продуктах, часто выступают и еще кучу всего, твой мозг делает простой вывод. Для того чтобы даже подумать о работе в крутой компании нужно создать крутую либу и выступить на конфе. Затем сделать крутое, красивое и запоминающееся резюме. Иначе твое резюме даже смотреть не будут. И вот только потом, желательно через реферальную систему нужно заходить в компанию.
Действительно ли это так? Да нет конечно, я сам поместил свой разум в клетку своих же домыслов. Я не думал о тысячах работников крупных компаний, которые нигде не выступают и которые просто откликнулись на hh. У которых не то что, хорошее резюме, а просто пара строчек о том, где они до этого работали и каких технологии знают. Я попался на ошибку выжившего.
Знаете есть такой интересный видос, где вокруг божей коровки чертят круг маркером, а она не может за него выйти, т.к думает что это стена. Вот мы часто косплеим эту божую коровку. Потом обнаружил что есть даже специальное слово для этого Overthinking, если не читали то прям рекомендую.
Хочу донести одну идею, не повторяйте мои ошибки, не придумывайте себе ограничений. У компаний и так дофига ограничений по тому, кого они могут нанимать. Есть ограничения на уровень знаний который им нужен, ограничения по зарплате, по месту работы и еще куча всего. При этом мы еще и свои ограничения вводим, на то, что нам кажется нужно знать прежде чем откликаться на вакансию. Создаем эти ограничения нашим друзьям которые хотят попробовать то, что мы ссым делать.
Проблема часто именно в этом, вместо того, чтобы пробовать и потом делать выводы, мы тратим уйму времени на изучение алгоритмов которые нас почти никогда не спросят, доводим английский до совершенства, когда хватило бы и уровня B1, изучаем всю доку по Android, хотя чаще всего достаточно знать работу основных компонентов. Разумеется есть компании, где нужны алгоритмы, но таких компаний меньшинство и чаще всего про это явно пишут.
В итоге: я потратил кучу времени на вылизывание профиля в linkedin, где рассписывал все что делал. Красиво оформил GitHub с петпроектами, на которые также потратил кучу времени на рефакторинг, чтобы было все красиво. Потратил кучу времени на решение литкода. Пригодилось ли что-то из этого? Ну наверное только профиль в Linkedin. В мой Github никто не заглядывал и алгоритмы никто не спрашивал из всех 6 компаний куда я проходил собес.
Часто мы пытаемся соотвествовать виртуальным требованиям. Поэтому, в новом году, перестаньте надумывать. Пробуйте, смотрите на результат и пробуйте еще раз.
Расскажу про одну из первых работ. Меня захантили знакомые ребята в свою недавно созданную галеру в небольшом городке Сибири. В самом начале было весело, крутые проекты печеньки в офисе. Однако со временем понимаешь, что в мелкой галере ты быстро упираешься в потолок, потому как у модели взять джуна подевешве и продать как сеньора подороже есть ограничения и пора бы искать место по круче. Однако я очень долго не уходил с той компании и это бездействие было ошибкой.
Если бы я ушел из этой компаний раньше, сейчас бы зарабатывал в разы больше при прочих равных условиях. Почему я не ушел раньше? Раньше я не ушел потому, что мне хотелось уйти в действительно “крутую” компанию. А какой образ рисуется у нас в голове когда мы говорим про крутых ребят работающих в больших крутых компаниях? Правильно, это разработчик с выступлениями на конференциях, у него крутой github с библиотеками которые используют все. Опыта нужно лет 5 и свой подкаст конечно, без него вообще никак.
Все эти ограничения были лишь в моей голове, которые родились из-за того, что я слушал подкасты именитых чуваков и ходил на конференции. Когда ты видишь ребят на конференциях, все из которых работают на больших продуктах, часто выступают и еще кучу всего, твой мозг делает простой вывод. Для того чтобы даже подумать о работе в крутой компании нужно создать крутую либу и выступить на конфе. Затем сделать крутое, красивое и запоминающееся резюме. Иначе твое резюме даже смотреть не будут. И вот только потом, желательно через реферальную систему нужно заходить в компанию.
Действительно ли это так? Да нет конечно, я сам поместил свой разум в клетку своих же домыслов. Я не думал о тысячах работников крупных компаний, которые нигде не выступают и которые просто откликнулись на hh. У которых не то что, хорошее резюме, а просто пара строчек о том, где они до этого работали и каких технологии знают. Я попался на ошибку выжившего.
Знаете есть такой интересный видос, где вокруг божей коровки чертят круг маркером, а она не может за него выйти, т.к думает что это стена. Вот мы часто косплеим эту божую коровку. Потом обнаружил что есть даже специальное слово для этого Overthinking, если не читали то прям рекомендую.
Хочу донести одну идею, не повторяйте мои ошибки, не придумывайте себе ограничений. У компаний и так дофига ограничений по тому, кого они могут нанимать. Есть ограничения на уровень знаний который им нужен, ограничения по зарплате, по месту работы и еще куча всего. При этом мы еще и свои ограничения вводим, на то, что нам кажется нужно знать прежде чем откликаться на вакансию. Создаем эти ограничения нашим друзьям которые хотят попробовать то, что мы ссым делать.
Проблема часто именно в этом, вместо того, чтобы пробовать и потом делать выводы, мы тратим уйму времени на изучение алгоритмов которые нас почти никогда не спросят, доводим английский до совершенства, когда хватило бы и уровня B1, изучаем всю доку по Android, хотя чаще всего достаточно знать работу основных компонентов. Разумеется есть компании, где нужны алгоритмы, но таких компаний меньшинство и чаще всего про это явно пишут.
В итоге: я потратил кучу времени на вылизывание профиля в linkedin, где рассписывал все что делал. Красиво оформил GitHub с петпроектами, на которые также потратил кучу времени на рефакторинг, чтобы было все красиво. Потратил кучу времени на решение литкода. Пригодилось ли что-то из этого? Ну наверное только профиль в Linkedin. В мой Github никто не заглядывал и алгоритмы никто не спрашивал из всех 6 компаний куда я проходил собес.
Часто мы пытаемся соотвествовать виртуальным требованиям. Поэтому, в новом году, перестаньте надумывать. Пробуйте, смотрите на результат и пробуйте еще раз.
🔥53👍20❤4
Мета пост
Итак, все сейчас на отдыхе и отходят от нового года. Честно говоря писать новые посты на данный момент дико лень, поэтому мне пришла в голову гениальная идея. Я решил сделать мета пост, который будет представлять собой ссылки на все интересные посты которые были за прошлый год, чтобы вы сразу могли найти интересующую вас тему.
Посты разделил на три лагеря:
1️⃣ полезные для практики, которые могут повлиять на ваш код уже сейчас
2️⃣ просто теоретические, которые может быть будут полезны, но это не точно
3️⃣ софтскильные, скорее некоторые мысли на околоайтишные темы
🧑💻Посты, как-то применимые на практике:
👉 Основы функционального программирования
👉 Принцип разделения запросов и команд
👉 В чем разница м/у смертью Activity и смертью процесса?
👉 Фрагменты, фрагменты, фрагменты
👉 Разница между IO и Сomputation
👉 Неблокирующая синхронизация
👉 Мысли про многомодульность
👉 Что не так с Result API
👉 LiveData, плюсы минусы
👉 История ViewModel
👉 Хватит делать, проксирующие интеракторы
📚Теоретические посты:
👉 Немного про Compose
👉 Как работает LeakCanary?
👉 Как система ловит ANR?
👉 Что такое DRM и как работает?
👉 Серия постов про то, как работает Android
👉 Gradle и что с ним не так (отнес в теорию, потому как просто жаловался на него и практического так довольно мало)
👉 Что за Window и для чего он нужен?
🗣 Софткильные посты:
👉 Прокрастинация идеального кода
👉 Немного про собесы
👉 Скорочтение
👉 Фича команды vs Отдельные команды(Хабы, Гильдии, Вертикали т.д)
👉 Ограничения которые мы сами себе придумываем
Итак, все сейчас на отдыхе и отходят от нового года. Честно говоря писать новые посты на данный момент дико лень, поэтому мне пришла в голову гениальная идея. Я решил сделать мета пост, который будет представлять собой ссылки на все интересные посты которые были за прошлый год, чтобы вы сразу могли найти интересующую вас тему.
Посты разделил на три лагеря:
1️⃣ полезные для практики, которые могут повлиять на ваш код уже сейчас
2️⃣ просто теоретические, которые может быть будут полезны, но это не точно
3️⃣ софтскильные, скорее некоторые мысли на околоайтишные темы
🧑💻Посты, как-то применимые на практике:
👉 Основы функционального программирования
👉 Принцип разделения запросов и команд
👉 В чем разница м/у смертью Activity и смертью процесса?
👉 Фрагменты, фрагменты, фрагменты
👉 Разница между IO и Сomputation
👉 Неблокирующая синхронизация
👉 Мысли про многомодульность
👉 Что не так с Result API
👉 LiveData, плюсы минусы
👉 История ViewModel
👉 Хватит делать, проксирующие интеракторы
📚Теоретические посты:
👉 Немного про Compose
👉 Как работает LeakCanary?
👉 Как система ловит ANR?
👉 Что такое DRM и как работает?
👉 Серия постов про то, как работает Android
👉 Gradle и что с ним не так (отнес в теорию, потому как просто жаловался на него и практического так довольно мало)
👉 Что за Window и для чего он нужен?
🗣 Софткильные посты:
👉 Прокрастинация идеального кода
👉 Немного про собесы
👉 Скорочтение
👉 Фича команды vs Отдельные команды(Хабы, Гильдии, Вертикали т.д)
👉 Ограничения которые мы сами себе придумываем
🔥45👍14❤3🥰3😁1
Активности на канале пока нет, просьба понять и простить)
Я понемного выхожу из пост-новогодней депрессиии и начинаю приходить в себя. Уже есть пара идей для постов, но пишутся пока они со скрипом. Пишу просто чтобы, успокоить вас если вдруг переживали.
Я понемного выхожу из пост-новогодней депрессиии и начинаю приходить в себя. Уже есть пара идей для постов, но пишутся пока они со скрипом. Пишу просто чтобы, успокоить вас если вдруг переживали.
👍52❤31🥰5🤯1
🔐 Разрешения
Начнем 2023 год с разговора о разрешениях. Казалось бы, что там такого сложного в этих разрешениях в Android? Два основных типа, одни запрашиваем, вторые даются при установке. Однако когда начинаешь копать, оказывается, что их там больше 2 типов. Еще какие-то разрешения по подписи, про которые любят спрашивать в Яндексе. Оказывается, что можно навесить разрешение на любой компонент, а на ContentProvider вообще можно навесить хренову тучу на любой чих и поди разберись в этой каше.
Поэтому я вам сейчас все просто и изящно раскидаю про то, как правильно просить разрешения. В этой серии разберем:
👉 Как развивались разрешения в Android?
👉 Какие типы есть и как они работают?
👉 Куда их можно навесить и как запрашивать?
👉 Что за сложности с разрешениями для ContentProvider?
Начнем 2023 год с разговора о разрешениях. Казалось бы, что там такого сложного в этих разрешениях в Android? Два основных типа, одни запрашиваем, вторые даются при установке. Однако когда начинаешь копать, оказывается, что их там больше 2 типов. Еще какие-то разрешения по подписи, про которые любят спрашивать в Яндексе. Оказывается, что можно навесить разрешение на любой компонент, а на ContentProvider вообще можно навесить хренову тучу на любой чих и поди разберись в этой каше.
Поэтому я вам сейчас все просто и изящно раскидаю про то, как правильно просить разрешения. В этой серии разберем:
👉 Как развивались разрешения в Android?
👉 Какие типы есть и как они работают?
👉 Куда их можно навесить и как запрашивать?
👉 Что за сложности с разрешениями для ContentProvider?
🔥62👍9❤3
В первых версиях Android о разрешениях вообще мало кто задумывался. Был только один тип разрешений (на самом деле два, но в сейчас не важно). Просто указываешь их в манифесте и все, дело в шляпе. Однако пользователям это было не очень удобно. Допустим есть крутое приложение, которое тебе очень нравится, а оно требует разрешения на гео локацию, и вообще не понятно зачем. И ты либо даешь разрешение, либо идешь лесом и ищешь другое приложение, которое уважает твою приватность.
Причем на заре Android, мало кто вообще обращал внимание на то, что там приложение просит. Ну считывает оно локацию, ну и что, что оно сделает с этими данными? Потом конечно пришел Facebook и понеслась)
В любом случае все понимали, что с этим нужно что-то делать. Нужно дать возможность пользователям устанавливать приложение, и при этом выбирать к каким данным приложение имеет доступ, а к каким не имеет. Чтобы решить эту проблему, далеко ходить не нужно, достаточно подглядеть у конкурентов. В iOS чуть ли не с первых версий была поддержка разрешений, которые пользователь давал в процессе использования приложения. Android решили пойти тем же путем и появились runtime permission.
Когда я начал увлекаться разработкой, уже вышел 7 Android и я пропустил этот переход, когда появились runtime permission, но готов поспорить у многих разработчиков пригорало от этой фичи. Ведь теперь ты не просто идешь и получаешь геолокацию или контакты. Ты сначала будь добр уговори пользователя на это, а затем еще повращай колбеками, чтобы обработать результат и понять дали тебе разрешения или нет. Зато теперь честно, пользователь может контролировать, что он разрешает приложению, а разработчики теперь должны это обосновать.
В 11 Android появились “one time permission” – разрешения которые можно дать один раз. Также система теперь может отобрать у вас разрешение, если вашим приложением давно не пользовались.
В целом это вся история развития разрешений в Android. Как можно догадаться сильно резких поворотов с ними не было и главным изменением в истории стало именно появление runtime permission. Однако изменились API взаимодействия с разрешениями, это мы рассмотрим в следующих постах.
Причем на заре Android, мало кто вообще обращал внимание на то, что там приложение просит. Ну считывает оно локацию, ну и что, что оно сделает с этими данными? Потом конечно пришел Facebook и понеслась)
В любом случае все понимали, что с этим нужно что-то делать. Нужно дать возможность пользователям устанавливать приложение, и при этом выбирать к каким данным приложение имеет доступ, а к каким не имеет. Чтобы решить эту проблему, далеко ходить не нужно, достаточно подглядеть у конкурентов. В iOS чуть ли не с первых версий была поддержка разрешений, которые пользователь давал в процессе использования приложения. Android решили пойти тем же путем и появились runtime permission.
Когда я начал увлекаться разработкой, уже вышел 7 Android и я пропустил этот переход, когда появились runtime permission, но готов поспорить у многих разработчиков пригорало от этой фичи. Ведь теперь ты не просто идешь и получаешь геолокацию или контакты. Ты сначала будь добр уговори пользователя на это, а затем еще повращай колбеками, чтобы обработать результат и понять дали тебе разрешения или нет. Зато теперь честно, пользователь может контролировать, что он разрешает приложению, а разработчики теперь должны это обосновать.
В 11 Android появились “one time permission” – разрешения которые можно дать один раз. Также система теперь может отобрать у вас разрешение, если вашим приложением давно не пользовались.
В целом это вся история развития разрешений в Android. Как можно догадаться сильно резких поворотов с ними не было и главным изменением в истории стало именно появление runtime permission. Однако изменились API взаимодействия с разрешениями, это мы рассмотрим в следующих постах.
👍50🔥1
Итак, у нас всего 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 вашего приложения в нужную группу, и если нет, то отпинывает с ошибкой.
👉 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
{1/2} Теперь погнали к более практической части работы с разрешениями. Раньше запрос разрешения выглядел так, проверяем дано ли оно вообще, если нет то сначала при помощи специальной функции запускаем запрос разрешения. Результат такого запроса приходил в метод onActivityResult. В котором нужно было проверить есть ли результат, а тот ли id запроса и самому раскрасить данные, геморройная схема.
С появлением Result API все стало проще, теперь мы просто описываем лямбду куда придет результат. Хоть я и не в восторге от Result API, запрашивать разрешения просто сказка. Скорее всего вы и так это знаете, ведь метод onActivityResult задеприкейтили и result API сейчас это единственный вариант.
Это вы и без меня могли найти в доке гугла, там все очень просто. Разумеется я был бы не я, если бы ограничился только этим. Поэтому поговорим о том, о чем обычно не пишут.
Из интересного, прошлой главе я упоминал, что можно делать свои разрешения. Эти разрешения можно повесить на любой стандартный компонент вашего приложения. Вот прям на любой и любое кастомное разрешение, это позволяет делать разные веселые штуки. Но давайте по порядку.
📱Мобильные системы устроены таким образом, чтобы у клиента было ощущение, что он сидит в одном приложении. Об этом я писал с одной из своих недавних статей. Android так и устроен, мы всегда видим Activity какого-то приложения. Даже когда вы переходите в лаунчер, Activity вашего приложения просто меняется на Activity лаунчера.
Я клоню к тому, что если так подумать то компоненты, которые вы объявляете в манифесте, становятся достоянием всей системы. Вот такой вот софтверный социализм. Однако мы можем указать системе, что некоторые компоненты можем запускать и использовать только мы и никто больше.
Есть такой атрибут, указываемый при объявлении компонента в манифесте, и он показывает, можно ли этим компонентом пользоваться кем-то кроме нашего приложения, называется
Однако если у компонента настроен intent-filter сделать его НЕ exported, уже не получится. Самый частый кейс использования intent-filter это когда вам нужно сделать deeplink или функциональность для отправки email. В таком случае ваш компонент сможет запустить любое приложение в системе. Однако возможно, вы не хотите, чтобы вас мог использовать любой (двояко получилось согласен).
🔐И тут уже на сцену выходят кастомные permission. В кейсе с intent-filter все довольно просто. Объявляем кастомное разрешение, ставим ему protectionLevel=“signature” (из прошлого поста) и все. Теперь только ваши приложения, подписанные одним ключом смогут использовать ваши компоненты.
Это все стандартные кейсы, но вот что действительно забавно, так это возможность повесить Danger разрешение на вашу Активити. На полном серьезе, вы можете сделать кастомное резрешение со своим текстом. Это разрешение нужно будет запрашивать при помощи системного диалога, как и с локацией. Потом взять и повесить это разрешение на вашу Activity и все. Если другое приложение захочет вас запустить, ему придется запрашивать разрешение у пользователя.
Зачем это нужно? Ну смешно жи, представьте в какой растерянности будет пользователь, когда увидит системный диалог с текстом “Разрешите доебаться?”. В реальности разумеется так никто не делает, ибо зачем? Если мы открываем свою Activity мы наоборот всеми правдами и неправдами должны привлекать пользователя и другие приложения нас вызвать, для увеличения конверсии и все такое.
С появлением 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
Если вы думали что я пропал, то нет, я просто хренову тучу времени убил на эксперименты с Content Provider, чтобы вам тут не напиздеть не ввести в заблуждение. Теперь у меня есть куча всего интересного чего я могу рассказать, что будет интересно даже прожженными сеньорам.
Content Provider я выделил отдельно вот по какой причине. У него в отличие от других компонентов есть несколько интересных моментов касательно установки разрешения. Так как Content Provider это основной компонент на него, как и на другие можно навесить обычное разрешение. Устанавливаем такое, и теперь только приложение с нужным разрешением сможет получить от нас какие-либо данные. Помимо этого можно
Помимо обычного разрешения Content Provider позволяет настроить более точечную настройку разрешений. Есть возможность поставить разрешение, отдельно на запись и отдельно на чтение данных. Например, можно не задавать разрешение на чтение данных и позволить любому приложению читать данные, и при этом поставить signature разрешение на запись данных, тем самым разрешив модифицировать данные только определенным приложениям. Тут тоже все понятно и очевидно.
И самое интересное и запутанная хрень в Content Provider это
Если вы пойдете на stackoverflow, там будет дикий запад с костылями про то, как это сделать. Поискав чуть лучше, можно будет найти FileProvider. Суть проста, FileProvider это частный случай Content Provider который работает только с файлами. А нужен он для того, чтобы вы могли раздавать свои приватные файлы другим приложениям.
Идея тут должна быть понятна, мы не можем перегнать весь файл в bundle и отправить его в другое приложение, мы можем другому приложению передать только путь до нашего файла. Однако, что другое приложение сможет сделать с этим путем? Да ничего, система пошлет его лесом как только он попробует по этому пути перейти. А вот FileProvider позволяет легально обойти это ограничение.
Если вы зайдете в доку FileProvider, там будет сказано, что вам нужно сделать этот провайдер как
👉 Первый это когда мы формируем Intent на показ файла, нужно добавить флаг ‘FLAG_GRANT_READ_URI_PERMISSION’ и приложение, которое получит этот Intent получить также право временно(до перезагрузки устройства) обращаться к переданному Uri(к нашему файлу).
👉 Второй, мы можем программно вызывать метод
Ну я думаю логика должна была сложиться к голове как это все работает. Если кстати навесить еще и разрешение на FileProvider, то даже несмотря на
Однако это не все самое прикольное. Я обнаружил интересную толи багу, толи фичу связанную с FLAG_GRANT_READ_URI_PERMISSION, о которой расскажу в следующем посте.
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
В прошлом посте я описал штуку под названием
Вот смотрите, такой кейс: нам нужно не просто показать файл, а отправить его по email. Для этого в Android есть специальный action
Когда я проверял поведение, решил, что, ну надо же проверить как будет вести себя система без передачи этого флага. Обнаружил весьма забавную вещь. Если в Intent с
Для проверки я накидал мини приложеньку, которая просто перехватывает Intent с
Вывод какой, вероятно где-то под капотом, если вы передаете Intent с
Также в инете по всюду пишут, что разрешение
В итоге, даже несмотря на всю эту магию, если у вас есть функциональность отправки email с файлов, я бы советовал проставлять вручную флаг
FLAG_GRANT_READ_URI_PERMISSION
, которая позволяет выдать временное разрешение на какой-либо файл когда его нужно зашарить с другим приложением. Я разбирал его на примере кейса, когда нам нужно просто открыть файл. Создаем Intent с ACTION_VIEW
, добавляем Uri, закидываем флаг для прав и погнали. Все работает достаточно логично и очевидно, однако есть другой action, который творит магию, которая мне не доступна для понимания. Вот смотрите, такой кейс: нам нужно не просто показать файл, а отправить его по email. Для этого в Android есть специальный action
ACTION_SEND
. В него можно также передать данные о том, на какой email мы отправляем сообщение, задать тему, текст и вот это все. Самое интересное, что можно также прикрепить файл для отправки. Как вы помните мы не можем просто взять и передать в Intent ссылку на файл, нужно еще проставить FLAG_GRANT_READ_URI_PERMISSION
.Когда я проверял поведение, решил, что, ну надо же проверить как будет вести себя система без передачи этого флага. Обнаружил весьма забавную вещь. Если в Intent с
ACTION_SEND
передаем Uri на файл, разрешение выдается автоматически. Серьезно я пробовал это и на эмуляторе и на реальном устройстве. Все работает без указания флага FLAG_GRANT_READ_URI_PERMISSION
. И так работает только с ACTION_SEND
, в кейсе с ACTION_VIEW
, если самому не выдать разрешение, другое приложение ничего не откроет.Для проверки я накидал мини приложеньку, которая просто перехватывает Intent с
ACTION_SEND
и действительно, можно просто так получить файл. Однако если при этом приложение попытается позже в другой Activity обратиться к этому Uri, система пошлет приложение лесом. Вывод какой, вероятно где-то под капотом, если вы передаете Intent с
ACTION_SEND
и кладете в него Uri, система к этому Intent проставляет разрешение на чтение. Видимо это из соображение бизнес логики. Если вы даете такой функционал пользователю, значит вы точно хотите расшарить файл и система любезно проставляет разрешения за вас. Спорный момент, как мне кажется было бы очевиднее если бы такими флагами мы управляли сами. Ну а по пока получается, что ACTION_SEND
это аналог сына депутата, который может работать и без прав.Также в инете по всюду пишут, что разрешение
FLAG_GRANT_READ_URI_PERMISSION
выдается до тех пор пока не вызывали revokeUriPermission либо пока устройство не перезагрузится. Это не совсем правда, возможно так было на раних версиях Android. Сейчас же я тестировал на Android 11+ и там разрешение выдается исключительно на время жизни Intent который мы передали, т.е пока живет та Activity которая открылась этим Intent.В итоге, даже несмотря на всю эту магию, если у вас есть функциональность отправки email с файлов, я бы советовал проставлять вручную флаг
FLAG_GRANT_READ_URI_PERMISSION
, чисто на всякий случай, мало ли как там другие прошивки работают.👍28🤔3