Интересно Android: Huawei без Google Play, динамические обновления и советы Сноудена

Takeshi

Перо Дьявола
Команда форума
PR-group
CPA & Трафик
Регистрация
23 Янв 2019
Сообщения
1,351
Баллы
0
Общие продажи
0$
Общие покупки
0$
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Huawei Mate 30 без Google Play

Please Login or Register to view hidden text.

— хорошая статья о том, как Huawei может выйти из ситуации, когда флагманы компании (линейка Huawei Mate 30) не могут поставляться на рынок с предустановленными приложениями и сервисами Google.

Чтобы иметь возможность установить на свои смартфоны набор приложений Google (в том числе магазин приложений), компания-производитель должна отправить в Google свой смартфон, где он проходит тесты совместимости Compatibility Test Suite (CTS) и Google Test Suite (GTS), а также подписать соглашение Mobile Application Distribution Agreement (MADA).

Все это открывает перед производителем возможность установить на свои смартфоны ключевые приложения Google (Google Play Store, Google Chrome, Google Maps и т. д.) и необходимый для их работы набор сервисов (Core Services).

Huawei по причине торговой войны США и Китая больше не может подписать новое соглашение MADA с Google, а потому по закону не имеет права предустанавливать приложения Google на смартфоны, продающиеся на территории большинства стран. Также они не могут дать пользователям возможность установить эти приложения самостоятельно, так как ключевые приложения Google (в первую очередь магазин приложений) и набор сервисов должны иметь расширенные права, а значит, быть предустановлеными в системный раздел.

Поначалу казалось, что у Huawei есть выход. Дело в том, что в прошлом они (а также компания Xiaomi и другие китайские производители) уже научились обходить такие ограничения. Трюк состоит в том, чтобы предустановить в систему только набор сервисов Google и добавить разрешения для приложений Google в общесистемный файл разрешений. В таком случае установленные из сторонних источников приложения Google автоматически получат нужные разрешения и будут полностью работоспособны. Осталось только дать пользователям какой-то инсталлятор для автоматической доустановки маркета и всего остального софта.

Судя по всему, в данном случае трюк осуществить не получилось, но выход все равно нашелся. Это кастомный инсталлятор сервисов Google

Please Login or Register to view hidden text.

, который может предустановить на смартфоны Huawei все необходимые сервисы и сам магазин приложений. При этом сообщение «Device is uncertified» на смартфоне не появляется, а это значит, что Google добавила Mate 30 в белый список сертифицированных устройств, несмотря на бан Huawei.

Динамические обновления Android

Please Login or Register to view hidden text.

— статья о расширении функции Dynamic System Updates в Android 10/11.

Функция Dynamic System Updates (DSU) появилась в третьей бета-версии Android 10 как ответ на необходимость временной установки тестовых версий ОС, при которой не затрагивается основная версия Android, установленная на смартфон. DSU базируется на технологии Dynamic Partitions, которая позволяет «сдвинуть» раздел data и создать в освободившемся месте новые разделы system и data, которые будут использованы для установки еще одной прошивки рядом с основной.

В финальной версии Android 10 DSU доступен в смартфонах линейки Pixel, но только для так называемых GSI-образов ОС (Generic System Image), которые выпускает сама Google на базе AOSP. Но совсем недавно в AOSP появился

Please Login or Register to view hidden text.

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

Что из этого всего следует? Во-первых, это не способ организовать мультизагрузку на смартфоне (по аналогии с MultiROM). Это лишь способ тестирования прошивок, после перезагрузки происходит автоматический откат к основной прошивке. Во-вторых, это действительно удобный способ для тестирования бета-версий прошивок без необходимости удалять основную прошивку.

Еще в Google анонсировали поддержку так называемой разметки «диска» Virtual A/B. Это развитие идеи разметки A/B, появившейся еще в Android 8 и предполагающей существование сразу двух разделов system. В одном разделе установлена текущая версия прошивки, в другой устанавливается обновление. После перезагрузки они меняются местами.

Разметка A/B позволяет устанавливать обновления прошивки в фоне и защищает от ситуаций, когда обновление может окирпичить смартфон (в этом случае смартфон автоматически загрузится со «старого» раздела system). Однако кроме самой Google мало какой производитель захотел использовать такую разметку ввиду банальной экономии пространства в памяти устройства. Virtual A/B позволяет решить эту проблему путем создания временного раздела system, который может быть удален после удачного обновления.

