Итоги года 2023
Постов: 7
то есть один пост раз в полтора месяца. знаете ли вы более продуктивного автора?)
Статьи на хабр:
• Прикладное adb (Android Debug Bridge) для зумеров
• Ускоряем поиск по коду в Android Studio
• Android. Принять себя или Cookie?
Планы на следующий год:
• дальше, больше, come on everybody
....
с новым годом! 🎁
желаю хорошо отдохнуть и потом еще раз хорошо отдохнуть 🥂
Постов: 7
то есть один пост раз в полтора месяца. знаете ли вы более продуктивного автора?)
Статьи на хабр:
• Прикладное adb (Android Debug Bridge) для зумеров
• Ускоряем поиск по коду в Android Studio
• Android. Принять себя или Cookie?
Планы на следующий год:
• дальше, больше, come on everybody
....
с новым годом! 🎁
желаю хорошо отдохнуть и потом еще раз хорошо отдохнуть 🥂
🍾30👍6🔥5🎉3🆒2
Автоподстановка кода из SMS
Есть такая магия— SMS приходит на телефон, а приложение его автоматически читает и подставляет в поле для ввода OTP (one-time password)
На первый взгляд механизм понятен:
система получает SMS -> кидает Intent в приложение -> Broadcast Receiver получается Intent с текстом SMS
Но есть подвох — это опасно. Если все приложения будут получать этот Intent, то они смогут перехватить OTP (читать "аккаунт украден")
Поэтому вводятся дополнительные степени защиты
Первая:
1. Ограничение по времени — приложение получает Intent только в течение 5 минут после начала ожидания OTP
А вторая на выбор:
2.1 Или показываем пользователю системную диаложку "Вы ТОЧНО хотите вставить этот код в это приложение?"
2.2 Или в SMS должен быть зашит hash-код приложения
Подход 2.1 называется One-tap SMS verification (потому что требует от юзера одного нажатия на кнопку "да, ТОЧНО"
Подход 2.2 вообще не требует от юзера тапов
hash-код для 2.2 формирутеся из подписи приложения и заранее сообщается бекенду, который отправляет SMS
бекенд вставляет hash-код в конец текста SMS
Например,
"Никому не сообщайте код 110011, Ваш Банк💋 Sdnjh!a+iDn",
где Sdnjh!a+iDn — hash-код приложения
Есть такая магия— SMS приходит на телефон, а приложение его автоматически читает и подставляет в поле для ввода OTP (one-time password)
На первый взгляд механизм понятен:
система получает SMS -> кидает Intent в приложение -> Broadcast Receiver получается Intent с текстом SMS
Но есть подвох — это опасно. Если все приложения будут получать этот Intent, то они смогут перехватить OTP (читать "аккаунт украден")
Поэтому вводятся дополнительные степени защиты
Первая:
1. Ограничение по времени — приложение получает Intent только в течение 5 минут после начала ожидания OTP
А вторая на выбор:
2.1 Или показываем пользователю системную диаложку "Вы ТОЧНО хотите вставить этот код в это приложение?"
2.2 Или в SMS должен быть зашит hash-код приложения
Подход 2.1 называется One-tap SMS verification (потому что требует от юзера одного нажатия на кнопку "да, ТОЧНО"
Подход 2.2 вообще не требует от юзера тапов
hash-код для 2.2 формирутеся из подписи приложения и заранее сообщается бекенду, который отправляет SMS
бекенд вставляет hash-код в конец текста SMS
Например,
"Никому не сообщайте код 110011, Ваш Банк💋 Sdnjh!a+iDn",
где Sdnjh!a+iDn — hash-код приложения
🔥48👍3🦄3❤1👎1👏1
Из чего состоит apk
,apk это .zip
Если переименовать расширение .apk на .zip, то спокойно можно увидеть содержимое ,apk
Или можно открыть .apk в Android Studio
А там такое:
• .dex-файлы — скомпилированный java/kotlin-код, часто обфусцированный
у .dex-формата есть ограничение по объему, поэтому код приложения разбивается на несколько файлов
• .so-либы — это скомпилированный нативный код, то есть написанный на C/C++
они кстати жрут много мегабайт, так как компилируются сразу под разные архитектуры процессоров
java/kotlin код компилируется в единственном экземпляре, потому что запускается через JVM
• в папке r или res—- картинки, строки и т.д.
• в файле resources.arsc лежит мапа ресурсов и их id
• AndroidManifest.xml — итоговый манифест, смерженный из всех модулей и библиотек
• куча всякой мета-информации о приложении, библиотеках, котлине и даже градле
• META-INF — хэши файлов, информация о подписи приложения и еще мета-информация о библиотеках
пост про .aab
,apk это .zip
Если переименовать расширение .apk на .zip, то спокойно можно увидеть содержимое ,apk
Или можно открыть .apk в Android Studio
А там такое:
• .dex-файлы — скомпилированный java/kotlin-код, часто обфусцированный
у .dex-формата есть ограничение по объему, поэтому код приложения разбивается на несколько файлов
• .so-либы — это скомпилированный нативный код, то есть написанный на C/C++
они кстати жрут много мегабайт, так как компилируются сразу под разные архитектуры процессоров
java/kotlin код компилируется в единственном экземпляре, потому что запускается через JVM
• в папке r или res—- картинки, строки и т.д.
• в файле resources.arsc лежит мапа ресурсов и их id
• AndroidManifest.xml — итоговый манифест, смерженный из всех модулей и библиотек
• куча всякой мета-информации о приложении, библиотеках, котлине и даже градле
• META-INF — хэши файлов, информация о подписи приложения и еще мета-информация о библиотеках
пост про .aab
👍33👏13🔥10🦄4👌3🗿2
Prefetch (предзагрузка)
Это фича настолько же полезна, как кэширование и пагинация, но почему-то о ней говорят реже
Предзагрузка — это загрузка контента до того, как юзер начнет взаимодействовать с ним
Например, плеер начинает грузить следующий трек раньше, чем вы на него перелистнете
Тик-ток заранее подгружает N первых секунд следующих K-штук видео
Онлайн-магазины подгружают описание товара до того, как вы на него кликните
Умная лента с мемами грузит следующие мемы до того, как они окажутся на экране
Реализовать такое легко:
• делаете запрос к беку в момент простоя приложения и сохраняете ответ в любой кэш
• когда юзеру нужно отобразить этот контент, быстро достаете его из кэша, а не долго из бека
У этого подхода есть очевидный минус:
• какой-то % запросов окажется лишним, так как запросы к беку на загрузку отправляются в попытке "угадать" следующее действите юзера
Но в ситуациях, когда скорость отображения контета важнее увеличения нагрузки на сервер — префетч это имба
Все же натыкались на исследования, которые доказывают, что выигрыш в пару сотен миллисекунд в скорости отображения контента в десятки раз окупает затраты на дополнительный сервер?)
Это фича настолько же полезна, как кэширование и пагинация, но почему-то о ней говорят реже
Предзагрузка — это загрузка контента до того, как юзер начнет взаимодействовать с ним
Например, плеер начинает грузить следующий трек раньше, чем вы на него перелистнете
Тик-ток заранее подгружает N первых секунд следующих K-штук видео
Онлайн-магазины подгружают описание товара до того, как вы на него кликните
Умная лента с мемами грузит следующие мемы до того, как они окажутся на экране
Реализовать такое легко:
• делаете запрос к беку в момент простоя приложения и сохраняете ответ в любой кэш
• когда юзеру нужно отобразить этот контент, быстро достаете его из кэша, а не долго из бека
У этого подхода есть очевидный минус:
• какой-то % запросов окажется лишним, так как запросы к беку на загрузку отправляются в попытке "угадать" следующее действите юзера
Но в ситуациях, когда скорость отображения контета важнее увеличения нагрузки на сервер — префетч это имба
Все же натыкались на исследования, которые доказывают, что выигрыш в пару сотен миллисекунд в скорости отображения контента в десятки раз окупает затраты на дополнительный сервер?)
🌚18👍16
Многомодульность зачем нужна?
С первых шагов в мобильной разработке каждый день слышал, что многомодульность — это топ, это канон
И этому веришь на подсознательном уровне. Много — круто, модули — круто, получается многомодульность тоже круто
А зачем она нужна?
....
Первое, что приходит в голову — ради чистой архитектуры, ради группировки кода, ради presentation, domain, data
Но кто мешает разделять код с помощью обычных папочек и пакетов?
Из них тоже можно построить древо любой сложности. Модуль в этом плане отличается только цветом иконки в студии
....
Второй ложный аргумент — в большом проекте у каждой команды должен быть свой модуль
Но право апрувить код настраивается на папки, git про модули ничего не знает
Единственное исключение здесь — модификатор internal в kotlin, позволяющий ограничить видимость кода на уровне модуля (команды)
....
На самом деле модуль нужен для системы сборки
Работает это примерно так:
• система сборки (обычно gradle) считает хэш от всех файлов в модуле
• считает хэш всех модулей / библиотек, от которых зависит модуль
• если хэши не изменились, то компилировать заново модуль не надо — можно взять его из кэша
соответственно, бить проект на модули нужно только для ускорения сборки
....
или есть еще причины?)
С первых шагов в мобильной разработке каждый день слышал, что многомодульность — это топ, это канон
И этому веришь на подсознательном уровне. Много — круто, модули — круто, получается многомодульность тоже круто
А зачем она нужна?
....
Первое, что приходит в голову — ради чистой архитектуры, ради группировки кода, ради presentation, domain, data
Но кто мешает разделять код с помощью обычных папочек и пакетов?
Из них тоже можно построить древо любой сложности. Модуль в этом плане отличается только цветом иконки в студии
....
Второй ложный аргумент — в большом проекте у каждой команды должен быть свой модуль
Но право апрувить код настраивается на папки, git про модули ничего не знает
Единственное исключение здесь — модификатор internal в kotlin, позволяющий ограничить видимость кода на уровне модуля (команды)
....
На самом деле модуль нужен для системы сборки
Работает это примерно так:
• система сборки (обычно gradle) считает хэш от всех файлов в модуле
• считает хэш всех модулей / библиотек, от которых зависит модуль
• если хэши не изменились, то компилировать заново модуль не надо — можно взять его из кэша
соответственно, бить проект на модули нужно только для ускорения сборки
....
или есть еще причины?)
🔥24❤3👍3🦄3🤔2🍌1
DNS в Android
• Когда дергается DNS-сервер?
У каждого сетевого запроса есть домен (например ya.ru)
Но для отправки интернет-запроса нужен не домен, а IP
Поэтому существуют DNS-сервера, которые обменивает домен в IP
Но на практике вручную отправлять запрос на DNS сервер не нужно — сетевой клиент это делает самостоятельно
Когда приложение дергает любую ручку, то клиент ищет в своих кэшах IP для этого домена. Если не находит, то делает запрос к DNS-серверу.
• Откуда клиент знает, на какой DNS-сервер слать запрос?
Клиент берет IP адреса DNS-сервера у системы. В нее обычно зашиты наиболее популярные DNS-сервера (например, гугловские 8.8.8.8)
При этом можно для каждой Wi-Fi сети указать свой DNS-сервер в настройках сети
Более того — для каждого OkHttpClient-а внутри приложения можно указать свой DNS-сервер
Под капотом там такая цепочка:
OkHttpClient -> DNS (интерфейс-колбек) -> InetAddresses (класс, который разруливает кэши и возвращает IP, связанные с доменом) -> Inet4Address/Inet6Address (классы, хранящие IP и мета-информацию)
• В какой момент домен обменивается на IP?
Когда в первый раз улетает запрос на определенный домен, клиент сначала выполняет запрос к DNS, а потом только сам запрос на ваш бекенд
При этом полученный IP сохраняется в DNS-кэш клиента
Поэтому первый запрос к бекенду будет лететь дольше, чем следующие
• Как долго живет DNS-кэш?
Точных данных не нашел, но судя по исходникам java net кэш очищается раз в какое-то время и при смене сети (переключении Wi-Fi или переходе на моб сеть)
• Можно ли вручную очиcтить DNS-кэш?
Неа, нет API для этого. Но можно в OkHttpClient передать свой DNS-колбек и самостоятельно делать запрос к DNS-серверу/организовать свой кэш
• Когда дергается DNS-сервер?
У каждого сетевого запроса есть домен (например ya.ru)
Но для отправки интернет-запроса нужен не домен, а IP
Поэтому существуют DNS-сервера, которые обменивает домен в IP
Но на практике вручную отправлять запрос на DNS сервер не нужно — сетевой клиент это делает самостоятельно
Когда приложение дергает любую ручку, то клиент ищет в своих кэшах IP для этого домена. Если не находит, то делает запрос к DNS-серверу.
• Откуда клиент знает, на какой DNS-сервер слать запрос?
Клиент берет IP адреса DNS-сервера у системы. В нее обычно зашиты наиболее популярные DNS-сервера (например, гугловские 8.8.8.8)
При этом можно для каждой Wi-Fi сети указать свой DNS-сервер в настройках сети
Более того — для каждого OkHttpClient-а внутри приложения можно указать свой DNS-сервер
Под капотом там такая цепочка:
OkHttpClient -> DNS (интерфейс-колбек) -> InetAddresses (класс, который разруливает кэши и возвращает IP, связанные с доменом) -> Inet4Address/Inet6Address (классы, хранящие IP и мета-информацию)
• В какой момент домен обменивается на IP?
Когда в первый раз улетает запрос на определенный домен, клиент сначала выполняет запрос к DNS, а потом только сам запрос на ваш бекенд
При этом полученный IP сохраняется в DNS-кэш клиента
Поэтому первый запрос к бекенду будет лететь дольше, чем следующие
• Как долго живет DNS-кэш?
Точных данных не нашел, но судя по исходникам java net кэш очищается раз в какое-то время и при смене сети (переключении Wi-Fi или переходе на моб сеть)
• Можно ли вручную очиcтить DNS-кэш?
Неа, нет API для этого. Но можно в OkHttpClient передать свой DNS-колбек и самостоятельно делать запрос к DNS-серверу/организовать свой кэш
🔥17🍓5👍4🍾4
Подписать переменную понятно
Data class vs Typealias vs Value class
Наприме, есть 2 переменных типа String — в одной храним полное ФИО, а в другой инициалы
и эти два параметра нужно перекидывать во множество функций
варианты решения:
• выбираем понятные длинные названия для переменных и везде используем их
минусы: нельзя сделать проверку типа, ведь обе переменные String, значит легко их перепутать
• создаем data-класс и упаковываем два поля туда
минусы: если играть в оптимизацию по памяти, то проиграешь + возможно не везде эти два поля нужно передавать вместе
• создаем typealias
минус:
• typealias — не новый класс, поэтому у него не может быть своих функций, полей, конструкторов и т.д.
• typealias не даст сделать проверку типа, ведь FullName == String
• создаем value class
плюсы:
• компилятор сам решит, где стоит оптимизировать и заинлайнить переменную, а где стоит оставить класс-обертку
• можно добавить функции и поля каждому value class
• можно делать проверку типа
минусы:
• нужно внимательно следить за .toString() — результат зависит от того, подставит компилятор value-класс или сразу его значение
Data class vs Typealias vs Value class
Наприме, есть 2 переменных типа String — в одной храним полное ФИО, а в другой инициалы
и эти два параметра нужно перекидывать во множество функций
варианты решения:
• выбираем понятные длинные названия для переменных и везде используем их
val fullName: String
val shortName: String
минусы: нельзя сделать проверку типа, ведь обе переменные String, значит легко их перепутать
• создаем data-класс и упаковываем два поля туда
data class Names(fullName: String, shortName: String)
минусы: если играть в оптимизацию по памяти, то проиграешь + возможно не везде эти два поля нужно передавать вместе
• создаем typealias
typealias FullName = String
typealias ShortName = String
минус:
• typealias — не новый класс, поэтому у него не может быть своих функций, полей, конструкторов и т.д.
• typealias не даст сделать проверку типа, ведь FullName == String
• создаем value class
value class FullName(value: String)
value class ShortName(value: String)
плюсы:
• компилятор сам решит, где стоит оптимизировать и заинлайнить переменную, а где стоит оставить класс-обертку
• можно добавить функции и поля каждому value class
• можно делать проверку типа
минусы:
• нужно внимательно следить за .toString() — результат зависит от того, подставит компилятор value-класс или сразу его значение
🔥24🦄9❤4🎃1
Как открыть URL в нативном приложении
Например, хотите дать возможность крутить казик прямо в вашем блокноте (осуждаю)
Для этого есть 5 вариантов:
• WebView
• GeckoView
• ChromeTabs
• TWA
• внешний браузер
WebView
Это обычная вьюшка, которая встраивается в вашу верстку
Плюсов много:
• можно отобразить хоть в диалоге, хоть на треть экрана
• можно контролировать каждый запрос (есть куча колбеков)
• можно передать любые куки и хедеры (в том числе токены пользователя, чтоб не заставлять пользователя заново авторизовываться)
• можно ограничить список ссылок, которые можно открывать
• можно настроить JS Bridge (вызывать нативный код прямо с сайта)
GeckoView
Это аналог WebView от Firefox
Сам не использовал, ничего сказать не могу. Интуиция подсказывает, что проблем будет больше, чем с WebView. Но API довольно обширное — это плюс. Если кто пользовался, поделитесь опытом/эмоциями, пожалуйста)
ChromeTab
ChromeTab — это Activity браузера Chrome, открытое поверх вашего приложения в вашей Task-e
Из плюсов:
• в ChromeTab доступен весь функционал браузера (кнопка "поделиться", поиск по странице...)
• общее с Chrome хранилище данных о юзере (если открыть ссылку, где юзер раньше авторизовывался, то он сразу окажется в своем аккаунте)
• поддерживает App Links (автоматический редирект в нативное приложение, если оно установлено)
Минусы есть:
• нельзя встроить в верстку
• колбеков практически нет, настройки минимальные
• можно передать только определенные хедеры/куки
• нельзя вытащить куки обратно
TWA (Trusted Web Activities)
Обертка над ChromeTab. Используется для связи PWA (progressive web app) и нативных возможностей приложения. Позволяет опубликовать PWA в Play Market.
Внешний браузер
Тут просто пуляем Intent с Intent.ACTION_VIEW в систему, а система уже находит приложение, которое этот URL может обработать
Из минусов:
• нельзя передать информацию о юзере, ему заново придется авторизовываться
• кнопка "назад" не вернет юзера в приложение, а будет листать сайт и отбрасывать юзера на главную браузера
Для этого есть 5 вариантов:
• WebView
• GeckoView
• ChromeTabs
• TWA
• внешний браузер
WebView
Это обычная вьюшка, которая встраивается в вашу верстку
Плюсов много:
• можно отобразить хоть в диалоге, хоть на треть экрана
• можно контролировать каждый запрос (есть куча колбеков)
• можно передать любые куки и хедеры (в том числе токены пользователя, чтоб не заставлять пользователя заново авторизовываться)
• можно ограничить список ссылок, которые можно открывать
• можно настроить JS Bridge (вызывать нативный код прямо с сайта)
GeckoView
Это аналог WebView от Firefox
ChromeTab
ChromeTab — это Activity браузера Chrome, открытое поверх вашего приложения в вашей Task-e
Из плюсов:
• в ChromeTab доступен весь функционал браузера (кнопка "поделиться", поиск по странице...)
• общее с Chrome хранилище данных о юзере (если открыть ссылку, где юзер раньше авторизовывался, то он сразу окажется в своем аккаунте)
• поддерживает App Links (автоматический редирект в нативное приложение, если оно установлено)
Минусы есть:
• нельзя встроить в верстку
• колбеков практически нет, настройки минимальные
• можно передать только определенные хедеры/куки
• нельзя вытащить куки обратно
TWA (Trusted Web Activities)
Обертка над ChromeTab. Используется для связи PWA (progressive web app) и нативных возможностей приложения. Позволяет опубликовать PWA в Play Market.
Внешний браузер
Тут просто пуляем Intent с Intent.ACTION_VIEW в систему, а система уже находит приложение, которое этот URL может обработать
Из минусов:
• нельзя передать информацию о юзере, ему заново придется авторизовываться
• кнопка "назад" не вернет юзера в приложение, а будет листать сайт и отбрасывать юзера на главную браузера
👍17🦄4🐳1
Сейчас, как и лет 8 назад, опять обрели моду click-to-earn игры, ну или кликеры за монетки
Раньше там рекламу надо было смотреть и донатить за энергию, теперь ждать листинга монеты... прогресс это хорошо
В тик-токе и на ютубе куча крутых видео, как люди изобретают целые механизмы, которые автоматически или полуавтоматически кликают на экран и приносят авторам доход
Но мобильным разработчикам еще легче — у нас есть adb
Достаточно зациклить команду:
где X и Y координаты тапа на экран
готово
p.s. когда разбогатеете на этом, не забудьте, кто дал вам удочку
Раньше там рекламу надо было смотреть и донатить за энергию, теперь ждать листинга монеты... прогресс это хорошо
В тик-токе и на ютубе куча крутых видео, как люди изобретают целые механизмы, которые автоматически или полуавтоматически кликают на экран и приносят авторам доход
Но мобильным разработчикам еще легче — у нас есть adb
Достаточно зациклить команду:
adb shell input tap X Y
где X и Y координаты тапа на экран
готово
😁52🏆10⚡4👍1
произошел ребрендинг
p.s. 10 лайков и начинаю копить на экспресс-дизайн от Николая Иронова
❤46👍7
Во что упороться, если надоел обычный Android
Этот мир абсолютно понятен и захотелось челленджа?
Тогда можно попробовать:
пару лет назад нужно было жестко занырнуть в математику (матрицы, градиенты...), чтобы написать что-то свое
сейчас все работает из коробки, есть бесплатные SDK
уровень входа низкий. отличий от обычного андроида крайне мало:
• UI управляется только перемещением фокуса с пульта
• железо телека часто слабее ноунейм телефона за 4к рублей
• есть много либ, оптимизированных под телеки, но можно все писать на привычных технологиях
первые шаги можно сделать на эмуляторе (прямо в Android Studio), а потом прикупить приставку за 5к+ рублей и запускать в гостиной свое приложение
дешевые приставки не берите (я брал)
Это вечное
Можно поускорять запуск приложения, замерить количество fps в UI, поразгонять сетевые запросы, снизить прожорливость RAM и расход батареи....
Переписать свой проект, чтоб он скомпилировался под iOS)
Изучить аналоги android-библиотек, вдохновиться их подходами, добавить в резюме фулл-стек-разработчик...
тут не знаю, не играл. если есть кто работал с этим, поделитесь, сильно от мобилки отличается?
....
что еще интересное бывает?
Этот мир абсолютно понятен и захотелось челленджа?
Тогда можно попробовать:
VR / AI
пару лет назад нужно было жестко занырнуть в математику (матрицы, градиенты...), чтобы написать что-то свое
сейчас все работает из коробки, есть бесплатные SDK
AndroidTV
уровень входа низкий. отличий от обычного андроида крайне мало:
• UI управляется только перемещением фокуса с пульта
• железо телека часто слабее ноунейм телефона за 4к рублей
• есть много либ, оптимизированных под телеки, но можно все писать на привычных технологиях
первые шаги можно сделать на эмуляторе (прямо в Android Studio), а потом прикупить приставку за 5к+ рублей и запускать в гостиной свое приложение
дешевые приставки не берите (я брал)
Оптимизации
Это вечное
Можно поускорять запуск приложения, замерить количество fps в UI, поразгонять сетевые запросы, снизить прожорливость RAM и расход батареи....
Мультиплатформ + iOS
Переписать свой проект, чтоб он скомпилировался под iOS)
Изучить аналоги android-библиотек, вдохновиться их подходами, добавить в резюме фулл-стек-разработчик...
WearOS / Android Auto
тут не знаю, не играл. если есть кто работал с этим, поделитесь, сильно от мобилки отличается?
....
что еще интересное бывает?
🎄17✍16❤6👍4🍓3🔥1
Кастомные операторы
Наткнулся на либу для построения графов
Насколько она хороша не знаю, но меня зацепило, как они грациозно позволяют задать граф:
• A и E — объекты вершин, возможно уже с какими-то связями
• "C" — название для новой вершины, для которой автоматически создастся объект
и вместе они соединяются в направленный граф с помощью минуса
примерно так:
....
есть еще ситуации, когда кастомный operator реально упрощает жизнь?
operator fun minus(b: Int) = this + b 👍
Наткнулся на либу для построения графов
Насколько она хороша не знаю, но меня зацепило, как они грациозно позволяют задать граф:
LabeledGraph { A - "C" - E }
• A и E — объекты вершин, возможно уже с какими-то связями
• "C" — название для новой вершины, для которой автоматически создастся объект
и вместе они соединяются в направленный граф с помощью минуса
примерно так:
operator fun minus(new: Any) = Vertex(incoming = this, current = new)
....
есть еще ситуации, когда кастомный operator реально упрощает жизнь?
💊17👍11🌭5
Новая рубрика — #cross_post
в ней мы сравним iOS и Android технологии
и наконец-то выясним, у кого зарплата должна быть больше
попробуем разобраться, насколько отличаются эти два мира
и возможно приблизим кросс-платформу. или точно поймем, что оно нам не надо
p.s. в некоторых темах будут участвовать приглашенные эксперты и просто заслуженные мэтры iOS/Android-разработки
в ней мы сравним iOS и Android технологии
попробуем разобраться, насколько отличаются эти два мира
и возможно приблизим кросс-платформу. или точно поймем, что оно нам не надо
🔥13👍3🌭1
Coroutine и Async/Await
Общее
• позволяют писать асинхронный код последовательно
• позволяют асинхронным функциям возвращать результат синхронно, без явных
callback-ов
(Android) / completion-ов
(iOS)• раньше многопоточный код писался с помощью очередей/реактивных потоков
Coroutine
• асинхронные функции помечаются ключевым словом suspend
•
CoroutineScope
— "область", для которой задаются параметры и внутри которой выполняются suspend-функции• пул-потоков задается через
Dispatcher
• можно отменить выполнение отдельной
suspend`-функции или всего `CoroutineScope
— cancel()
• есть два основных билдера —
launch
(запускает корутину) и async/await
(создает корутину и возвращает результат)
CoroutineScope(Dispatcher.Main).launch {
val result = doSomething()
}
suspend fun doSomething(): String {
...
}
Async/await
• асинхронная функция помечается ключевым словом async, место вызова функции помечает как
await
•
Task
— это контекст, позволяющий запустить асинхронный код, относительно точки вызова. Может быть вызван, как из синхронной, так и асинхронной функции• пул потоков задается через
Actor
• можно отменить выполнение async-фукнции или всего
Task
— cancel()
•
async
-функции можно вызывать внутри Task
и других async
-функций
Task(priority: .medium) {
let result = await doSomething()
}
func doSomething() async throws -> [String] {
...
}
#cross_post
@dolgo_polo_dev
• iOS
• Android
🏆13👍12🍓2🔥1
Открыл для себя мир кастомных эмоджи в тг 🙂 🤡
апрувните, пожалуйста, канал, появится возможность настроить красивые реакции)
www.group-telegram.com/dolgo_polo_dev.com?boost
пока тестил их, нашел баг — если добавлять кастомный эмоджи в пост после двух блоков кода (например swift + kotlin), то после публикации поста эмоджи распадается на два — базовый и кастомный
🧠 --> 🧠 🧠
апрувните, пожалуйста, канал, появится возможность настроить красивые реакции)
www.group-telegram.com/dolgo_polo_dev.com?boost
Please open Telegram to view this post
VIEW IN TELEGRAM
👾8 7🐳2
Swift / Kotlin
Они оказывается жуть как похожи
И речь не о том, что они оба ООП + статически типизированы + автоматически выводят типы + не требует точки с запятой в конце строки...
Радует больше совпадение по сахарным фичам, которые есть в обоих языках:
extension
— расширение классовinternal
для ограчения видимости по модулюnull-safety
lateinit var
(Android) / lazy var
(iOS)
extension Double {
var km: Double { return self * 1_000.0 }
}
let result = 25.4.km
var x: Bool? = getXorNull()
print(x ?? false)
fun Double.km() = this * 1_000.0
val result = 25.4.km()
var x: Boolean? = getXorNull()
print(x ?: false)
#cross_post
@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18 8🦄3👎2❤1❤🔥1
Реверс-инжиниринг чужого приложения
Dolgo.polo Dev x Coffee&Code
#cross_post
💎 iOS
➖
в .ipa-файл, а в нем код в формате unix executable file (бинарь, скомпилированный код)
➖
да, если у вас есть доступ до .ipa файла (как его получить), можно с легкостью дойти до ассемблерного кода (используя Hopper, можно получить даже псевдо код)
приложения из AppStore шифруются и без jailbreak будет сложно достать что-то полезное из обфусцированного бинаря, но добрые (или не очень) люди создают сайты, где выкладывают незашифрованные бинари популярных приложений
➖
да, например тулза sideloadly позволяет пересобрать .ipa файл с дополнительным фреймворком (который мы можем написать сами)
этот фреймворк, к примеру, может случайно посвиззлить (подменить реализацию метода в рантайме) функцию начисления количества внутриигровой валюты и сделать нас миллионерами
➖
🔵 источник приложений только один — AppStore (уже нет)
🔵 подпись .ipa-файла, связанная с аккаунтом разработчика
🔵 DeviceCheck — фича, позволяющая сгенерировать токен оригинальность приложения и проверить его на бэкенде
➖
только если она в публичном доступе
в остальном, также декомпилировать и смотреть ассемблер или дампнуть хедеры (интерфейс либы)
еще есть возможность изучить библиотеку прямо в рантайме, если она написана на Objective-C, используя инструменты дебага
например можно:
🔵 запринтить все методы объекта (подробнее)
🔵 переопределить любой (да да, любой, даже приватный) метод
🔵 подменить класс в рантайме, создать класс в рантайме
🔵 вызывать любой метод (даже не объявленный)
🔵 подключить любую библиотеку (даже системные фреймворки Apple) и много чего еще
💎 Android
➖
в .apk-файл, в котором лежит java-байткод (Java/Kotlin-код компилируется в java-байткод на этапе сборки .apk)
➖
да
получить .apk-файл можно из любого приложения, установленного на устройстве
дальше достаточно использовать любую программу, умеющую превращать байткод обратно в Java-код
единственная защита от этого — обфускация кода. но она лишь усложняет читаемость кода, а не защищает от считывания
➖
да, поскольку после декомпиляции мы получаем обычный Java-код, который можем изменить его и заново собрать .apk
➖
🔵 подпись приложения
подпись — грубо говоря, уникальная строка, которая формируется на основе хэша от кода приложения и пароля, который знает только разработчик приложения
если изменить исходный код приложения, то подпись потеряет актуальность, и система не даст установить такое .apk
🔵 Play integrity API — фича, позволяющая сгенерировать токен оригинальность приложения и проверить его на бэкенде
➖
да, у нас есть доступ к исходникам любой либы, написанной на Java/Kotlin (в том числе системных/гугловских) прямо из Android Studio
💎 Выводы
все секреты, попавшие в .apk/.ipa-файл (токены/алгоритмы шифрования/пароли/протоколы...), могут быть вытащены и подменены с помощью реверс-инжиниринга на обоих платформах
на iOS изучить/подменить чужое приложение сложнее, но тоже реально
так что все что попало в .apk/.ipa-файл — считай open-source
спасибо Coffee&Code и в частности @gronzeisl за экспертизу по iOS
Dolgo.polo Dev x Coffee&Code
#cross_post
во что собирается приложение?
в .ipa-файл, а в нем код в формате unix executable file (бинарь, скомпилированный код)
можно ли декомпилировать чужое приложение?
да, если у вас есть доступ до .ipa файла (как его получить), можно с легкостью дойти до ассемблерного кода (используя Hopper, можно получить даже псевдо код)
приложения из AppStore шифруются и без jailbreak будет сложно достать что-то полезное из обфусцированного бинаря, но добрые (или не очень) люди создают сайты, где выкладывают незашифрованные бинари популярных приложений
можно ли пересобрать чужое приложение, изменив его исходники, и поставить себе на устройство?
да, например тулза sideloadly позволяет пересобрать .ipa файл с дополнительным фреймворком (который мы можем написать сами)
этот фреймворк, к примеру, может случайно посвиззлить (подменить реализацию метода в рантайме) функцию начисления количества внутриигровой валюты и сделать нас миллионерами
что защищает от хакнутых приложений?
можно ли посмотреть исходники любой библиотеки?
только если она в публичном доступе
в остальном, также декомпилировать и смотреть ассемблер или дампнуть хедеры (интерфейс либы)
еще есть возможность изучить библиотеку прямо в рантайме, если она написана на Objective-C, используя инструменты дебага
например можно:
во что собирается приложение?
в .apk-файл, в котором лежит java-байткод (Java/Kotlin-код компилируется в java-байткод на этапе сборки .apk)
можно ли декомпилировать чужое приложение?
да
получить .apk-файл можно из любого приложения, установленного на устройстве
дальше достаточно использовать любую программу, умеющую превращать байткод обратно в Java-код
единственная защита от этого — обфускация кода. но она лишь усложняет читаемость кода, а не защищает от считывания
можно ли пересобрать чужое приложение, изменив его исходники?
да, поскольку после декомпиляции мы получаем обычный Java-код, который можем изменить его и заново собрать .apk
что защищает от хакнутых приложений?
подпись — грубо говоря, уникальная строка, которая формируется на основе хэша от кода приложения и пароля, который знает только разработчик приложения
если изменить исходный код приложения, то подпись потеряет актуальность, и система не даст установить такое .apk
можно ли посмотреть исходники любой библиотеки?
да, у нас есть доступ к исходникам любой либы, написанной на Java/Kotlin (в том числе системных/гугловских) прямо из Android Studio
все секреты, попавшие в .apk/.ipa-файл (токены/алгоритмы шифрования/пароли/протоколы...), могут быть вытащены и подменены с помощью реверс-инжиниринга на обоих платформах
на iOS изучить/подменить чужое приложение сложнее, но тоже реально
так что все что попало в .apk/.ipa-файл — считай open-source
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍9👏9🎉2 2
Тут Play Market пообещал вычистить мусорные приложения, которые не имеют полезного функционала
А я вспомнил историю, рассказываю
Наверное, все слышали от стримеров/блогеров, насколько казики платят выше рынка за рекламу
Но мало где говорят, что такая же ситуация и в мобильной разработке
Лет 5 назад, когда только начинал заниматься фрилансом и постоянных заказчиков не было, часто натыкался на объявления:
Сделать приложение, которое открывает википедию в WebView. А если потрясти телефон и покричать в микрофон, открывается однорукий бандит. Оплата 10к
А 10к за приложение, которое пишется за несколько часов по шаблону — это много
Но, очевидно, делать и распространять такие приложения абсолютно незаконно ни с юридической, ни с моральной, ни с гуглплеевской точки зрения
Не брал такие заказы, и вам не советую
Есть миллион приложений, которые zip-архивы со скинами/модами кидают через Intent и ContentResolver в приложение Minecraft, тем самым устанавливая моды. Парочка из них мои)
@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
😁18 8👍3❤1☃1🤩1👾1