SDK

https://developer.android.com/guide/components/activities/parcelables-and-bundles
https://developer.android.com/reference/androidx/annotation/RequiresPermission
https://developer.android.com/develop/sensors-and-location/location/permissions
https://developer.android.com/develop/background-work/background-tasks/broadcasts
https://developer.android.com/develop/background-work/background-tasks/broadcasts/broadcast-exceptions
https://developer.android.com/guide/topics/providers/content-providers
https://developer.android.com/guide/topics/providers/content-provider-basics
https://developer.android.com/guide/topics/providers/content-provider-creating
https://developer.android.com/guide/topics/providers/document-provider
https://developer.android.com/guide/topics/providers/create-document-provider
https://developer.android.com/guide/topics/providers/cloud-media-provider
Manifest

Важный файл в корне проекта который описывает информацию о приложении для инструментов сборки, операционной системы и Google Play.

BroadcastReceiver можно не указывать в манифесте.

exported

Атрибут устанавливает может ли компонент запускаться компонентами других приложений.

configChanges

Атрибут для перечисления конфигураций (ориентация, направление макета, клавиатура, локализация) при изменении которых компонент не пересоздается. Будет вызван метод onConfigurationChanged.

process

Устанавливает имя процесса в котором работает сервис. Обычно все компоненты приложения работают в процессе по умолчанию, созданном для приложения. Он имеет то же имя, что и пакет приложения.

• если имя назначенное этому атрибуту, начинается с двоеточия : при необходимости создается новый процесс, закрытый для приложения, и служба запускается в этом процессе.

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

Manifest Variables

<meta-data
    android:name="apiKey"android:value="${apiKey}"/>
defaultConfig {
    manifestPlaceholders += mapOf("apiKey" to "key")
}

Context

Интерфейс, предоставляющий доступ к информации о текущем состоянии приложения и его среде выполнения. Это основной компонент, который позволяет объектам взаимодействовать с системными ресурсами и службами. Божественный объект.

Доступ к ресурсам: Через Context можно получить доступ к ресурсам приложения, таким как строки, изображения и макеты, используя методы вроде getResources и getString.

Запуск компонентов: Context позволяет запускать активити, сервисы и получать доступ к BroadcastReceiver. Например, метод startActivity используется для запуска новых активити.

Доступ к файловой системе: Через Context можно получить доступ к файловой системе приложения, используя методы getFilesDir, getCacheDir и другие.

Преференции: Для работы с хранилищем предпочтений можно использовать методы getSharedPreferences.

Системные службы: Context позволяет получить доступ к различным системным службам, например, через метод getSystemService, чтобы взаимодействовать с компонентами, такими как LocationManager, ConnectivityManager, и другими.

// Получение Application Context
val appContext = context.applicationContext

// Запуск новой активити
val intent = Intent(context, NewActivity::class.java)
context.startActivity(intent)

// Доступ к ресурсам
val myString = context.getString(R.string.my_string)

// Работа с SharedPreferences
val prefs = context.getSharedPreferences("my_prefs", Context.MODE_PRIVATE)

Application Context

Это глобальный контекст для всего приложения. Он создается при запуске приложения и доступен через метод getApplicationContext у активити или сервиса. Подходит для задач, которые не зависят от конкретной активности, таких как работа с базой данных, регистрация сервисов, управление глобальными настройками или доступ к ресурсам приложения, которые не зависят от UI.

Activity Context

Этот контекст связан с жизненным циклом активити и предоставляется при создании активити. Доступен через this в активити. Подходит для задач, зависящих от активити, таких как создание диалогов, привязка адаптеров, запуск другой активности, или доступ к ресурсам, специфичным для текущей активити.

Service Context

Похож на Activity Context, но связан с жизненным циклом сервиса. Может быть получен через this в сервисе.

Application

Базовый класс для поддержания глобального состояния приложения. Создается перед любым другим классом при создании процесса приложения.

Application.onCreate

Вызывается при запуске приложения до создания activity, service или receiver (за исключением ContentProvider). Реализации должны быть максимально быстрыми (например, с использованием ленивой инициализации), поскольку время, затраченное на эту функцию, напрямую влияет на производительность.

registerActivityLifecycleCallbacks

Метод, позволяющий зарегистрировать коллбэк, сообщающий о вызове методов lifecycle всех activity в приложении.

BroadcastReceiver

BroadcastReceiver