Какой телефон использовал бы Эдвард Сноуден

Please Login or Register to view hidden text.

— компиляция

Please Login or Register to view hidden text.

Эдварда Сноудена о том, какой сетап следует использовать для сохранения конфиденциальности при использовании смартфона. Тезисы:

  • прошивка GrapheneOS (от создателя

    Please Login or Register to view hidden text.

    );
  • выход в интернет только через Tor;
  • использование Ethernet (!) вместо Wi-Fi и мобильной сети (это действительно можно сделать с помощью USB-донгла);
  • блокировщик рекламы;
  • файрвол с блокировкой доступа к интернету для большинства приложений (можно использовать AFWall);
  • блокировка сторонних кукисов в браузере;
  • никакого e-mail;
  • общение только в Signal и Wire.
РАЗРАБОТЧИКУ
Умные анимации


Please Login or Register to view hidden text.

— статья одного из разработчиков Android, посвященная созданию консистентных умных анимаций, способных работать в паре с реактивными UI-фреймворками.

В качестве примера автор приводит следующую функцию, предназначенную для анимации появления/исчезновения элемента на экране:

fun animateVisibility(view: View, visible: Boolean) {
view.visibility = View.VISIBLE
if (visible) {
ObjectAnimator.ofFloat(view, View.ALPHA, 0f, 1f).start()
} else {
ObjectAnimator.ofFloat(view, View.ALPHA, 1f, 0f).apply {
doOnEnd { view.visibility = View.GONE }
}.start()
}
}

Эта функция будет отлично работать в приложении, написанном в классической манере без использования реактивных фреймворков и паттернов (MVVM, MVI). Если же мы используем реактивный подход, когда модель данных может изменяться непредсказуемо, а UI должен незамедлительно реагировать на изменения, то мы получим минимум две проблемы.

  1. Приложение не готово к получению новых данных во время проигрывания анимации, нужен способ сбросить все листенеры и остановить анимацию.
  2. Анимация всегда начинается с начала (с максимального или минимального значения альфа-канала), поэтому — даже если решить первую проблему — анимация станет «дерганой», когда данные будут приходить во время проигрывания анимации.
Решить вторую проблему очень легко, достаточно просто не указывать начальное состояние анимации — и при повторном запуске она начнется с того же места:

- ObjectAnimator.ofFloat(view, View.ALPHA, 0f, 1f).start()
+ ObjectAnimator.ofFloat(view, View.ALPHA, 1f).start()

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

fun animateVisibility(view: View, visible: Boolean) {
+ val targetAlpha = if (visible) 1f else 0f
+ if (view.alpha == targetAlpha) return

Далее нам необходимо сделать так, чтобы текущая анимация останавливалась перед началом следующей. Для этого можно нагородить огород костылей, а можно просто заменить ObjectAnimator на метод View.animate():

- val anim = ObjectAnimator.ofFloat(view, View.ALPHA, targetAlpha)
- if (!visible) {
- anim.doOnEnd { view.visibility = View.GONE }
- }
+ val anim = view.animate().alpha(targetAlpha)
+ if (!visible) {
+ anim.withEndAction { view.visibility = View.GONE }
+ }

Это все. Теперь у нас есть анимация, которая всегда будет выглядеть консистентно.

В статье автор также приводит пример решения этих проблем для анимации перемещения элементов, но это уже совсем другая история.

Типы Unit, Nothing, Any в Kotlin

Please Login or Register to view hidden text.

— статья, поясняющая суть типов данных Unit, Nothing и Any в языке Kotlin.

  • Unit — эквивалент типа void в Java. Другими словами, он нужен для того, чтобы показать, что функция ничего не возвращает. Unit наследуется от типа Any, а при работе с Java-кодом автоматически транслируется в void.
  • Nothing — класс, являющийся субклассом любого класса (именно так) и не позволяющий создать объект своего типа (конструктор приватный). Используется для представления результата исполнения функции, которая никогда не завершается (скажем, потому что она выбрасывает исключение). Пример:
public inline fun TODO(): Nothing = throw NotImplementedError()
// Ошибки компиляции не будет, потому что Nothing — субкласс любого класса, в том числе Player
fun determineWinner(): Player = TODO()

  • Any — родитель всех остальных классов. Аналог Object в Java.
Обзор новой функции биндинга View-элементов в Android Studio

Please Login or Register to view hidden text.

— рассказ о новой функции Android Studio, появившейся в версии 3.6 Canary 11. View Binding позволяет получить доступ к View-элементам, определенным в XML, простым и типобезопасным способом, не требующим использовать функцию findViewById().

Чтобы продемонстрировать, как это работает, возьмем следующий XML, описывающий простенький интерфейс (add_profile.xml):

<?xml version="1.0" encoding="utf-8">
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="

Please Login or Register to view hidden text.

"
xmlns:app="

Please Login or Register to view hidden text.

"
xmlns:tools="

Please Login or Register to view hidden text.

"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/button_authenticate"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/button_add_profile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="@string/label_authenticate"
android:layout_marginBottom="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>

Теперь открываем код активности и пишем следующее:

private lateinit var binding: AddProfileBinding

...

@Override
fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)

