Введение: «Невидимая» ошибка, которая ломает сборку
Вы пишете приложение на Kotlin, всё идёт отлично, но вдруг — бац! — Android Studio подсвечивает красным строку, а в логах сборки появляется устрашающее сообщение:
Default interface methods are only supported starting with Android 7.0 (Nougat)
Знакомая ситуация? Если вы новичок в Android-разработке, эта ошибка может показаться настоящей загадкой. Вы ведь просто используете интерфейс с методом по умолчанию — что может пойти не так?
На самом деле, проблема кроется в несовместимости minSdkVersion вашего приложения и возможностей языка Kotlin (который внутри использует фичи Java 8).
В этой статье мы разберёмся, почему возникает эта ошибка, как её исправить, и как писать современный код, не теряя поддержки старых устройств. Поехали!
Что такое «default interface method» и почему он появился?
Начнём с основ. В старых версиях Java (до 8) интерфейсы могли содержать только объявления методов — без реализации. Но с приходом Java 8 появилась возможность добавлять в интерфейсы методы с телом (так называемые дефолтные методы).
Kotlin, будучи современным языком, полностью поддерживает эту концепцию. Например:
interface Logger {
fun log(message: String)
fun logWithTimestamp(message: String) {
log("${System.currentTimeMillis()}: $message")
}
}
Здесь logWithTimestamp — это default interface method. Если класс реализует Logger, он может не переопределять этот метод, а использовать реализацию «по умолчанию». Удобно, правда?
Проблема в том, что на уровне байт-кода Android такие методы требуют поддержки со стороны операционной системы. И эта поддержка появилась только в Android 7.0 (Nougat, API 24).
Почему возникает ошибка в Android Studio?
Когда вы устанавливаете minSdkVersion ниже 24 (например, 21 или 23), компилятор Android видит, что ваше приложение может работать на устройствах с Android 6.0 или 5.0. А на этих версиях дефолтные методы интерфейсов не поддерживаются на уровне виртуальной машины (Dalvik/ART).
Именно поэтому компилятор выдаёт ошибку:
Default interface methods are only supported starting with Android 7.0 (Nougat)
Он буквально говорит: «Я не могу скомпилировать этот код, потому что твоё приложение может запуститься на устройстве, которое не умеет выполнять такие методы».
Типичный сценарий, когда это происходит
Чаще всего ошибка возникает в двух случаях:
- Использование Kotlin-коллекций (например,
listOf,mapOf) — у них есть методы по умолчанию. - Использование сторонних библиотек, которые внутри содержат интерфейсы с дефолтными методами.
- Работа с Android Jetpack (например,
LifecycleObserverилиDefaultLifecycleObserver).
Вы даже можете не писать собственные интерфейсы с default-методами — ошибка всё равно появится, если какая-то из зависимостей их использует.
Как исправить ошибку? 3 проверенных способа
Давайте рассмотрим все возможные решения — от самого простого до более гибкого.
Способ 1: Поднять minSdkVersion до 24
Это самое прямолинейное решение. Если ваше приложение не обязано поддерживать устройства старше Android 7.0, просто измените minSdkVersion в файле build.gradle (на уровне модуля):
android {
...
defaultConfig {
minSdkVersion 24
targetSdkVersion 34
...
}
}
Плюсы: быстро, чисто, не нужно менять код.
Минусы: вы теряете до 10-15% пользователей (особенно в Азии и Африке, где популярны старые устройства).
Способ 2: Включить desugaring (рекомендуемый для новичков)
Desugaring — это процесс, при котором компилятор преобразует современные конструкции Java 8/Kotlin в байт-код, понятный старым версиям Android. Включить его очень просто.
В файле build.gradle (уровень модуля) добавьте:
android {
...
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
// остальные зависимости
}
После синхронизации Gradle ошибка исчезнет, и вы сможете использовать дефолтные методы интерфейсов даже с minSdkVersion 21.
Важно: Убедитесь, что версия desugar_jdk_libs актуальна. На момент написания статьи это 2.0.4, но лучше проверять на официальной странице документации.
Способ 3: Использовать альтернативные конструкции (для перфекционистов)
Если вы не хотите включать desugaring и не можете поднять minSdkVersion, можно переписать код, избегая default-методов. Например, вместо:
interface Logger {
fun log(message: String)
fun logWithTimestamp(message: String) {
log("${System.currentTimeMillis()}: $message")
}
}
Используйте абстрактный класс:
abstract class Logger {
abstract fun log(message: String)
fun logWithTimestamp(message: String) {
log("${System.currentTimeMillis()}: $message")
}
}
Или вынесите метод-расширение:
interface Logger {
fun log(message: String)
}
fun Logger.logWithTimestamp(message: String) {
log("${System.currentTimeMillis()}: $message")
}
Этот способ требует больше ручной работы, но полностью устраняет проблему без изменения конфигурации сборки.
Что выбрать новичку?
Мой совет: используйте способ 2 (desugaring). Он:
- ✅ Сохраняет поддержку старых устройств (до API 21)
- ✅ Не требует переписывания кода
- ✅ Поддерживается Google официально
- ✅ Работает с Kotlin 1.5+ и Android Gradle Plugin 4.0+