קבלת דוחות קריסה של Android NDK

אם אפליקציית Android שלכם מכילה ספריות Native, תוכלו להפעיל מעקב סטאק מלא ודוחות מפורטים על קריסות בקוד ה-Native מ-Firebase Crashlytics באמצעות כמה עדכונים קטנים בהגדרות ה-build של האפליקציה.

במדריך הזה מוסבר איך להגדיר דיווח על קריסות באמצעות Firebase Crashlytics SDK ל-NDK.

רוצים לדעת איך מתחילים לעבוד עם Crashlytics בפרויקטים ב-Unity? כדאי לעיין במדריך לתחילת השימוש ב-Unity.

לפני שמתחילים

  1. אם עדיין לא עשיתם זאת, מוסיפים את Firebase לפרויקט Android. אם אין לכם אפליקציה ל-Android, תוכלו להוריד אפליקציה לדוגמה.

  2. מומלץ: כדי לקבל באופן אוטומטי יומני נתיב ולעזור לכם להבין את הפעולות של המשתמשים שהובילו לקריסה, לאירוע לא קטלני או לאירוע ANR, צריך להפעיל את Google Analytics בפרויקט Firebase.

    • אם Google Analytics לא מופעל בפרויקט הקיים ב-Firebase, תוכלו להפעיל אותו בכרטיסייה Integrations (שילובים) בקטע > Project settings במסוף Firebase.Google Analytics

    • אם אתם יוצרים פרויקט חדש ב-Firebase, צריך להפעיל את Google Analytics במהלך תהליך יצירת הפרויקט.

  3. מוודאים שהאפליקציה שלכם מותקנת בגרסאות המינימליות הבאות:

    • Gradle 8.0
    • Android Gradle plugin 8.1.0
    • פלאגין Gradle של שירותי Google 4.4.1

שלב 1: מוסיפים לאפליקציה את ה-SDK של Crashlytics ל-NDK

בקובץ Gradle של המודול (ברמת האפליקציה) (בדרך כלל <project>/<app-module>/build.gradle.kts או <project>/<app-module>/build.gradle), מוסיפים את התלות בספריית NDK‏ Crashlytics ל-Android. מומלץ להשתמש ב-Firebase Android BoM כדי לשלוט בגרסאות הספרייה.

כדי ליהנות מחוויית שימוש אופטימלית ב-Crashlytics, מומלץ להפעיל את Google Analytics בפרויקט Firebase ולהוסיף את Firebase SDK for Google Analytics לאפליקציה.

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

    // 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")
}

כשמשתמשים ב-Firebase Android BoM, האפליקציה תמיד תשתמש בגרסאות תואמות של ספריות Firebase ל-Android.

אם בוחרים לא להשתמש ב-Firebase BoM, צריך לציין את כל הגרסאות של ספריות Firebase בשורת התלות שלהן.

שימו לב: אם אתם משתמשים במספר ספריות של Firebase באפליקציה, מומלץ מאוד להשתמש ב-BoM כדי לנהל את הגרסאות של הספריות, וכך לוודא שכל הגרסאות תואמות.

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:19.4.0")
    implementation("com.google.firebase:firebase-analytics:22.2.0")
}
מחפשים מודול ספרייה ספציפי ל-Kotlin? החל מ-אוקטובר 2023 (Firebase BoM 32.5.0), מפתחי Kotlin ומפתחי Java יוכלו להסתמך על מודול הספרייה הראשי (פרטים נוספים זמינים בשאלות הנפוצות בנושא היוזמה הזו).