binding = AddProfileBinding.inflate(layoutInflater)
setContentView(binding.root)

binding.textTitle.text = getString(R.string.some_string)
binding.buttonAddProfile.setOnClickListener {
...
}
}

Этот код покажет на экране приведенный выше интерфейс, а также присвоит TextView под именем text_title строку R.string.some_string и назначит на кнопку button_add_profile какое-то действие.

Может показаться, что автор пропустил важную часть кода, но это не так. Функция View Binding автоматически создает для каждого XML-файла класс, получающий имя XML-файла с отброшенными символами подчеркивания и словом Binding в конце. В данном примере Android Studio создал класс AddProfileBinding для файла add_profile_xml.

Используя этот класс, мы затем отобразили интерфейс на экране и получили доступ к TextView и кнопке, которые по аналогии с именем класса получили имена на основе их id в XML-файле. Идентификатор text_title стал textTitle, а button_add_profile стала buttonAddProfile.

Это действительно все. Больше никаких проблем с поиском View с помощью findViewById(), никаких null на месте ненайденных элементов и ошибок типов. Просто и ясно.

Чтобы все это работало, необходимо установить Android Studio 3.6 Canary 11 и добавить в build.gradle следующую строку:

android {

viewBinding {
enabled = true
}
}


Инструменты повышения производительности приложения

Please Login or Register to view hidden text.

— небольшой обзор сторонних инструментов и библиотек, позволяющих повысить стабильность и производительность приложения.


  • Please Login or Register to view hidden text.

    — известная библиотека, автоматически сообщающая об утечках памяти.

  • Please Login or Register to view hidden text.

    — аналог LeakCanary, позволяющий отловить блокировки основного потока приложения (лаги); по ссылке форк оригинального проекта, корректно работающий в новых версиях Android.

  • Please Login or Register to view hidden text.

    — показывает производительность методов onCreate(), onStart() и onResume().

  • Please Login or Register to view hidden text.

    — показывает текущий FPS приложения.

  • Please Login or Register to view hidden text.

    — инструмент трассировки методов, реализованный в форме полноценного форка Android (разработка Uber).

  • Please Login or Register to view hidden text.

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

  • Please Login or Register to view hidden text.

    — модульный инструмент для оценки производительности приложения.

ИНСТРУМЕНТЫ
  • Andromeda — интерактивный инструмент реверса Android-приложений.
  • Obfuscapk — модульный обфускатор, не требующий исходный код приложения.
  • EVABS — тренировочное приложение, уязвимое к разным типам атак.
  • Malware Timeline 2019 — сборник малвари для Android, найденной в 2019 году.
  • Android-Malware-Sandbox — скрипт для быстрого развертывания пентест-окружения на базе эмулятора Android, Frida и Mitmproxy.
  • VyAPI — очередное уязвимое приложение для проверки скилов пентестинга.
  • dump_hprof.py — скрипт для дампа хипа Android-приложений с помощью Frida.
  • xia0FridaScript — набор подсобных функций для Frida.
  • iOS-messaging-tools — набор утилит для обнаружения и эксплуатации уязвимости в iMessage.
  • leetdump — дампер памяти Android-процессов.