Obtener informes de fallos del NDK de Android

Si su aplicación de Android contiene bibliotecas nativas , puede habilitar seguimientos de pila completos e informes de fallas detallados para su código nativo desde Firebase Crashlytics con algunas pequeñas actualizaciones en la configuración de compilación de su aplicación.

Esta guía describe cómo configurar los informes de fallos con Firebase Crashlytics SDK para NDK.

Si está buscando cómo comenzar con Crashlytics en sus proyectos de Unity, consulte la guía de introducción a Unity .

Antes de que empieces

  1. Si aún no lo has hecho, agrega Firebase a tu proyecto de Android. Si no tiene una aplicación para Android, puede descargar una aplicación de muestra .

  2. Recomendado : para obtener automáticamente registros de ruta de navegación para comprender las acciones del usuario que conducen a un evento de falla, no fatal o ANR, debe habilitar Google Analytics en su proyecto de Firebase.

    • Si su proyecto Firebase existente no tiene Google Analytics habilitado, puede habilitar Google Analytics desde la pestaña Integraciones de su > Configuración del proyecto en Firebase console.

    • Si estás creando un nuevo proyecto de Firebase, habilita Google Analytics durante el flujo de trabajo de creación del proyecto.

Paso 1 : agregue el SDK de Crashlytics para NDK a su aplicación

En el archivo Gradle de su módulo (nivel de aplicación) (generalmente <project>/<app-module>/build.gradle.kts o <project>/<app-module>/build.gradle ), agregue la dependencia para Crashlytics NDK biblioteca para Android. Recomendamos utilizar Firebase Android BoM para controlar el control de versiones de la biblioteca.

Para una experiencia óptima con Crashlytics, recomendamos habilitar Google Analytics en su proyecto de Firebase y agregar el SDK de Firebase para Google Analytics a su aplicación.

dependencies {
    // Import the BoM for the Firebase platform
    implementation(platform("com.google.firebase:firebase-bom:32.7.2"))

    // Add the dependencies for the Crashlytics NDK and Analytics libraries
    // When using the BoM, you don't specify versions in Firebase library dependencies
    implementation("com.google.firebase:firebase-crashlytics-ndk")
    implementation("com.google.firebase:firebase-analytics")
}

Al usar Firebase Android BoM , su aplicación siempre usará versiones compatibles de las bibliotecas de Firebase Android.

(Alternativa) Agregue dependencias de la biblioteca de Firebase sin usar la BoM

Si elige no utilizar la BoM de Firebase, debe especificar cada versión de la biblioteca de Firebase en su línea de dependencia.

Tenga en cuenta que si usa varias bibliotecas de Firebase en su aplicación, le recomendamos encarecidamente usar la BoM para administrar las versiones de la biblioteca, lo que garantiza que todas las versiones sean compatibles.

dependencies {
    // Add the dependencies for the Crashlytics NDK and Analytics libraries
    // When NOT using the BoM, you must specify versions in Firebase library dependencies
    implementation("com.google.firebase:firebase-crashlytics-ndk:18.6.2")
    implementation("com.google.firebase:firebase-analytics:21.5.1")
}
¿Busca un módulo de biblioteca específico de Kotlin? A partir de octubre de 2023 (Firebase BoM 32.5.0) , tanto los desarrolladores de Kotlin como los de Java podrán depender del módulo de biblioteca principal (para más detalles, consulte las preguntas frecuentes sobre esta iniciativa ).