שלב 2: מוסיפים את הפלאגין Crashlytics של Gradle לאפליקציה

  1. בקובץ Gradle ברמת הבסיס (ברמת הפרויקט) (<project>/build.gradle.kts או <project>/build.gradle), מוסיפים את הפלאגין Crashlytics ל-Gradle לבלוק plugins:

    KotlinGroovy
    plugins {
        // Make sure that you have the AGP plugin 8.1+ dependency
        id("com.android.application") version "8.1.4" apply false
        // ...
    
        // Make sure that you have the Google services Gradle plugin 4.4.1+ dependency
        id("com.google.gms.google-services") version "4.4.2" apply false
    
        // Add the dependency for the Crashlytics Gradle plugin
        id("com.google.firebase.crashlytics") version "3.0.3" apply false
    }
    plugins {
        // Make sure that you have the AGP plugin 8.1+ dependency
        id 'com.android.application' version '8.1.4' apply false
        // ...
    
        // Make sure that you have the Google services Gradle plugin 4.4.1+ dependency
        id 'com.google.gms.google-services' version '4.4.2' apply false
    
        // Add the dependency for the Crashlytics Gradle plugin
        id 'com.google.firebase.crashlytics' version '3.0.3' apply false
    }
  2. בקובץ Gradle של המודול (ברמת האפליקציה) (בדרך כלל <project>/<app-module>/build.gradle.kts או <project>/<app-module>/build.gradle), מוסיפים את הפלאגין Crashlytics של Gradle:

    KotlinGroovy
    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")
    }
    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'
    }

שלב 3: מוסיפים את התוסף של Crashlytics לגרסה היציבה (build)

מגדירים את התוסף של Crashlytics בקובץ Gradle של המודול (ברמת האפליקציה) (בדרך כלל <project>/<app-module>/build.gradle.kts או <project>/<app-module>/build.gradle).

KotlinGroovy
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
          }
      }
  }
}
// ...

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
          }
      }
  }
}

שלב 4: מגדירים העלאה אוטומטית של סמלים מקומיים

כדי ליצור מעקב סטאק קריא מקשות ב-NDK, Crashlytics צריך לדעת על הסמלים בקובצי הבינארי הנוכחיים. הפלאגין Crashlytics של Gradle כולל את המשימה uploadCrashlyticsSymbolFileBUILD_VARIANT כדי לבצע אוטומציה של התהליך הזה.

  1. כדי שתוכלו לגשת למשימה של העלאת סמלים אוטומטית, הקפידו שהערך של nativeSymbolUploadEnabled יהיה true בקובץ Gradle של המודול (ברמת האפליקציה).

  2. כדי ששמות השיטות יופיעו בנתוני המעקב אחר סטאק, צריך להפעיל את המשימה uploadCrashlyticsSymbolFileBUILD_VARIANT באופן מפורש אחרי כל build של ספריית ה-NDK. לדוגמה:

    >./gradlew app:assembleBUILD_VARIANT\
               app:uploadCrashlyticsSymbolFileBUILD_VARIANT
  3. גם ה-SDK של Crashlytics ל-NDK וגם הפלאגין Crashlytics ל-Gradle תלויים בנוכחות של מזהה ה-build של GNU בתוך האובייקטים המשותפים הניידים.

    כדי לוודא שהמזהה הזה קיים, מריצים את הפקודה readelf -n בכל קובץ בינארי. אם מזהה ה-build לא מופיע, מוסיפים את הדגל -Wl,--build-id לדגלים של מערכת ה-build כדי לפתור את הבעיה.

שלב 5: מפעילים קריסה לצורך בדיקה כדי לסיים את ההגדרה

כדי לסיים את ההגדרה של Crashlytics ולראות נתונים ראשוניים בלוח הבקרה Crashlytics במסוף Firebase, צריך לאלץ קריסה לצורך בדיקה.

  1. מוסיפים לאפליקציה קוד שבעזרתו אפשר לאלץ קריסה לצורך בדיקה.

    אפשר להשתמש בקוד הבא ב-MainActivity של האפליקציה כדי להוסיף לה לחצן שיגרום לקריסה כשתלחצו עליו. הלחצן נקרא 'בדיקת קריסה'.

    KotlinJava
    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))
    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. יוצרים את האפליקציה ומריצים אותה.

  3. מפעילים את הקריסה לצורך בדיקה כדי לשלוח את דוח הקריסה הראשון של האפליקציה:

    1. פותחים את האפליקציה במכשיר הבדיקה או במהדמ.

    2. באפליקציה, לוחצים על הלחצן 'בדיקת קריסה' שהוספתם באמצעות הקוד שלמעלה.

    3. אחרי שהאפליקציה קורסת, מפעילים אותה מחדש כדי שהיא תוכל לשלוח את דוח הקריסה ל-Firebase.

  4. עוברים אל מרכז הבקרה של Crashlytics במסוף Firebase כדי לראות את קריסה של הבדיקה.

    אם רעננתם את המסוף ועדיין לא ראיתם את קריסת הבדיקה אחרי חמש דקות, הפעילו את יומני ניפוי הבאגים כדי לראות אם האפליקציה שולחת דוחות קריסה.