Используется для отправки и получения различных событий, например: загрузка системы, смена языка/способа ввода, переход в режим полета, зарядка батареи. Приложения могут уведомлять друг друга о загрузке новых данных. Приложения могут получать события 2 способами: через ресиверы, объявленные в манифесте и ресиверы, зарегистрированные в контексте. Если объявлен в манифесте, система запустит приложение при отправке рассылки. Диспетчер системных пакетов регистрирует приемник при установке приложения. Затем приемник становится отдельной точкой входа в приложение, что означает, что система может запустить приложение и доставить трансляцию, если он в данный момент не запущено. Система создает новый BroadcastReceiver объект для обработки каждой получаемой рассылки. Этот объект действителен только на время вызова onReceive(Context, Intent) (вызывается в основном потоке). Как только код возвращается из этого метода, система считает, что компонент больше не активен. Можно установить ограничения как для отправителя, так и для получателя рассылки. Разрешения позволяют ограничивать трансляции набором приложений, обладающих определенными разрешениями. В Android 4.0 и выше можно указать пакет с setPackage(String) при отправке трансляции. Система ограничивает трансляцию набором приложений, соответствующих пакету

sendOrderedBroadcast

Отправляет сообщения одному получателю за раз. Поскольку каждый получатель выполняется по очереди, он может передать результат следующему получателю или полностью прервать широковещательную рассылку, чтобы она не передавалась другим получателям. Запущенными получателями заказов можно управлять с помощью атрибута android:priority соответствующего фильтра намерений; приемники с одинаковым приоритетом будут запускаться в произвольном порядке

sendBroadcast

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

LocalBroadcastManager.sendBroadcast

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

Явный BroadcastReceiver

Явные BroadcastReceiver регистрируются в коде приложения, через метод registerReceiver() или в AndroidManifest.xml с использованием конкретного Intent и его компонентов. Явный BroadcastReceiver отправляется с конкретным Intent, который явно указывает класс приемника. То есть, вы явно указываете компонент, который должен обработать этот Intent. Обычно используется для коммуникации между компонентами вашего приложения.

// Регистрация в коде
val intent = Intent(this, MyReceiver::class.java)
sendBroadcast(intent)

Неявный BroadcastReceiver

Неявные BroadcastReceiver регистрируются через IntentFilter, который указывает на действие или категорию, но не на конкретный класс приемника. Регистрация может быть выполнена в коде приложения через registerReceiver() или в AndroidManifest.xml, где фильтры настраиваются с использованием действия или категории. Неявный BroadcastReceiver отправляется с Intent, который содержит действия, категории или другие данные, но не указывает конкретный класс приемника. Обычно используется для обработки системных событий или событий от других приложений. Например, действия, такие как изменение состояния сети, получение сообщения, изменение состояния батареи и другие системные события.

// Регистрация в коде
val intent = Intent("com.example.MY_ACTION")
sendBroadcast(intent)

Ограничения

• Начиная с Android 7.0 (API 24) не работают ACTION_NEW_PICTURE и ACTION_NEW_VIDEO, и объявление получателя в манифесте для CONNECTIVITY_ACTION.

• Начиная с Android 8.0 (API 26) система ограничивает получателей, объявленных в манифесте для большинства трансляций не нацеленных конкретно на приложение, можно регистрировать вручную.

• Начиная с Android 9 (API 28) не работает получение данных о местонахождении пользователя или данные, позволяющие установить личность (NETWORK_STATE_CHANGED_ACTION)

ContentProvider

Предоставляет контент для приложений через единый интерфейс. Пример: доступ к словарям пользователя, хранилищу, контактам, календарям. ContentProvider работает как ворота: может дать доступ к файлу, или не дать, позволяет удалять файлы, проверяет permissions, которые рекомендуется использовать меньше, если это не файловый менеджер, для файлов есть специальный FileProvider, который может временно предоставлять доступ к файлу по uri, эта модель безопасна, когда в onActivityResult возвращается intent там есть флаг GRANT_URI_PERMISSION.

Permissions

Runtime Permissions (Dangerous)

Опасные разрешения, предоставляющие доступ к данным с ограниченным доступом и действиям, которые существенно влияют на систему и другие приложения. Начиная с API 23 перед перед выполнением опасных действий нужно запросить у пользователя разрешение в runtime.
• dangerous samples:
location contacts storage contacts phone calls camera microphone

shouldShowRequestPermissionRationale

Этот метод возвращает true, если приложение ранее запросило это разрешение, а пользователь отклонил запрос.

Notifications

Notification Channel

Начиная с Android 8.0 (API level 26) для каждого уведомления необходимо указывать канал. Пользователь может управлять визуальным и звуковым поведением, которое будет применяться ко всем уведомлениям в канале. Например, разные каналы в приложении часы для будильников, таймеров, секундомеров

Bundle

Класс c массивом пар ключ-значение. Включает get и put методы для примитивов, строк и объектов, которые реализуют интерфейсы Parcelable и Serializable. Используется для передачи данных между базовыми компонентами и для сохранения состояния.