Paso 2 : agregue el complemento Crashlytics Gradle a su aplicación

  1. En su archivo Gradle de nivel raíz (nivel de proyecto) ( <project>/build.gradle.kts o <project>/build.gradle ), agregue el complemento Crashlytics Gradle al bloque plugins :

    Kotlin

    plugins {
        id("com.android.application") version "7.3.0" apply false
        // ...
    
        // Make sure that you have the Google services Gradle plugin dependency
        id("com.google.gms.google-services") version "4.4.1" apply false
    
        // Add the dependency for the Crashlytics Gradle plugin
        id("com.google.firebase.crashlytics") version "2.9.9" apply false
    }
    

    Groovy

    plugins {
        id 'com.android.application' version '7.3.0' apply false
        // ...
    
        // Make sure that you have the Google services Gradle plugin dependency
        id 'com.google.gms.google-services' version '4.4.1' apply false
    
        // Add the dependency for the Crashlytics Gradle plugin
        id 'com.google.firebase.crashlytics' version '2.9.9' apply false
    }
    
  2. En el archivo Gradle de su módulo (nivel de aplicación) (generalmente <project>/<app-module>/build.gradle.kts o <project>/<app-module>/build.gradle ), agregue el complemento Crashlytics Gradle:

    Kotlin

    plugins {
      id("com.android.application")
      // ...
    
      // Make sure that you have the Google services Gradle plugin
      id("com.google.gms.google-services")
    
      // Add the Crashlytics Gradle plugin
      id("com.google.firebase.crashlytics")
    }

    Groovy

    plugins {
      id 'com.android.application'
      // ...
    
      // Make sure that you have the Google services Gradle plugin
      id 'com.google.gms.google-services'
    
      // Add the Crashlytics Gradle plugin
      id 'com.google.firebase.crashlytics'
    }

Paso 3 : agrega la extensión Crashlytics a tu compilación

En el archivo Gradle de su módulo (nivel de aplicación) (generalmente <project>/<app-module>/build.gradle.kts o <project>/<app-module>/build.gradle ), configure la extensión Crashlytics.

Kotlin

import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension

// ...

android {
  // ...
  buildTypes {
      getByName("release") {
          // Add this extension
          configure<CrashlyticsExtension> {
              // Enable processing and uploading of native symbols to Firebase servers.
              // By default, this is disabled to improve build speeds.
              // This flag must be enabled to see properly-symbolicated native
              // stack traces in the Crashlytics dashboard.
              nativeSymbolUploadEnabled = true
          }
      }
  }
}

Groovy

// ...

android {
  // ...
  buildTypes {
      release {
          // Add this extension
          firebaseCrashlytics {
              // Enable processing and uploading of native symbols to Firebase servers.
              // By default, this is disabled to improve build speeds.
              // This flag must be enabled to see properly-symbolicated native
              // stack traces in the Crashlytics dashboard.
              nativeSymbolUploadEnabled true
          }
      }
  }
}

Paso 4 : Configura la carga automática de símbolos nativos

Para producir seguimientos de pila legibles a partir de fallas del NDK, Crashlytics necesita conocer los símbolos en sus archivos binarios nativos. El complemento Crashlytics Gradle incluye la tarea uploadCrashlyticsSymbolFile BUILD_VARIANT para automatizar este proceso.

  1. Para que pueda acceder a la tarea de carga automática de símbolos, asegúrese de que nativeSymbolUploadEnabled esté configurado en true en el archivo Gradle de su módulo (nivel de aplicación).

  2. Para que los nombres de los métodos aparezcan en los seguimientos de la pila, debes invocar explícitamente la tarea uploadCrashlyticsSymbolFile BUILD_VARIANT después de cada compilación de tu biblioteca NDK. Por ejemplo:

    >./gradlew app:assembleBUILD_VARIANT\
               app:uploadCrashlyticsSymbolFileBUILD_VARIANT
    
  3. Tanto el SDK de Crashlytics para NDK como el complemento Crashlytics Gradle dependen de la presencia del ID de compilación de GNU dentro de los objetos compartidos nativos.

    Puede verificar la presencia de esta ID ejecutando readelf -n en cada binario. Si el ID de compilación está ausente, agregue -Wl,--build-id a los indicadores de su sistema de compilación para solucionar el problema.

Paso 5 : fuerce una prueba de bloqueo para finalizar la configuración

