Кащеева смерть — защищаем свои пароли с помощью аппаратного хранилища ключей Android
Несколько лет назад меня начала посещать мысль, что менеджеры паролей всё-таки «для честных людей». Как раз все встречные и поперечные стали заявлять, что у них теперь сквозное шифрование… И настали типа спокойные и безопасные времена (ну если не считать миллиардов, которые крадут с криптобирж каждый второй день, прослушки всех этих чатов со сквозным шифрованием, слива баз паролей, взлома LastPass…)
Короче, решил я замутить что-то своё, чтоб не хранить все свои доступы удобно (не)доступными в одном файле KeePass, а то ведь мало ли что. Просто так, из принципа. Биткойнов не держу.
Шли годы…
Читать статью
Несколько лет назад меня начала посещать мысль, что менеджеры паролей всё-таки «для честных людей». Как раз все встречные и поперечные стали заявлять, что у них теперь сквозное шифрование… И настали типа спокойные и безопасные времена (ну если не считать миллиардов, которые крадут с криптобирж каждый второй день, прослушки всех этих чатов со сквозным шифрованием, слива баз паролей, взлома LastPass…)
Короче, решил я замутить что-то своё, чтоб не хранить все свои доступы удобно (не)доступными в одном файле KeePass, а то ведь мало ли что. Просто так, из принципа. Биткойнов не держу.
Шли годы…
Читать статью
Teletype
Кащеева смерть — защищаем свои пароли с помощью аппаратного хранилища ключей Android
Несколько лет назад меня начала посещать мысль, что менеджеры паролей всё-таки «для честных людей». Как раз все встречные и поперечные...
👍5🆒1
Из каких базовых компонент состоит приложение?
Базовые компоненты андроид приложения: Activity, Service, BroadcastReceiver, ContentProvider. Каждый из базовых компонент объявляется в андроид манифесте и может являться точкой входа в приложение.
Activity представляет UI и функциональность, видимые пользователю.
Service используется для исполнения долгих операций, которые не требуют взаимодействия с пользователем.
BroadcastReceiver принимает и обрабатывает броадкаст ивенты, отправленные внутри приложения или из других приложений.
ContentProvider используется для обмена данными с другими приложениями.
Базовые компоненты андроид приложения: Activity, Service, BroadcastReceiver, ContentProvider. Каждый из базовых компонент объявляется в андроид манифесте и может являться точкой входа в приложение.
Activity представляет UI и функциональность, видимые пользователю.
Service используется для исполнения долгих операций, которые не требуют взаимодействия с пользователем.
BroadcastReceiver принимает и обрабатывает броадкаст ивенты, отправленные внутри приложения или из других приложений.
ContentProvider используется для обмена данными с другими приложениями.
👍8
Что под капотом у Leak Canary?
LeakCanary – библиотека, позволяющая находить утечки памяти во работы приложения в фоновом режиме. При всем при этом, со стороны клиента ничего делать не нужно. Просто указал либу в зависимостях Gradle, и она сама начинает работать.
Естественно инженерное любопытство заставляет задаться вопросом, а как работает эта магия? Эта статья даст хоть и поверхностные, но ответы на эти вопросы. В статье постараюсь описать: Как запускается LeakCanary? Откуда берется отдельный ярлык? Как вообще LeakCanary находит утечки и находит путь до утекшей ссылки?
Читать статью
LeakCanary – библиотека, позволяющая находить утечки памяти во работы приложения в фоновом режиме. При всем при этом, со стороны клиента ничего делать не нужно. Просто указал либу в зависимостях Gradle, и она сама начинает работать.
Естественно инженерное любопытство заставляет задаться вопросом, а как работает эта магия? Эта статья даст хоть и поверхностные, но ответы на эти вопросы. В статье постараюсь описать: Как запускается LeakCanary? Откуда берется отдельный ярлык? Как вообще LeakCanary находит утечки и находит путь до утекшей ссылки?
Читать статью
Teletype
Что под капотом у Leak Canary?
Утечка памяти пожалуй одна из самых незаметных ошибок, которую можно допустить в разработке. Такая ошибка никак не влияет на работу...
👍2
Может ли приложение быть запущено в нескольких процессах?
Короткий ответ – Да.
Но для начала давайте разберемся чем процесс отличается от потока.
Процесс – это сущность на уровне ОС. Каждая программа может быть запущена в одном или нескольких процессах.
Поток – это сущность на уровне Runtime Environment.
Программа может выполняться в нескольких процессах. В каждом из процессов может быть создано несколько потоков (Java Threads).
Вернемся к андроиду. В предыдущем посте мы рассмотрели базовые компоненты и узнали, что каждый из компонентов может быть точкой входа в приложение. По умолчанию компоненты приложения работают в дефолтном процессе, но каждый из компонентов <activity>, <service>, <receiver>, <provider> может иметь поле android:process=”<name>” в андроид манифесте. Кастомное значение этого поля явно говорит системе в каком процессе будет работать компонент.
Важно: При старте нового процесса создается инстанс приложения и снова вызывается Application.onCreate(). Если в этом методе вы инициализируете модули или библиотеки, которые используются только в главном процессе, то не забывайте проверять, в каком процессе вы находитесь в момент инициализации.
Подробнее про процессы и треды читайте в документации.
Короткий ответ – Да.
Но для начала давайте разберемся чем процесс отличается от потока.
Процесс – это сущность на уровне ОС. Каждая программа может быть запущена в одном или нескольких процессах.
Поток – это сущность на уровне Runtime Environment.
Программа может выполняться в нескольких процессах. В каждом из процессов может быть создано несколько потоков (Java Threads).
Вернемся к андроиду. В предыдущем посте мы рассмотрели базовые компоненты и узнали, что каждый из компонентов может быть точкой входа в приложение. По умолчанию компоненты приложения работают в дефолтном процессе, но каждый из компонентов <activity>, <service>, <receiver>, <provider> может иметь поле android:process=”<name>” в андроид манифесте. Кастомное значение этого поля явно говорит системе в каком процессе будет работать компонент.
Важно: При старте нового процесса создается инстанс приложения и снова вызывается Application.onCreate(). Если в этом методе вы инициализируете модули или библиотеки, которые используются только в главном процессе, то не забывайте проверять, в каком процессе вы находитесь в момент инициализации.
Подробнее про процессы и треды читайте в документации.
👍3
Принципы построения многомодульного Android-приложения и их применение в СберЗдоровье
Статей про «чистую» архитектуру и многомодульность очень много. Но не многие компании готовы делиться своим опытом и полученными результатами от внедрения этих практик. Я хочу попробовать исправить ситуацию.
В этом материале я расскажу о принципах построения многомодульного приложения, как мы применяем их при разработке мобильного приложения СберЗдоровье под Android и что это нам даёт.
Да, эта статья тоже про многомодульность, но не спешите пролистывать, потому что описанные ниже принципы, можно применять не только в мобильной разработке, но и в разработке ПО в целом.
Читать статью
Статей про «чистую» архитектуру и многомодульность очень много. Но не многие компании готовы делиться своим опытом и полученными результатами от внедрения этих практик. Я хочу попробовать исправить ситуацию.
В этом материале я расскажу о принципах построения многомодульного приложения, как мы применяем их при разработке мобильного приложения СберЗдоровье под Android и что это нам даёт.
Да, эта статья тоже про многомодульность, но не спешите пролистывать, потому что описанные ниже принципы, можно применять не только в мобильной разработке, но и в разработке ПО в целом.
Читать статью
Teletype
Принципы построения многомодульного Android-приложения и их применение в СберЗдоровье
Всем привет! Меня зовут Александр. Я Android разработчик в СберЗдоровье.
👍2
Приоритеты процессов
Процессы делятся по приоритету на 4 вида, в порядке убывания:
1. Видимый активный процесс (Foreground process). В этом процессе работает приложение, с которым взаимодействует пользователь. Процесс находится в этом состоянии в следующих случаях:
- Activity, у которой вызван onResume(), но еще не вызван onPause()
- Во время выполнения BroadcastReceiver.onReceive()
- Запущен Service и выполняется один из колбэков: onCreate(), onStart(), onDestroy()
2. Видимый процесс. Пользователь знает о приложении, запущенном в этом процессе, но не взаимодействует с ним:
- Activity у которой вызван onPause(), но еще не вызван onStop().
- Service, который запущен через Service.startForeground(). В этом случае пользователь видит нотификацию, связанную с сервисом.
- Service, выполняющий функцию, о которой пользователь осведомлен. Например input method service.
3. Background Service. Процесс с сервисом, запущенным командой startService().
4. Закэшированный процесс. К ним относятся пустые процессы, используемые при старте приложений, и процессы, в которых все активити в onStop() состоянии.
Система убивает процессы в порядке возрастания их приоритета для восстановления ресурсов.
Процессы делятся по приоритету на 4 вида, в порядке убывания:
1. Видимый активный процесс (Foreground process). В этом процессе работает приложение, с которым взаимодействует пользователь. Процесс находится в этом состоянии в следующих случаях:
- Activity, у которой вызван onResume(), но еще не вызван onPause()
- Во время выполнения BroadcastReceiver.onReceive()
- Запущен Service и выполняется один из колбэков: onCreate(), onStart(), onDestroy()
2. Видимый процесс. Пользователь знает о приложении, запущенном в этом процессе, но не взаимодействует с ним:
- Activity у которой вызван onPause(), но еще не вызван onStop().
- Service, который запущен через Service.startForeground(). В этом случае пользователь видит нотификацию, связанную с сервисом.
- Service, выполняющий функцию, о которой пользователь осведомлен. Например input method service.
3. Background Service. Процесс с сервисом, запущенным командой startService().
4. Закэшированный процесс. К ним относятся пустые процессы, используемые при старте приложений, и процессы, в которых все активити в onStop() состоянии.
Система убивает процессы в порядке возрастания их приоритета для восстановления ресурсов.
👍8
Какое ожидается поведение от этого кода?
Anonymous Quiz
44%
Приложение при запуске запросит разрешение на Bluetooth
12%
Приложение вылетит из-за receiver1
23%
Приложение вылетит из-за receiver2
21%
Код не скомпилируется
🔥5👍1
Как настроить автомиграцию в Room
В этой статье я расскажу про автомиграцию в Room (версия не ниже Room 2.4.0), варианты ее использования, преимущества, которые она дает, и проблемы, с которыми мы можем столкнуться.
Автомиграция поможет упростить процесс работы с базой данных, особенно если она большая, и в нее часто вносятся изменения. Она позволит не писать самостоятельно сложные SQL-запросы, а сгенерирует их автоматически в специально отведенной директории. Это позволит избежать опечаток при миграции и сэкономить время (если у нас запросы с огромным количеством полей).
Дисклеймер: в этой статье я буду ориентироваться на то, что мы уже умеем работать с Room и знаем, для чего нужна миграция. Материал будет полезен Android-разработчикам уровня Middle.
Читать статью
В этой статье я расскажу про автомиграцию в Room (версия не ниже Room 2.4.0), варианты ее использования, преимущества, которые она дает, и проблемы, с которыми мы можем столкнуться.
Автомиграция поможет упростить процесс работы с базой данных, особенно если она большая, и в нее часто вносятся изменения. Она позволит не писать самостоятельно сложные SQL-запросы, а сгенерирует их автоматически в специально отведенной директории. Это позволит избежать опечаток при миграции и сэкономить время (если у нас запросы с огромным количеством полей).
Дисклеймер: в этой статье я буду ориентироваться на то, что мы уже умеем работать с Room и знаем, для чего нужна миграция. Материал будет полезен Android-разработчикам уровня Middle.
Читать статью
Teletype
Как настроить автомиграцию в Room
Меня зовут Роман, я Android-разработчик в IT-компании SimbirSoft. В этой статье я расскажу про автомиграцию в Room (версия не ниже Room...
👍6❤🔥1
Activity: Что такое и как запустить?
Activity – основной компонент в андроиде. Активити – это экран, то что видит и с чем взаимодействует пользователь. Может содержать несколько View и фрагментов. Так же как и другие базовые компоненты, может быть точкой входа в приложение.
Активити с MAIN Intent Filter в манифесте запускается при старте приложения, когда пользователь кликает на иконку приложения.
Activity – основной компонент в андроиде. Активити – это экран, то что видит и с чем взаимодействует пользователь. Может содержать несколько View и фрагментов. Так же как и другие базовые компоненты, может быть точкой входа в приложение.
Активити с MAIN Intent Filter в манифесте запускается при старте приложения, когда пользователь кликает на иконку приложения.
👍7❤🔥1
Какое ожидается поведение от этого кода?
Считать, что timer - это TextView с соответствующим id.
Считать, что timer - это TextView с соответствующим id.
Anonymous Quiz
44%
Приложение исправно меняет у timer свойство text каждую секунду
9%
Приложение вылетит из-за 19 строки кода
41%
Приложение вылетит из-за 22 строки кода
6%
Приложение вылетит из-за 24 строки кода
👍6❤1
Нейронные сети и Android: как их создавать и использовать в мобильных приложениях
Тренд на нейросети не обошёл стороной и мобильные приложения. Многие фичи — например, распознавание изображений и речи, улучшение качество фото и видео — созданы с применением нейронных сетей.
Рассказываем про нейросети в Android-приложениях: какие есть инструменты для внедрения, как создавать свои модели и использовать готовые.
Читать статью
Тренд на нейросети не обошёл стороной и мобильные приложения. Многие фичи — например, распознавание изображений и речи, улучшение качество фото и видео — созданы с применением нейронных сетей.
Рассказываем про нейросети в Android-приложениях: какие есть инструменты для внедрения, как создавать свои модели и использовать готовые.
Читать статью
Teletype
Нейронные сети и Android: как их создавать и использовать в мобильных приложениях
Маски в Snapchat и Запрещёноgram, категоризация фотографий в галерее, улучшение качества фотографий в Google Camera — все эти фичи...
👍1
Activity: Жизненный цикл
Жизненный цикл активити состоит из шести основных коллбэков, вызываемых системой. В порядке вызова: onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy().
onCreate() вызывается когда активити создается. В onCreate() вы должны вызвать метод setContentView().
onStart() вызывается когда активити отрисована и видима пользователю.
onResume() вызывается перед тем как активити станет доступна для взаимодействия с пользователем.
onPause() – метод симметричный onResume(). Пользователь больше не может взаимодействовать с активити, но активити частично видна пользователю. В этом состоянии UI активити может изменяться.
onStop() – метод симметричный onStart(). Вызывается, когда активити больше не видна пользователю.
onDestroy() – метод симметричный onCreate(). Вызывается перед тем, как активити будет уничтожена системой.
Несколько примеров:
1. Пользователь жмет Home. В этом случае активити больше не видна, поэтому вызываются onPause(), onStop(). Пользователь открывает приложение снова - onStart(), onResume().
2. Пользователь переходит на другую активити внутри приложения (реализуется вызовом startActivity()) – onPause(), onStop(). Пользователь возвращается на предыдущую активити – onStart(), onResume().
3. Вызов finish() – onPause(), onStop(), onDestroy(). Когда пользователь перейдет на эту активити снова, она будет создана с нуля без сохранения состояния.
4. Пользователь поворачивает телефон и ориентация активити меняется. Активити пересоздается и вызываются коллбеки onPause(), onStop(), onDestroy(), onCreate(), onStart(), onResume() с сохранением состояния.
Это базовые методы активити. Более подробно они описаны в документации.
В полный жизненный цикл также входят onRestart(), onSaveInstanceState(), onRestoreInstanceState(), onNewIntent() и другие методы, которые разберем в будущем.
Жизненный цикл активити состоит из шести основных коллбэков, вызываемых системой. В порядке вызова: onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy().
onCreate() вызывается когда активити создается. В onCreate() вы должны вызвать метод setContentView().
onStart() вызывается когда активити отрисована и видима пользователю.
onResume() вызывается перед тем как активити станет доступна для взаимодействия с пользователем.
onPause() – метод симметричный onResume(). Пользователь больше не может взаимодействовать с активити, но активити частично видна пользователю. В этом состоянии UI активити может изменяться.
onStop() – метод симметричный onStart(). Вызывается, когда активити больше не видна пользователю.
onDestroy() – метод симметричный onCreate(). Вызывается перед тем, как активити будет уничтожена системой.
Несколько примеров:
1. Пользователь жмет Home. В этом случае активити больше не видна, поэтому вызываются onPause(), onStop(). Пользователь открывает приложение снова - onStart(), onResume().
2. Пользователь переходит на другую активити внутри приложения (реализуется вызовом startActivity()) – onPause(), onStop(). Пользователь возвращается на предыдущую активити – onStart(), onResume().
3. Вызов finish() – onPause(), onStop(), onDestroy(). Когда пользователь перейдет на эту активити снова, она будет создана с нуля без сохранения состояния.
4. Пользователь поворачивает телефон и ориентация активити меняется. Активити пересоздается и вызываются коллбеки onPause(), onStop(), onDestroy(), onCreate(), onStart(), onResume() с сохранением состояния.
Это базовые методы активити. Более подробно они описаны в документации.
В полный жизненный цикл также входят onRestart(), onSaveInstanceState(), onRestoreInstanceState(), onNewIntent() и другие методы, которые разберем в будущем.
👍15
Что произойдёт после поворота экрана?
Anonymous Quiz
24%
На экране ничего не изменится.
18%
TextView очистится, а EditText - нет.
21%
EditText очистится, а TextView - нет.
38%
Оба элемента очистятся.
👍9👨💻6
Activity: Как пережить поворот экрана?
При повороте экрана активити уничтожается и создается заново. Вызываются коллбэки onPause(), onStop(), onSaveInstanceState(), onDestroy() – onCreate(), onStart(), onRestoreInstanceState(), onResume().
Чтобы сохранить состояние активити, вы должны переопределить метод onSaveInstanceState() и положить данные в Bundle.
При реинициализации активити, Bundle с сохраненным состоянием передается в onCreate() и в onRestoreInstanceState().
Система вызывает onSaveInstanceState() и onRestoreInstanceState() только в том случае, когда необходимо сохранить состояние, например при повороте экрана или при убийстве активити для освобождения памяти. Данные коллбэки не вызываются, если пользователь выходит из активити нажав Back или если активити убивается вызовом finish().
onSaveInstanceState() вызывается после onStop() на версии API ≥ 28. На API < 28 этот коллбэк вызывается перед onStop() и нет гарантий до или после onPause().
onRestoreInstanceState() вызывается после onStart().
При повороте экрана активити уничтожается и создается заново. Вызываются коллбэки onPause(), onStop(), onSaveInstanceState(), onDestroy() – onCreate(), onStart(), onRestoreInstanceState(), onResume().
Чтобы сохранить состояние активити, вы должны переопределить метод onSaveInstanceState() и положить данные в Bundle.
При реинициализации активити, Bundle с сохраненным состоянием передается в onCreate() и в onRestoreInstanceState().
Система вызывает onSaveInstanceState() и onRestoreInstanceState() только в том случае, когда необходимо сохранить состояние, например при повороте экрана или при убийстве активити для освобождения памяти. Данные коллбэки не вызываются, если пользователь выходит из активити нажав Back или если активити убивается вызовом finish().
onSaveInstanceState() вызывается после onStop() на версии API ≥ 28. На API < 28 этот коллбэк вызывается перед onStop() и нет гарантий до или после onPause().
onRestoreInstanceState() вызывается после onStart().
👍8🔥2
Нужно ли думать о сохранении состояния, если приложение поддерживает только портретную ориентацию?
– Да.
Поворот экрана – это частный случай Configuration Changes. Другой пример – изменение языка системы.
Кроме того, как было упомянуто постом выше, система может уничтожить активити, чтобы использовать занятые ей ресурсы. В этом случае состояние сохраняется и восстанавливается при пересоздании активити.
– Да.
Поворот экрана – это частный случай Configuration Changes. Другой пример – изменение языка системы.
Кроме того, как было упомянуто постом выше, система может уничтожить активити, чтобы использовать занятые ей ресурсы. В этом случае состояние сохраняется и восстанавливается при пересоздании активити.
👍5
Fragment
Fragment используется для отображения части UI на экране. Фрагмент создается внутри активити или внутри другого фрагмента.
Для создания и управления фрагментами используется FragmentManager.
Класс-наследник класса Fragment должен иметь дефолтный конструктор без параметров. Система использует этот конструктор при пересоздании фрагмента.
Начиная с API v28 системный класс Fragment – deprecated. Рекомендуется использовать Fragment из Support Library.
Fragment используется для отображения части UI на экране. Фрагмент создается внутри активити или внутри другого фрагмента.
Для создания и управления фрагментами используется FragmentManager.
Класс-наследник класса Fragment должен иметь дефолтный конструктор без параметров. Система использует этот конструктор при пересоздании фрагмента.
Начиная с API v28 системный класс Fragment – deprecated. Рекомендуется использовать Fragment из Support Library.
👍1
Расскажите про способы добавления и переключения фрагментов. Как работать с бэкстэком?
Для управления фрагментами используются два класса: FragmentManager и FragmentTransaction.
Для получения FragmentManager используются метод активити getSupportFragmentManager() или метод фрагмента getChildFragmentManager().
FragmentManager начинает транзакцию и возвращает объект FragmentTransaction вызовом метода beginTransaction().
Методы класса FragmentTransaction, которые необходимо знать - add(), remove() и replace().
add() добавляет фрагмент на активити или другой фрагмент. Принимает аргументами containerViewId, в который добавляется фрагмент, инстанс фрагмента, тег.
Другой способ добавить фрагмент - определить в лэйауте с помощью тега <fragment>.
remove() - операция, обратная add(). Удаляет фрагмент.
replace() удаляет все фрагменты, добавленные методом add() в заданный контейнер, и добавляет переданный аргументом фрагмент в контейнер. Параметр tag может быть null.
Эти операции не выполняются сразу же после вызова методов. Метод commit() завершает транзакцию и выполняет операции транзакции.
Метод addToBackStack() добавляет транзакцию в Back Stack. Это значит, что когда пользователь нажмет Back транзакция откатится. addToBackStack() применяется ко всем операциям в транзакции. Например следующий код добавляет транзакцию из трех операций в бэкстэк:
Для управления фрагментами используются два класса: FragmentManager и FragmentTransaction.
Для получения FragmentManager используются метод активити getSupportFragmentManager() или метод фрагмента getChildFragmentManager().
FragmentManager начинает транзакцию и возвращает объект FragmentTransaction вызовом метода beginTransaction().
Методы класса FragmentTransaction, которые необходимо знать - add(), remove() и replace().
add() добавляет фрагмент на активити или другой фрагмент. Принимает аргументами containerViewId, в который добавляется фрагмент, инстанс фрагмента, тег.
Другой способ добавить фрагмент - определить в лэйауте с помощью тега <fragment>.
remove() - операция, обратная add(). Удаляет фрагмент.
replace() удаляет все фрагменты, добавленные методом add() в заданный контейнер, и добавляет переданный аргументом фрагмент в контейнер. Параметр tag может быть null.
Эти операции не выполняются сразу же после вызова методов. Метод commit() завершает транзакцию и выполняет операции транзакции.
Метод addToBackStack() добавляет транзакцию в Back Stack. Это значит, что когда пользователь нажмет Back транзакция откатится. addToBackStack() применяется ко всем операциям в транзакции. Например следующий код добавляет транзакцию из трех операций в бэкстэк:
fragmentTransactionМетод popBackStack() удаляет транзакцию с верхушки бэкстэка, возвращает true, если бэкстэк хранил хотя бы одну транзакцию.
.add(R.id.fragmentContainer1, fragment1)
.add(R.id.fragmentContainer2, fragment2)
.replace(R.id.fragmentContainer1, fragment3)
.addToBackStack("tag")
.commit()
👍2