• Bundle проверяет типы данных при добавлении и извлечении, что помогает предотвратить ошибки типа.

• Для предотвращения потерь данных, Bundle обеспечивает надежную упаковку данных в формате Parcel и гарантирует, что все данные будут корректно сохранены и переданы.

• Указывать capacity для лучшего перфоманса.

• Не реализует equals и hashCode.

• Буфер транзакций Binder имеет фиксированный размер 1 MB, который используется всеми транзакциями в процессе, если размер превышен генерируется TransactionTooLargeException

val bundle: Bundle = Bundle(10)

val bundle: Bundle = bundleOf(
    "name" to "John",
    "age" to 80
)
Parcelable

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

Если класс реализует интерфейс Parcelable, поля класса сериализуются в методе writeToParcel(). Также parcelable класс обязан иметь статическое ненулевое поле, названное CREATOR типа Creator. Интерфейс Creator имеет два метода createFromParcel(parcel: Parcel): T и newArray(size: Int): Array. Эти методы обратные writeToParcel() и используются для чтения данных из Parcel и создания объекта. Объект Parcelable записывается в контейнер Parcel, который имеет метод marshall(): Array для представления объекта в виде массива байтов. Parcel предназначен для передачи данных при межпроцессорной коммуникации. При изменении структуры объекта или реализации метода writeToParcel() байтовое представление, которое возвращается методом marshall(), будет изменено. Поэтому строго не рекомендуется записывать его в персистентное хранилище.

Что быстрее parcelable или serializable?

В режиме «ручного управления» быстрее Serializable, тогда он не использует reflection и сериализует поля вручную через методы writeObject() и readObject(). В другие случаях быстрее Parcelable, потому что разработчик управляет методами преобразования

LruCache

Кэш, который содержит ссылки на ограниченное количество значений. При каждом доступе к объекту оно перемещается в начало очереди. При добавлении объекта, если кэш переполнен, значение в конце вытесняется и может быть собрано сборщиком мусора. По умолчанию размер кэша измеряется количеством записей. Следует использовать, когда загрузка ресурсов влияет на отзывчивость приложения (хранить эскизы изображений)

val maxMemory: Long = Runtime.getRuntime().maxMemory() / 1024
val cacheSize: Int = (maxMemory / 8).toInt()

val lruCache: BitmapCache = BitmapCache(cacheSize)

class BitmapCache(maxSize: Int): LruCache<String, Bitmap>(maxSize) {

    fun getBitmapFromMemory(key: String): Bitmap? {
        return this.get(key)
    }

    fun setBitmapToMemory(key: String, bitmap: Bitmap) {
        if (getBitmapFromMemory(key) == null) {
            this.put(key, bitmap)
        }
    }
}

Reflection API

Механизм исследования данных о программе во время её выполнения. Рефлексия позволяет исследовать информацию о полях, методах и конструкторах классов.

class Bank {
    private val money = "$300"
}

fun main() = runBlocking {
    val money = Bank::class
        .memberProperties
        .first { it.name == "money" }
        .apply { isAccessible = true }
        .get(Bank()) as String
    println(money)
}

XML
https://developer.android.com/develop/ui/views/layout/declaring-layout
https://developer.android.com/reference/android/util/Xml

Extensible Markup Language. Язык разметки, используемый для описания данных. В Android в основном используется для описания данных, связанных с UI.

<merge>

Используется для оптимизации макетов в Android и упрощения их структурирования. Этот тег помогает избежать ненужного уровня вложенности в иерархии макетов, что может способствовать улучшению производительности и читаемости кода. Позволяет объединить содержимое нескольких макетов в один без добавления дополнительных контейнеров. Когда вы используете тег <merge>, все его дочерние элементы будут “встраиваться” в макет, который его включает. Таким образом, элементы внутри <merge> не будут добавлены в иерархию в виде отдельного уровня, что снижает количество необходимых ViewGroup и упрощает иерархию.

<!-- layout/fragment_example.xml -->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView
        android:id="@+id/example_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World" />

    <Button
        android:id="@+id/example_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me" />
</merge>

<include>

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

<!-- layout/activity_main.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include
        layout="@layout/fragment_example" />

</LinearLayout>

Sensor
https://developer.android.com/reference/android/hardware/Sensor
https://developer.android.com/reference/android/hardware/SensorManager
https://developer.android.com/reference/android/hardware/SensorEvent
https://developer.android.com/reference/android/hardware/SensorEventListener

Sensor

Предоставляет методы для определения возможностей, которые доступны конкретному датчику.

SensorManager

Предоставляет методы регистрации активности с датчиков и их калибровки.

SensorEvent

Предоставляет необработанные данные датчика, включая информацию о точности.

SensorEventListener

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

Drawable
https://developer.android.com/guide/topics/resources/drawable-resource