וזהו זה. Crashlytics עוקב עכשיו אחרי קריסות באפליקציה, ותוכלו להציג ולבדוק סטטיסטיקות ודוחות קריסה במרכז הבקרה של Crashlytics.

השלבים הבאים

  • (מומלץ) כדי לקבל עזרה בניפוי באגים של קריסות שנגרמו על ידי שגיאות זיכרון נייטיב, צריך לאסוף דוחות GWP-ASan. שגיאות שקשורות לזיכרון יכולות להיות קשורות לזיהום זיכרון באפליקציה, שהיא הסיבה העיקרית לפרצות אבטחה באפליקציות. כדי ליהנות מתכונה לניפוי באגים, צריך לוודא שהאפליקציה מופעלת באופן מפורש ב-GWP-ASan ושנעשה בה שימוש ב-SDK העדכני ביותר של Crashlytics ל-NDK (גרסה 18.3.6 ואילך או Firebase BoM גרסה 31.3.0 ואילך).

  • התאמה אישית של ההגדרות של דוח הקריסה: הוספת דיווח על הסכמה, יומנים, מפתחות ומעקב אחרי שגיאות לא קטלניות.

  • שילבו את השירות עם Google Play כדי שתוכלו לסנן את דוחות הקריסה של אפליקציית Android לפי Google Play טרקר ישירות בלוח הבקרה Crashlytics. כך תוכלו להתמקד טוב יותר בלוחות הבקרה ב-builds ספציפיים.

פתרון בעיות

אם מופיעים קווים שונים של סטאק במסוף Firebase וב-logcat, כדאי לעיין במדריך לפתרון בעיות.



אפשרויות חלופיות להעלאת סמלים

תהליך העבודה הראשי שמתואר למעלה בדף הזה רלוונטי לגרסאות build רגילות של Gradle. עם זאת, באפליקציות מסוימות נעשה שימוש בהגדרות או בכלים שונים (לדוגמה, תהליך build שאינו Gradle). במקרים כאלה, יכול להיות שהאפשרויות הבאות יעזרו לכם להעלות סמלים.

אפשרות: העלאת סמלים של מודולים בספרייה ושל יחסי תלות חיצוניים

האפשרות הזו יכולה להיות שימושית במקרים הבאים:

  • אם משתמשים בתהליך build מותאם אישית של NDK ב-Gradle
  • אם הספריות המקומיות שלכם נוצרו בספרייה או במודול תכונה, או שסופקו על ידי צד שלישי
  • אם המשימה של העלאת הסמלים באופן אוטומטי נכשלת או אם מוצגים בוחנים ללא סימון בחלונית הבקרה

המשימה הרגילה להעלאת סמלים של Crashlytics מבוססת על ההנחה שאתם יוצרים את הספריות הילידיות כחלק מה-build של מודול האפליקציה ב-Gradle, באמצעות כלי build רגילים של NDK כמו CMake.

