SDK
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
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. Вопросы на собесе
- Для чего нужен AndroidManifest?
- Какие компоненты можно не указывать в манифесте?
- В крэшлитике увидели TransacionTooLargeException. Что будем делать?
- Что бы ты улучшил в OS Android?
- Чем Parcelable отличается от Serializable?
- Что быстрее Parcelable или Serializable?
- В чем разница между dangerous и normal разрешениями?
- Можно ли отозвать полученное разрешение?
- Что значит статус show rationale у разрешения?
- Почему передавать данные между компонентами рекомендуется через Bundle?
- Чем вызвано ограничение на размер Bundle?
- Чем lifecycleOwner отличается от viewLifecycleOwner?
- Как получить доступ к данным сенсора в Android-приложении?
- Какие типы Drawable существуют в Android, и в чем их различия?
- Зачем нужны теги merge и include в Xml?
- Различие между явным и неявным BroadcastReceiver?
- Что нужно определить приложению для работы с ContentProvider?
- Разница между Serializable и Parcelable?
•
Serializable
— это стандартный Java метод, который медленнее, но проще в использовании, так как требует лишь реализации интерфейсаSerializable
.•
Parcelable
— это Android-специфический метод, который более эффективен и быстрый, но требует явного определения способов сериализации и десериализации данных.
- Какое ограничение размера у Bundle?
Не имеет строгого ограничения по размеру, но рекомендуется, чтобы размер данных не превышал 1MB. Превышение этого размера может привести к ошибкам и проблемам с производительностью.
- Почему в Bundle введено ограничение на 1 MB?
Ограничение введено для оптимизации производительности и предотвращения проблем с передачей данных между процессами (Binder), так как слишком большие данные могут привести к ошибкам и блокировке IPC (межпроцессного взаимодействия).
- Какие типы данных поддерживает Bundle?
•
Boolean
Byte
Char
CharSequence
Double
Float
Int
Long
Short
String
•
String[]
CharSequence[]
•
Parcelable
(включая массивыParcelable[]
)•
Serializable
•
Bundle
(вложенныеBundle
)•
ArrayList<T>
(где T может быть из вышеперечисленных типов илиParcelable
/Serializable
объектов)
- Основные компоненты приложения Android?
•
Activity
•
Service
•
BroadcastReceiver
•
ContentProvider
- Что бы ты улучшил в OS Android?
• FindMyDevice
• AirDrop
• Общий буфер обмена
• Нативная реализация без JVM
- Как перехватить все Runtime-исключения в Android-приложении?
Установить Thread.setDefaultUncaughtExceptionHandler в Application.onCreate
- Что в Android можно использовать для анимаций?
•
ObjectAnimator
• ValueAnimator
•
AnimatorSet
•
MotionLayout
- Какое ключевое слово используется для доступа к ресурсам приложения (например, строкам или изображениям) в коде? (
•
R
• resources
•
this
•
getResources()
- Какой из следующих классов используется для создания анимаций в Android?
• AnimationManager
• AnimationController
• AnimationUtils
• AnimationHandler
- Что из перечисленного является основными компонентами Android?
•
Application
•
Service
•
Fragment
•
Activity
- Какой из следующих классов используется для работы с разрешениями в Android?
• PermissionsHandler
• PermissionsManager
•
ActivityCompat
• PermissionsCompat