Avatar ·

Приложение крашится с ошибкой "Unfortunately MyApp has stopped". Как исправить?

Всем привет! Я новичок в Android-разработке на Kotlin. Написал простое приложение — список задач (ToDo). При запуске на эмуляторе всё работало, но когда я установил APK на свой реальный телефон (Samsung Galaxy A50, Android 11), приложение вылетает сразу после открытия с сообщением "Unfortunately MyApp has stopped". Вот мой код MainActivity.kt: ```kotlin class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val recyclerView = findViewById(R.id.recycler_tasks) val tasks = listOf("Купить хлеб", "Позвонить маме", "Сделать ДЗ") val adapter = TaskAdapter(tasks) recyclerView.adapter = adapter recyclerView.layoutManager = LinearLayoutManager(this) } } ``` И адаптер TaskAdapter.kt: ```kotlin class TaskAdapter(private val tasks: List) : RecyclerView.Adapter() { class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val textView: TextView = itemView.findViewById(R.id.task_text) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_task, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { holder.textView.text = tasks[position] } override fun getItemCount() = tasks.size } ``` В логах Logcat вижу только: ``` E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.myapp, PID: 12345 java.lang.RuntimeException: Unable to start activity ComponentInfo{...}: android.view.InflateException: Binary XML file line #2: ... ``` Что я делаю не так? Как понять, в чём именно проблема? Очень раздражает, что приложение просто падает без понятного сообщения. Заранее спасибо за помощь! <<>>

Понимание ошибки и диагностика

Сообщение "Unfortunately MyApp has stopped" — это стандартное системное уведомление Android, которое появляется, когда в приложении возникает необработанное исключение (crash). Само по себе оно не говорит о причине, но ключ к разгадке — в Logcat. Вы уже на правильном пути, увидев там FATAL EXCEPTION. Однако в вашем логе обрезана самая важная часть — стек-трейс (stack trace).

Как получить полный стек-трейс

  1. Подключите телефон к компьютеру через USB.
  2. В Android Studio откройте вкладку Logcat (обычно внизу).
  3. В фильтре выберите No Filters и поставьте уровень Error.
  4. Запустите приложение заново — вы увидите полный красный текст. Скопируйте его полностью.

Если у вас нет доступа к Android Studio, используйте adb logcat в терминале:

adb logcat -v long *:E

Анализ вашего кода и типичная проблема

Глядя на ваш код, я вижу вероятную причину: проблема с разметкой (layout). Ошибка InflateException: Binary XML file line #2 указывает, что Android не может создать View из XML-файла. Чаще всего это происходит из-за:

  • Отсутствия обязательного атрибута (например, android:layout_width и android:layout_height).
  • Неправильного имени класса View (например, опечатка в androidx.recyclerview.widget.RecyclerView).
  • Несовместимости версий библиотек (например, используете androidx, а в XML — старый android.support).

Решение: проверьте XML-файлы

Первым делом проверьте activity_main.xml и item_task.xml. Вот пример корректного activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_tasks"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

И item_task.xml для элемента списка:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp">

    <TextView
        android:id="@+id/task_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp" />

</LinearLayout>

Универсальный рецепт отладки крашей

Чтобы в будущем не гадать, добавьте глобальный обработчик исключений в класс Application. Это позволит вам видеть полную ошибку даже без Logcat:

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
            // Сохраняем ошибку в файл или отправляем на сервер
            Log.e("CRASH", "Unhandled exception", throwable)
            // Можно показать диалог с деталями (только для отладки)
            val stackTrace = Log.getStackTraceString(throwable)
            Toast.makeText(this, "Ошибка: ${throwable.message}", Toast.LENGTH_LONG).show()
        }
    }
}

Не забудьте добавить android:name=".MyApp" в <application> в AndroidManifest.xml.

Быстрая проверка зависимостей

Убедитесь, что в build.gradle (Module: app) у вас подключены правильные зависимости:

dependencies {
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'androidx.recyclerview:recyclerview:1.3.2'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
}

После исправления XML и синхронизации Gradle приложение должно запуститься без краша.

<<>>

Альтернативный подход: использование Crashlytics

Если вы хотите профессионально отслеживать краши в продакшене, рекомендую подключить Firebase Crashlytics. Это бесплатный сервис, который автоматически ловит все исключения и показывает их в удобной панели управления.

Как подключить Crashlytics:

  1. Добавьте Firebase в проект через Firebase Console.
  2. В build.gradle (project) добавьте: classpath 'com.google.gms:google-services:4.3.15'
  3. В build.gradle (app) добавьте:
    implementation 'com.google.firebase:firebase-crashlytics-ktx:18.4.3'
    implementation 'com.google.firebase:firebase-analytics-ktx:21.3.0'
  4. В AndroidManifest.xml добавьте метаданные для отключения отчётов в режиме отладки (по желанию).

Почему это лучше ручного поиска?

  • Вы получаете полный стек-трейс с указанием строки кода.
  • Crashlytics группирует одинаковые ошибки и показывает их частоту.
  • Работает даже на устройствах пользователей, к которым у вас нет доступа.

В вашем случае Crashlytics сразу бы показал InflateException с указанием конкретного файла и строки XML, где проблема. Это сэкономило бы часы догадок.