עם זאת, אם אתם משתמשים בתהליך build מותאם אישית של NDK ב-Gradle, או שהספריות המקומיות שלכם נוצרות בספרייה/במודול תכונה או מסופקות על ידי צד שלישי, יכול להיות שתצטרכו לציין במפורש את הנתיב לספריות ללא הסרת קוד מיותר. כדי לעשות זאת, אפשר להוסיף את המאפיין unstrippedNativeLibsDir בתוסף של Crashlytics בקובץ ה-build של Gradle.

  1. חשוב לוודא שהשלמתם את המשימות הראשוניות הבאות מתהליך העבודה הראשי שמתואר למעלה בדף:

    1. הפעלת Crashlytics במסוף Firebase.

    2. הוספנו את Crashlytics SDK ל-NDK ואת הפלאגין Crashlytics ל-Gradle.

    3. הוספת התוסף של Crashlytics לגרסה היציבה.

    4. הגדרת העלאה אוטומטית של סמלים מקוריים

  2. כדי שהמשימה האוטומטית להעלאת סמלים תוכל למצוא את פרטי הסמל, צריך להוסיף את הקוד הבא לקובץ Gradle של המודול (ברמת האפליקציה) (בדרך כלל <project>/<app-module>/build.gradle.kts או <project>/<app-module>/build.gradle):

    KotlinGroovy
    import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension
    
    // ...
    
    android {
        // ...
        buildTypes {
            release {
                configure<CrashlyticsExtension> {
                    nativeSymbolUploadEnabled = true
                    unstrippedNativeLibsDir = file("PATH/TO/UNSTRIPPED/DIRECTORY")
                }
            }
        }
    }
    // ...
    
    android {
        // ...
        buildTypes {
            release {
                firebaseCrashlytics {
                    nativeSymbolUploadEnabled true
                    unstrippedNativeLibsDir file("PATH/TO/UNSTRIPPED/DIRECTORY")
                }
            }
        }
    }

    הפלאגין Crashlytics יחפש באופן רקורסיבי בספרייה שצוינה ספריות מקומיות עם סיומת .so. לאחר מכן, Crashlytics מחלץ סמלי ניפוי באגים מכל הספריות האלה ומעלה אותם לשרתים של Firebase.

    אלה הערכים שאפשר לציין במאפיין unstrippedNativeLibsDir:

    • כל ארגומנט שמותר להשתמש בו ב-org.gradle.api.Project#files(Object...), כולל: java.lang.String,‏ java.io.File או org.gradle.api.file.FileCollection

    • כמה ספריות לאותו סוג build, על ידי הצגת רשימה או מופע של FileCollection

    • (החל מ-Crashlytics Gradle plugin v3.0.0) צבירת מספר ספריות במוצרים נפרדים וגרסאות build.

      buildTypes {
        release {
          configure<CrashlyticsExtension> {
            nativeSymbolUploadEnabled = true
            unstrippedNativeLibsDir = file("MY/NATIVE/LIBS")
          }
        }
        productFlavors {
          flavorDimensions += "feature"
          create("basic") {
            dimension = "feature"
            // ...
          }
          create("featureX") {
            dimension = "feature"
            configure<CrashlyticsExtension> {
              unstrippedNativeLibsDir = file("MY/FEATURE_X/LIBS")
            }
          }
        }
      }
      

    המשימה uploadCrashlyticsSymbolFilesBasicRelease תעלה רק את הסמלים ב-MY/NATIVE/LIBS, אבל המשימה uploadCrashlyticsSymbolFilesFeatureXRelease תעלה סמלים גם ב-MY/NATIVE/LIBS וגם ב-MY/FEATURE_X/LIBS.

  3. לבסוף, גורמים לקריסה לצורך בדיקה כדי לסיים את ההגדרה של Crashlytics ולראות את הנתונים הראשוניים במרכז הבקרה של Crashlytics במסוף Firebase.

אפשרות: העלאת סמלים לגרסאות build שאינן של Gradle או לספריות מקוריות לא שהוסר מהן הקוד הלא נדרש ולא ניתן לגשת אליהן

האפשרות הזו יכולה להיות שימושית במקרים הבאים:

  • אם אתם משתמשים בתהליך build שאינו Gradle

  • אם הספריות המקומיות ללא הסרת קוד מיותר ניתנות לכם באופן כלשהו כך שלא תוכלו לגשת אליהן במהלך ה-builds של Gradle