Drawable

Абстрактный класс, представляющий ресурс, который можно нарисовать на экране. Он является основной единицей для отображения изображений, графики и других визуальных элементов в приложении. В частности, объекты Drawable используются для установки фона, иконок, анимаций и других графических элементов в интерфейсе пользователя.

BitmapDrawable

Представляет изображение (растровое изображение) из ресурсов, обычно это файлы .png, .jpg или .gif.

ShapeDrawable

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

LayerDrawable

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

StateListDrawable

Это набор Drawable, которые могут изменяться в зависимости от состояния элемента интерфейса (например, нажатия, фокуса и т. д.). Часто используется для создания кнопок, которые меняют вид при взаимодействии с пользователем.

NinePatchDrawable

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

VectorDrawable

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

AnimationDrawable

Это последовательность изображений, которая используется для создания анимации путем переключения кадров.

Window
https://developer.android.com/reference/android/view/Window

Это абстрактный класс, который не является наследником Activity Fragment или View. Класс Window контролирует что и как рисуется на экране. Активити имеет один инстанс Window который можно получить методом getWindow. Window в свою очередь, имеет объект Surface и единственную иерархию View. Android-приложение использует WindowManager для создания объектов типа Window и Surface на котором рисуется контент Window. Когда UI должен обновиться, на объекте Surface вызывается метод lockCanvas который возвращает объект типа Canvas. Canvas передается вниз по иерархии View ассоциированной с Window и каждая view рисует себя на канвасе.

Android SDK. Вопросы на собесе
  1. Для чего нужен AndroidManifest?
  1. Какие компоненты можно не указывать в манифесте?
  1. В крэшлитике увидели TransacionTooLargeException. Что будем делать?
  1. Что бы ты улучшил в OS Android?
  1. Чем Parcelable отличается от Serializable?
  1. Что быстрее Parcelable или Serializable?
  1. В чем разница между dangerous и normal разрешениями?
  1. Можно ли отозвать полученное разрешение?
  1. Что значит статус show rationale у разрешения?
  1. Почему передавать данные между компонентами рекомендуется через Bundle?
  1. Чем вызвано ограничение на размер Bundle?
  1. Чем lifecycleOwner отличается от viewLifecycleOwner?
  1. Как получить доступ к данным сенсора в Android-приложении?
  1. Какие типы Drawable существуют в Android, и в чем их различия?
  1. Зачем нужны теги merge и include в Xml?
  1. Различие между явным и неявным BroadcastReceiver?
  1. Что нужно определить приложению для работы с ContentProvider?
  1. Разница между Serializable и Parcelable?

    Serializable — это стандартный Java метод, который медленнее, но проще в использовании, так как требует лишь реализации интерфейса Serializable.

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

  1. Какое ограничение размера у Bundle?

    Не имеет строгого ограничения по размеру, но рекомендуется, чтобы размер данных не превышал 1MB. Превышение этого размера может привести к ошибкам и проблемам с производительностью.

  1. Почему в Bundle введено ограничение на 1 MB?

    Ограничение введено для оптимизации производительности и предотвращения проблем с передачей данных между процессами (Binder), так как слишком большие данные могут привести к ошибкам и блокировке IPC (межпроцессного взаимодействия).

  1. Какие типы данных поддерживает Bundle?

    Boolean Byte Char CharSequence Double Float Int Long Short String

    String[] CharSequence[]

    Parcelable (включая массивы Parcelable[])

    Serializable

    Bundle (вложенные Bundle)

    ArrayList<T> (где T может быть из вышеперечисленных типов или Parcelable/Serializable объектов)

  1. Основные компоненты приложения Android?

    Activity

    Service

    BroadcastReceiver

    ContentProvider

  1. Что бы ты улучшил в OS Android?

    FindMyDevice

    AirDrop

    Общий буфер обмена

    Нативная реализация без JVM

  1. Как перехватить все Runtime-исключения в Android-приложении?

    Установить Thread.setDefaultUncaughtExceptionHandler в Application.onCreate

  1. Что в Android можно использовать для анимаций?

    ObjectAnimator

    ValueAnimator

    AnimatorSet

    MotionLayout

  1. Какое ключевое слово используется для доступа к ресурсам приложения (например, строкам или изображениям) в коде? (

    R

    resources

    this

    getResources()

  1. Какой из следующих классов используется для создания анимаций в Android?

    AnimationManager

    AnimationController

    AnimationUtils

    AnimationHandler

  1. Что из перечисленного является основными компонентами Android?

    Application

    Service

    Fragment

    Activity

  1. Какой из следующих классов используется для работы с разрешениями в Android?

    PermissionsHandler

    PermissionsManager

    ActivityCompat

    PermissionsCompat