Ошибка java.lang.RuntimeException: Unable to start activity ComponentInfo возникает в тот момент, когда Android пытается создать и запустить Activity, но процесс прерывается исключением — приложение аварийно закрывается сразу после нажатия на иконку или при переходе на другой экран. В логах это выглядит как цепочка Caused by, где ComponentInfo содержит имя пакета и класс проблемной Activity, например {com.example.app/com.example.app.MainActivity}.
Важно понимать: сама строка Unable to start activity — это лишь обёртка, а реальная причина скрыта глубже в стектрейсе. Чаще всего это NullPointerException в методе onCreate(), отсутствующий ресурс, неправильно объявленная Activity в манифесте или ошибка инициализации View. Ниже разберём, как читать стектрейс, какие причины встречаются чаще всего и как их устранить.
Как читать стектрейс и находить первопричину
Ключ к решению — блок Caused by: в нижней части лога. Именно там указано исходное исключение и строка кода, которая его вызвала. Верхняя часть стектрейса показывает только путь вызова через системные классы Android (ActivityThread.performLaunchActivity, handleLaunchActivity) и для диагностики почти бесполезна.
Откройте Logcat в Android Studio, отфильтруйте вывод по имени пакета и найдите последнюю строку Caused by. Рядом будет ссылка вида at com.example.app.MainActivity.onCreate(MainActivity.java:42) — клик по ней ведёт прямо к проблемной строке. Если причин несколько, читайте цепочку снизу вверх: самое нижнее исключение — корневое.
- 🔍 Найдите в Logcat строку
Caused by— она указывает тип исходной ошибки. - 📍 Перейдите по ссылке на файл и номер строки в стектрейсе.
- 🧩 Проверьте, какой объект используется в этой строке и мог ли он быть равен
null. - 🔁 Воспроизведите ошибку повторно с включённым логированием, чтобы убедиться в стабильности сценария.
Типичные причины ошибки
Хотя текст исключения один и тот же, внутренние причины различаются. Ниже — наиболее распространённые сценарии, с которыми сталкиваются разработчики Android-приложений.
| Исключение в «Caused by» | Вероятная причина | Где искать |
|---|---|---|
| NullPointerException | Обращение к View или объекту до инициализации | onCreate(), findViewById |
| Resources.NotFoundException | Отсутствует layout, строка или drawable-ресурс | setContentView(), res/ |
| ClassNotFoundException | Activity объявлена в манифесте, но класс удалён или переименован | AndroidManifest.xml |
| IllegalStateException | Некорректная работа с фрагментами или состоянием | onCreate(), FragmentTransaction |
| InflateException | Ошибка в XML-разметке: неверный атрибут или кастомная View | layout-файл Activity |
Обратите внимание: одна и та же строка «Unable to start activity» может скрывать десятки разных причин, поэтому копировать чужое решение с форумов без анализа собственного стектрейса почти всегда бесполезно.
NullPointerException в onCreate() — самый частый сценарий
Классическая ситуация: вы вызываете findViewById(R.id.button) и сразу вешаете на результат обработчик, но View с таким ID в текущем layout отсутствует. Метод возвращает null, и обращение к нему роняет приложение. Вторая типовая ошибка — вызов findViewById до setContentView(), когда иерархия View ещё не создана.
Правильный порядок в onCreate() выглядит так:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.button)
button.setOnClickListener { / действие / }
}
Также проверьте, что ID в разметке и в коде совпадают с учётом регистра, и что вы загружаете именно тот layout-файл, в котором находится нужный элемент. Если используются варианты разметки (например, layout-land), элемент должен присутствовать во всех версиях либо код должен проверять результат на null.
Проблемы с AndroidManifest.xml
Если Activity не объявлена в манифесте, при её запуске система выбрасывает ActivityNotFoundException. Но бывает и обратная ситуация: Activity объявлена, а класс переименовали или переместили в другой пакет — тогда в «Caused by» появится ClassNotFoundException. Проверьте, что атрибут android:name указывает на реально существующий класс с актуальным пакетом.
Типичная корректная запись выглядит так:
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
⚠️ Внимание: начиная с Android 12 (API 31), для Activity с
intent-filterобязательно нужно явно указывать атрибутandroid:exported. Без него приложение может не установиться или упасть при запуске на современных устройствах.
Ещё одна тонкость — точка в начале имени класса (.MainActivity) означает, что класс ищется относительно пакета приложения. Если вы изменили applicationId или структуру пакетов, относительные имена могут перестать разрешаться корректно.
Отсутствующие ресурсы и ошибки разметки
Исключение Resources.NotFoundException возникает, когда setContentView() ссылается на несуществующий layout, либо код запрашивает строку, цвет или drawable, которых нет в ресурсах. Такое бывает после слияния веток в системе контроля версий, удаления «неиспользуемых» ресурсов или ошибок в названиях файлов.
Отдельный случай — InflateException. Он означает, что XML-разметка не смогла превратиться в дерево View: например, в файле указана кастомная View с неверным полным именем класса или неподдерживаемый атрибут. В стектрейсе при этом будет указан конкретный тег и строка XML-файла.
☑️ Проверка ресурсов и разметки
Ошибки при передаче данных между Activity
Если падение происходит при открытии второго экрана, проверьте, как вы читаете данные из Intent. Вызов intent.getStringExtra("key") вернёт null, если ключ не передали или опечатались в его имени. Дальнейшее использование этого значения без проверки — прямой путь к NullPointerException внутри onCreate() целевой Activity.
Рекомендуется задавать значения по умолчанию и проверять nullable-результаты. В Kotlin удобно использовать элвис-оператор: val name = intent.getStringExtra("name") ?: "". Также полезно хранить ключи extras в константах, чтобы исключить опечатки на обеих сторонах — и в отправляющей, и в принимающей Activity.
Почему ошибка проявляется только на некоторых устройствах
Разные версии Android по-разному обрабатывают ресурсы и жизненный цикл. Например, на устройствах с другой плотностью экрана может подхватываться альтернативный вариант ресурса, где отсутствует нужный элемент. Также производители иногда меняют поведение системных компонентов. Поэтому тестируйте запуск на эмуляторах с разными API-уровнями и хотя бы на одном реальном устройстве.
Пошаговый алгоритм диагностики
Чтобы не гадать, действуйте последовательно — от чтения лога к точечному исправлению. Ниже универсальный порядок, который не зависит от конкретного проекта.
- 📋 Откройте Logcat и скопируйте полный стектрейс с момента падения.
- 🔎 Найдите последнюю строку
Caused byи определите тип исключения. - 🎯 Перейдите по ссылке к строке кода и проверьте все объекты, которые там используются.
- 🧪 Проверьте манифест, ресурсы и порядок вызовов в
onCreate(). - ♻️ После исправления выполните Clean/Rebuild и повторите сценарий запуска.
⚠️ Внимание: не маскируйте ошибку пустыми блоками
try-catchвокруг всегоonCreate(). Это скроет падение, но приложение останется в некорректном состоянии — экран будет пустым, а найти настоящую причину станет ещё сложнее.
Если после всех проверок причина не ясна, добавьте временное логирование (Log.d) перед подозрительными строками и выведите значения переменных. Это безопасный способ локализовать проблему без изменения логики приложения.
Часто задаваемые вопросы
Что означает ComponentInfo в тексте ошибки?
ComponentInfo — это идентификатор компонента, который система пыталась запустить. В фигурных скобках указаны пакет приложения и полное имя класса Activity. По этой записи можно сразу понять, какой именно экран стал источником падения.
Ошибка возникает только у пользователей, а на моём устройстве всё работает. Что делать?
Вероятно, проблема зависит от версии Android, разрешения экрана или локали устройства. Подключите инструмент сбора crash-отчётов (например, Firebase Crashlytics), чтобы получать полные стектрейсы с устройств пользователей, и проверьте альтернативные варианты ресурсов в проекте.
Может ли ошибка быть связана с ProGuard или R8?
Да, в релизных сборках обфускация иногда удаляет или переименовывает классы, которые используются через рефлексию или указаны в XML строками. Если ошибка появляется только в release-APK, проверьте правила proguard-rules.pro и добавьте keep-правила для затронутых классов.
Почему приложение падает после обновления библиотеки?
Новая версия библиотеки могла изменить API или потребовать дополнительной инициализации в Application-классе. Изучите changelog библиотеки и проверьте, вызываются ли все обязательные методы инициализации до запуска Activity.
Как быстро проверить, что проблема именно в onCreate()?
Поставьте точку останова на первой строке onCreate() и запустите приложение в режиме отладки. Пошаговое выполнение (Step Over) покажет, на какой именно строке возникает исключение и какие переменные в этот момент равны null.