כדי להשתמש באפשרות הזו, צריך להריץ פקודה ב-CLI של Firebase כשיוצרים build למהדורה או build כלשהו שרוצים לראות בו מעקב סמלי של סטאק במסוף Firebase.

  1. חשוב לוודא שהשלמתם את המשימות הראשוניות הבאות מתהליך העבודה הראשי שמתואר למעלה בדף:

    1. הפעלת Crashlytics במסוף Firebase.

    2. הוספנו את Crashlytics SDK ל-NDK ואת הפלאגין Crashlytics ל-Gradle.

    חשוב לזכור שבאפשרות הזו אין צורך להוסיף את התוסף firebaseCrashlytics או להגדיר העלאה אוטומטית של סמלים, כי במקום זאת תשתמשו ב-CLI של Firebase (השלבים הבאים בהמשך) כדי ליצור ולהעלות את קובצי הסמלים.

  2. מגדירים את הסביבה והפרויקט להעלאת סמלים:

    1. פועלים לפי ההוראות להתקנת ה-CLI של Firebase.

      אם כבר התקנתם את ה-CLI, חשוב לעדכן אותו לגרסה האחרונה.

    2. (רק לאפליקציות שמשתמשות ב-Android API ברמה 30 ואילך) מעדכנים את התבנית AndroidManifest.xml של האפליקציה כדי להשבית את התיוג של סמן העכבר:

      1. מסמנים את התיבה הגדרות נגן Android > הגדרות פרסום > build > מניפסט ראשי מותאם אישית.

      2. פותחים את תבנית המניפסט שנמצאת ב-Assets/Plugins/Android/AndroidManifest.xml.

      3. מוסיפים את המאפיין הבא לתג האפליקציה: <application android:allowNativeHeapPointerTagging="false" ... />

  3. מריצים את ה-build של הפרויקט.

  4. מעלים את פרטי הסמלים.

    בסיום ה-build, יוצרים קובץ סמלים תואם ל-Crashlytics ומעלים אותו לשרתים של Firebase באמצעות הפקודה הבאה ב-CLI של Firebase:

    firebase crashlytics:symbols:upload --app=FIREBASE_APP_ID PATH/TO/SYMBOLS
    • FIREBASE_APP_ID: מזהה האפליקציה שלכם ב-Firebase ל-Android (לא שם החבילה)
      דוגמה למזהה האפליקציה שלכם ב-Firebase ל-Android: 1:567383003300:android:17104a2ced0c9b9b

      יש שתי דרכים למצוא את מזהה האפליקציה ב-Firebase:

      • בקובץ google-services.json, מזהה האפליקציה הוא הערך mobilesdk_app_id.

      • במסוף Firebase, עוברים אל Project settings. גוללים למטה אל הכרטיס האפליקציות שלך ולוחצים על אפליקציית Firebase הרצויה כדי למצוא את מזהה האפליקציה שלה.

    • PATH/TO/SYMBOLS: הנתיב לקובץ הסמלים שנוצר על ידי ה-CLI

      • ייצוא לפרויקט ב-Android Studio – PATH/TO/SYMBOLS יכולה להיות כל ספרייה. ה-CLI של Firebase יחפש באופן רקורסיבי בספרייה שצוינה ספריות מקוריות עם סיומת .so.

      • פיתחתם את קובץ ה-APK ישירות מתוך Unity – PATH/TO/SYMBOLS הוא הנתיב של קובץ הסמל המוצפן שנוצר בספריית השורש של הפרויקט בסיום ה-build (לדוגמה: myproject/myapp-1.0-v100.symbols.zip).

    דגל תיאור
    --generator=csym

    שימוש במחולל קובצי הסמלים הקודם של cSYM במקום במחולל ברירת המחדל של Breakpad

    לא מומלץ לשימוש. מומלץ להשתמש בברירת המחדל של ה-generator של קובצי הסימנים של Breakpad.

    --generator=breakpad

    שימוש במחולל קובצי הסמלים של Breakpad

    הערה: ברירת המחדל ליצירת קובצי סמלים היא Breakpad. צריך להשתמש בדגל הזה רק אם הוספתם את symbolGenerator { csym() } להגדרות ה-build ואתם רוצים לשנות את ההגדרה הזו ולהשתמש ב-Breakpad במקום זאת.

    --dry-run

    יצירת קובצי הסמלים, אבל לא העלאה שלהם

    הדגל הזה שימושי אם רוצים לבדוק את התוכן של הקובצים שנשלחים.

    --debug מידע נוסף על ניפוי באגים
  5. לבסוף, גורמים לקריסה לצורך בדיקה כדי לסיים את ההגדרה של Crashlytics ולראות את הנתונים הראשוניים במרכז הבקרה של Crashlytics במסוף Firebase.

    אחרי יצירת ה-build של האפליקציה כחלק מהפעלת קריסה, חשוב להריץ את הפקודה crashlytics:symbols:upload ב-CLI של Firebase כדי להעלות את קובץ הסמל.