Para terminar de configurar Crashlytics y ver los datos iniciales en el panel de Crashlytics de Firebase console, debes forzar una prueba de bloqueo.

  1. Agregue código a su aplicación que pueda usar para forzar una falla de prueba.

    Puede usar el siguiente código en MainActivity de su aplicación para agregar un botón a su aplicación que, cuando se presiona, provoca un bloqueo. El botón tiene la etiqueta "Test Crash".

    Kotlin+KTX

    val crashButton = Button(this)
    crashButton.text = "Test Crash"
    crashButton.setOnClickListener {
       throw RuntimeException("Test Crash") // Force a crash
    }
    
    addContentView(crashButton, ViewGroup.LayoutParams(
           ViewGroup.LayoutParams.MATCH_PARENT,
           ViewGroup.LayoutParams.WRAP_CONTENT))
    

    Java

    Button crashButton = new Button(this);
    crashButton.setText("Test Crash");
    crashButton.setOnClickListener(new View.OnClickListener() {
       public void onClick(View view) {
           throw new RuntimeException("Test Crash"); // Force a crash
       }
    });
    
    addContentView(crashButton, new ViewGroup.LayoutParams(
           ViewGroup.LayoutParams.MATCH_PARENT,
           ViewGroup.LayoutParams.WRAP_CONTENT));
    
  2. Cree y ejecute su aplicación.

  3. Fuerza el bloqueo de prueba para enviar el primer informe de bloqueo de tu aplicación:

    1. Abra su aplicación desde su dispositivo de prueba o emulador.

    2. En su aplicación, presione el botón "Probar bloqueo" que agregó usando el código anterior.

    3. Después de que su aplicación falle, reiníciela para que pueda enviar el informe de fallas a Firebase.

  4. Vaya al panel de Crashlytics de Firebase console para ver el fallo de su prueba.

    Si actualizó la consola y aún no ve el fallo de prueba después de cinco minutos, habilite el registro de depuración para ver si su aplicación envía informes de fallos.


¡Y eso es! Crashlytics ahora monitorea su aplicación en busca de fallas y usted puede ver e investigar informes y estadísticas de fallas en el panel de Crashlytics.

Próximos pasos

  • (Recomendado) Obtenga ayuda para depurar fallas causadas por errores de memoria nativa recopilando informes de GWP-ASan . Estos errores relacionados con la memoria pueden estar asociados con daños en la memoria dentro de su aplicación, que es la causa principal de las vulnerabilidades de seguridad de las aplicaciones. Para aprovechar esta función de depuración, asegúrese de que su aplicación tenga GWP-ASan explícitamente habilitado y use el último SDK de Crashlytics para NDK (v18.3.6+ o Firebase BoM v31.3.0+).

  • Personalice la configuración de su informe de fallos agregando informes, registros, claves y seguimiento de errores no fatales.

  • Integre con Google Play para que pueda filtrar los informes de fallos de su aplicación de Android por seguimiento de Google Play directamente en el panel de Crashlytics. Esto le permite centrar mejor su panel en compilaciones específicas.

Solución de problemas

Si ves diferentes seguimientos de pila en Firebase console y en logcat, consulta la guía de solución de problemas .



Opciones alternativas para cargar símbolos

El flujo de trabajo principal de esta página anterior se aplica a las compilaciones estándar de Gradle. Sin embargo, algunas aplicaciones utilizan una configuración o herramientas diferentes (por ejemplo, un proceso de compilación distinto de Gradle). En estas situaciones, las siguientes opciones pueden resultar útiles para cargar símbolos correctamente.

Opción : cargar símbolos para módulos de biblioteca y dependencias externas

Esta opción puede resultar útil en las siguientes situaciones:

  • Si utiliza un proceso de compilación de NDK personalizado dentro de Gradle
  • Si sus bibliotecas nativas están integradas en una biblioteca/módulo de funciones o las proporciona un tercero
  • Si la tarea de carga automática de símbolos falla o ves fallas no simbolizadas en el panel

Opción : cargar símbolos para compilaciones que no sean de Gradle o bibliotecas nativas no eliminadas inaccesibles

Esta opción puede resultar útil en las siguientes situaciones:

  • Si utiliza un proceso de compilación que no sea Gradle

  • Si sus bibliotecas nativas no eliminadas se le proporcionan de alguna manera a la que no se puede acceder durante las compilaciones de Gradle