1. مقدمة
في هذا الدرس العملي، ستتعرّف على كيفية استخدام الميزات المتقدّمة في Crashlytics التي ستمنحك إمكانية أفضل للاطّلاع على الأعطال والظروف التي ربما تسبّبت فيها.
ستضيف وظائف جديدة إلى لعبة نموذجية، وهي MechaHamster: Level Up with Firebase Edition. هذه اللعبة النموذجية هي إصدار جديد من لعبة MechaHamster الكلاسيكية على Firebase، وهي تزيل معظم وظائف Firebase المضمّنة، ما يمنحك الفرصة لتنفيذ استخدامات جديدة لـ Firebase بدلاً منها.
ستضيف قائمة تصحيح الأخطاء إلى اللعبة. تستدعي قائمة تصحيح الأخطاء هذه الطرق التي ستنشئها وتتيح لك استخدام الوظائف المختلفة في Crashlytics. ستوضّح لك هذه الطرق كيفية إضافة تعليقات توضيحية إلى تقارير الأعطال التلقائية باستخدام مفاتيح مخصّصة وسجلات مخصّصة وأخطاء غير قاتلة وغير ذلك.
بعد إنشاء اللعبة، ستستخدم قائمة تصحيح الأخطاء، وتفحص النتائج لفهم طريقة عرضها الفريدة لطريقة تشغيل لعبتك في بيئة الإنتاج.
أهداف الدورة التعليمية
- أنواع الأخطاء التي يرصدها Crashlytics تلقائيًا
- أخطاء إضافية يمكن تسجيلها عمدًا
- كيفية إضافة المزيد من المعلومات إلى هذه الأخطاء لتسهيل فهمها
المتطلبات
- Unity (الحدّ الأدنى للإصدار المقترَح هو 2019 أو إصدار أحدث) مع أحد الخيارَين التاليَين أو كليهما:
- توافُق إصدار iOS
- توافُق إصدار Android
- (لنظام التشغيل Android فقط) أداة سطر الأوامر (CLI) من Firebase (تُستخدم لتحميل الرموز لتقارير الأعطال)
- اتّبِع التعليمات لتثبيت واجهة سطر الأوامر (CLI) في Firebase.
إذا سبق لك تثبيت واجهة سطر الأوامر، احرص على تحديثها إلى أحدث إصدار.
- اتّبِع التعليمات لتثبيت واجهة سطر الأوامر (CLI) في Firebase.
2. إعداد بيئة التطوير
توضّح الأقسام التالية كيفية تنزيل رمز Level Up with Firebase وفتحه في Unity.
يُرجى العِلم أنّ لعبة Level Up with Firebase النموذجية هذه مستخدَمة في العديد من برامج الترميز الأخرى من Firebase وUnity، لذا قد تكون أكملت المهام في هذا القسم من قبل. إذا كان الأمر كذلك، يمكنك الانتقال مباشرةً إلى الخطوة الأخيرة في هذه الصفحة: "إضافة حِزم تطوير البرامج (SDK) لمنصة Firebase إلى Unity".
تنزيل الرمز
استنسِخ مستودع GitHub الخاص بهذا الدرس العملي من سطر الأوامر:
git clone https://github.com/firebase/level-up-with-firebase.git
بدلاً من ذلك، إذا لم يكن git مثبّتًا لديك، يمكنك تنزيل المستودع كملف ZIP.
افتح Level Up with Firebase في محرِّر Unity
- شغِّل Unity Hub، ثم انقر على سهم القائمة المنسدلة بجانب فتح من علامة التبويب المشاريع.
- انقر على إضافة مشروع من القرص.
- انتقِل إلى الدليل الذي يحتوي على الرمز، ثم انقر على حسنًا.
- إذا طُلب منك ذلك، اختَر إصدارًا من "محرّر Unity" لاستخدامه والنظام الأساسي المستهدف (Android أو iOS).
- انقر على اسم المشروع، level-up-with-firebase، وسيتم فتح المشروع في "محرّر Unity".
- إذا لم يفتح المحرّر تلقائيًا، افتح
MainGameScene
في الأصول (Assets) > Hamster في علامة التبويب المشروع (Project) في Unity Editor.
لمزيد من المعلومات حول تثبيت Unity واستخدامه، يُرجى الاطّلاع على العمل في Unity.
3- إضافة Firebase إلى مشروع Unity
إنشاء مشروع Firebase
- سجِّل الدخول إلى وحدة تحكّم Firebase باستخدام حسابك على Google.
- انقر على الزر لإنشاء مشروع جديد، ثم أدخِل اسم المشروع (على سبيل المثال،
Mechahamster Codelab
).
- انقر على متابعة.
- إذا طُلب منك ذلك، راجِع بنود Firebase واقبلها، ثم انقر على متابعة.
- (اختياري) فعِّل ميزة "المساعدة المستندة إلى الذكاء الاصطناعي" في وحدة تحكّم Firebase (المعروفة باسم "Gemini في Firebase").
- في هذا الدرس العملي، تحتاج إلى "إحصاءات Google" لاستخدام منتجات Firebase على النحو الأمثل، لذا أبقِ زر التبديل مفعّلاً لخيار "إحصاءات Google". اتّبِع التعليمات الظاهرة على الشاشة لإعداد "إحصاءات Google".
- انقر على إنشاء مشروع، وانتظِر إلى أن يتم توفير مشروعك، ثم انقر على متابعة.
تسجيل تطبيقك في Firebase
- في وحدة تحكّم Firebase، انقر على رمز Unity من وسط صفحة نظرة عامة على المشروع لتشغيل سير عمل الإعداد، أو انقر على إضافة تطبيق لعرض خيارات المنصّة إذا سبق لك إضافة تطبيق إلى مشروعك على Firebase.
- اختَر تسجيل كلّ من أهداف إنشاء Apple (iOS) وAndroid.
- أدخِل أرقام التعريف الخاصة بمنصّة مشروع Unity. بالنسبة إلى هذا الدرس التطبيقي حول الترميز، أدخِل ما يلي:
- بالنسبة إلى Apple (iOS): أدخِل
com.google.firebase.level-up
في حقل معرّف حزمة iOS. - في نظام التشغيل Android: أدخِل
com.google.firebase.level_up
في حقل اسم حزمة Android.
- بالنسبة إلى Apple (iOS): أدخِل
- (اختياري) أدخِل الأسماء المستعارة الخاصة بالنظام الأساسي لمشروع Unity.
- انقر على تسجيل التطبيق، ثم انتقِل إلى قسم تنزيل ملف الإعداد.
إضافة ملفات إعداد Firebase
بعد النقر على تسجيل التطبيق، سيُطلب منك تنزيل ملفَّي إعداد (ملف إعداد واحد لكل هدف إنشاء). يحتاج مشروع Unity إلى بيانات Firebase الوصفية في هذه الملفات للربط بخدمة Firebase.
- نزِّل ملفَي الإعداد المتاحَين:
- بالنسبة إلى Apple (iOS): نزِّل الملف GoogleService-Info.plist.
- على Android: نزِّل ملف google-services.json.
- افتح نافذة المشروع في مشروع Unity، ثم انقل ملفَي الإعداد إلى مجلد الأصول.
- ارجع إلى وحدة تحكّم Firebase، وفي سير عمل الإعداد، انقر على التالي وانتقِل إلى إضافة حِزم تطوير البرامج (SDK) لمنصّة Firebase إلى Unity.
إضافة حِزم Firebase SDK لـ Unity
- انقر على تنزيل حزمة تطوير البرامج (SDK) لمنصة Firebase Unity في وحدة تحكّم Firebase.
- فكّ ضغط حزمة تطوير البرامج (SDK) في مكان مناسب.
- في مشروع Unity المفتوح، انتقِل إلى الأصول (Assets) > استيراد حزمة (Import Package) > حزمة مخصّصة (Custom Package).
- في مربّع الحوار استيراد حزمة، انتقِل إلى الدليل الذي يحتوي على حزمة تطوير البرامج (SDK) التي تم فك ضغطها، واختَر
FirebaseAnalytics.unitypackage
، ثم انقر على فتح. - من مربّع الحوار استيراد حزمة Unity الذي يظهر، انقر على استيراد.
- كرِّر الخطوات السابقة لاستيراد
FirebaseCrashlytics.unitypackage
. - ارجع إلى "وحدة تحكّم Firebase"، وانقر على التالي في سير عمل الإعداد.
لمزيد من المعلومات عن إضافة حِزم تطوير البرامج (SDK) من Firebase إلى مشاريع Unity، اطّلِع على خيارات تثبيت Unity الإضافية.
4. إعداد Crashlytics في مشروع Unity
لاستخدام Crashlytics في مشاريع Unity، عليك تنفيذ بعض خطوات الإعداد الإضافية. بالطبع، عليك إعداد حزمة تطوير البرامج (SDK). عليك أيضًا تحميل الرموز حتى تتمكّن من الاطّلاع على عمليات تتبُّع تسلسل استدعاء الدوال البرمجية التي تم ترميزها في وحدة تحكّم Firebase، كما عليك فرض حدوث عُطل تجريبي للتأكّد من أنّ Firebase يتلقّى أحداث الأعطال.
إعداد حزمة تطوير البرامج (SDK) الخاصة بخدمة Crashlytics
- في
Assets/Hamster/Scripts/MainGame.cs
، أضِف عباراتusing
التالية: تتيح لك الوحدة الأولى استخدام طرق من حزمة تطوير البرامج (SDK) الخاصة بـ Crashlytics، وتحتوي الوحدة الثانية على بعض الإضافات إلى C# Tasks API. بدون عبارتَي bothusing Firebase.Crashlytics; using Firebase.Extensions;
using
، لن يعمل الرمز التالي. - في ملف
MainGame.cs
، أضِف عملية إعداد Firebase إلى طريقةStart()
الحالية من خلال استدعاءInitializeFirebaseAndStartGame()
:void Start() { Screen.SetResolution(Screen.width / 2, Screen.height / 2, true); InitializeFirebaseAndStartGame(); }
- مرة أخرى، في
MainGame.cs
، ابحث عنInitializeFirebaseAndStartGame()
، وأدخِل متغيّرًا للتطبيق، ثمّ استبدِل تنفيذ الطريقة على النحو التالي:public Firebase.FirebaseApp app = null; // Begins the firebase initialization process and afterwards, opens the main menu. private void InitializeFirebaseAndStartGame() { Firebase.FirebaseApp.CheckAndFixDependenciesAsync() .ContinueWithOnMainThread( previousTask => { var dependencyStatus = previousTask.Result; if (dependencyStatus == Firebase.DependencyStatus.Available) { // Create and hold a reference to your FirebaseApp, app = Firebase.FirebaseApp.DefaultInstance; // Set the recommended Crashlytics uncaught exception behavior. Crashlytics.ReportUncaughtExceptionsAsFatal = true; InitializeCommonDataAndStartGame(); } else { UnityEngine.Debug.LogError( $"Could not resolve all Firebase dependencies: {dependencyStatus}\n" + "Firebase Unity SDK is not safe to use here"); } }); }
يمنع وضع منطق الإعداد هنا تفاعل المشغّل قبل إعداد التبعيات في Firebase.
يمكنك الاطّلاع على مزيد من المعلومات حول فوائد وآثار الإبلاغ عن الاستثناءات غير المعالَجة على أنّها فادحة في الأسئلة الشائعة حول Crashlytics.
إنشاء مشروعك وتحميل الرموز
تختلف خطوات إنشاء الرموز وتحميلها في تطبيقات iOS عن تطبيقات Android.
iOS+ (منصة Apple)
- من مربّع الحوار إعدادات الإنشاء، يمكنك تصدير مشروعك إلى مساحة عمل Xcode.
- أنشئ تطبيقك.
بالنسبة إلى منصات Apple، يضبط مكوّن Firebase Unity Editor الإضافي مشروع Xcode تلقائيًا لإنشاء ملف رموز متوافق مع Crashlytics وتحميله إلى خوادم Firebase لكل إصدار. يجب توفُّر معلومات الرموز هذه للاطّلاع على عمليات تتبُّع تسلسل استدعاء الدوال البرمجية التي تم تحويلها إلى رموز في لوحة بيانات Crashlytics.
Android
- (أثناء عملية الإعداد الأوّلية فقط، وليس لكل إصدار) يمكنك إعداد الإصدار باتّباع الخطوات التالية:
- أنشئ مجلدًا جديدًا باسم Builds في جذر دليل مشروعك (أي كمجلد فرعي لمجلد Assets)، ثم أنشئ مجلدًا فرعيًا باسم Android.
- في ملف (File) > إعدادات الإنشاء (Build Settings) > إعدادات المشغّل (Player Settings) > الإعدادات (Configuration)، اضبط Scripting Backend على IL2CPP.
- يؤدي IL2CPP بشكل عام إلى تصغير حجم الإصدارات وتحسين أدائها.
- إنّ IL2CPP هو الخيار الوحيد المتاح على iOS، ويسمح تحديده هنا بتحقيق توافق أفضل بين النظامين الأساسيين وتسهيل تصحيح الأخطاء بينهما (إذا اخترت إنشاء كليهما).
- أنشئ تطبيقك. في ملف (File) > إعدادات الإنشاء (Build Settings)، أكمل ما يلي:
- تأكَّد من وضع علامة في المربّع بجانب Create symbols.zip (أو اختَر تصحيح الأخطاء إذا ظهرت لك قائمة منسدلة).
- أنشئ ملف APK مباشرةً من Unity Editor في المجلد الفرعي Builds/Android الذي أنشأته للتو.
- بعد انتهاء عملية الإنشاء، عليك إنشاء ملف رموز متوافق مع Crashlytics وتحميله إلى خوادم Firebase. يجب توفير معلومات الرموز هذه للاطّلاع على عمليات تتبُّع تسلسل استدعاء الدوال البرمجية التي تم ترميزها لأعطال المكتبة الأصلية في لوحة بيانات Crashlytics.
أنشئ ملف الرموز هذا وحمِّله من خلال تنفيذ أمر Firebase CLI التالي:firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
- استبدِل
FIREBASE_APP_ID
بمعرّف تطبيق Firebase على Android (وليس اسم الحزمة). ابحث عن هذه القيمة في ملفgoogle-services.json
الذي نزّلته سابقًا. وهي قيمةmobilesdk_app_id
.
مثال على رقم تعريف تطبيق Android على Firebase:1:567383003300:android:17104a2ced0c9b9b
PATH/TO/SYMBOLS
: مسار ملف الرموز المضغوط الذي تم إنشاؤه في الدليل Builds/Android عند انتهاء عملية الإنشاء (على سبيل المثال:Builds/Android/myapp-1.0-v100.symbols.zip
).
- استبدِل
فرض حدوث عُطل تجريبي لإكمال عملية الإعداد
لإنهاء إعداد Crashlytics والاطّلاع على البيانات الأولية في لوحة بيانات Crashlytics في وحدة تحكُّم Firebase، عليك فرض حدوث عُطل تجريبي.
- في MainGameScene، ابحث عن EmptyObject
GameObject
في Hierarchy ضمن المحرّر، وأضِف النص البرمجي التالي إليه ثم احفظ المشهد. سيؤدي هذا النص البرمجي إلى حدوث عُطل تجريبي بعد بضع ثوانٍ من تشغيل تطبيقك.using System; using UnityEngine; public class CrashlyticsTester : MonoBehaviour { // Update is called once per frame void Update() { // Tests your Crashlytics implementation by // throwing an exception every 60 frames. // You should see reports in the Firebase console // a few minutes after running your app with this method. if(Time.frameCount >0 && (Time.frameCount%60) == 0) { throw new System.Exception("Test exception; please ignore"); } } }
- أنشئ تطبيقك وحمِّل معلومات الرموز بعد انتهاء عملية الإنشاء.
- نظام التشغيل iOS: يضبط تلقائيًا مكوّن Firebase Unity Editor الإضافي مشروع Xcode لتحميل ملف الرموز.
- Android: شغِّل الأمر
crashlytics:symbols:upload
في واجهة سطر الأوامر (CLI) لمنصة Firebase لتحميل ملف الرموز.
- شغِّل تطبيقك. بعد تشغيله، راقِب سجلّ الجهاز وانتظِر حتى يتم تشغيل الاستثناء من
CrashlyticsTester
.- iOS: يمكنك الاطّلاع على السجلّات في اللوحة السفلية من Xcode.
- Android: يمكنك عرض السجلات من خلال تنفيذ الأمر التالي في نافذة الأوامر:
adb logcat
.
- انتقِل إلى لوحة بيانات Crashlytics لعرض الاستثناء. يمكنك الاطّلاع عليه في جدول المشاكل في أسفل لوحة البيانات. في وقت لاحق من الدرس التطبيقي حول الترميز، ستتعرّف على مزيد من المعلومات حول كيفية استكشاف هذه التقارير.
- بعد التأكّد من تحميل الحدث إلى Crashlytics، اختَر EmptyObject
GameObject
الذي أرفقته به، وأزِل مكوّنCrashlyticsTester
فقط، ثم احفظ المشهد لاستعادته إلى حالته الأصلية.
5- تفعيل "قائمة تصحيح الأخطاء" وفهمها
حتى الآن، أضفت Crashlytics إلى مشروع Unity وأكملت عملية الإعداد وتأكّدت من أنّ حزمة تطوير البرامج (SDK) لـ Crashlytics تحمّل الأحداث إلى Firebase. ستنشئ الآن قائمة في مشروع Unity توضّح كيفية استخدام وظائف Crashlytics الأكثر تقدّمًا في لعبتك. يتضمّن مشروع Unity Level Up with Firebase قائمة تصحيح أخطاء مخفية ستجعلها مرئية وتكتب وظائفها.
تفعيل "قائمة تصحيح الأخطاء"
يتوفّر الزرّ للوصول إلى "قائمة تصحيح الأخطاء" في مشروع Unity، ولكنّه غير مفعّل حاليًا. يجب تفعيل الزر للوصول إليه من العنصر الجاهز MainMenu
:
- في Unity Editor، افتح العنصر الجاهز للاستخدام باسم
MainMenu
. - في بنية العنصر الجاهز، ابحث عن العنصر الفرعي غير المفعّل الذي يحمل الاسم
DebugMenuButton
، ثم اختَره. - فعِّل
DebugMenuButton
من خلال وضع علامة في المربّع في أعلى يمين الصفحة إلى يسار حقل النص الذي يحتوي علىDebugMenuButton
. - احفظ العنصر الجاهز.
- شغِّل اللعبة في المحرّر أو على جهازك. من المفترض أن تتمكّن من الوصول إلى القائمة الآن.
معاينة وفهم نصوص الطرق في "قائمة تصحيح الأخطاء"
في وقت لاحق من هذا الدرس العملي، ستكتب نصوصًا برمجية لبعض طرق تصحيح الأخطاء في Crashlytics التي تم ضبطها مسبقًا. في مشروع Unity تطوير المهارات باستخدام Firebase، يتم تحديد الطرق واستدعاؤها من DebugMenu.cs
.
على الرغم من أنّ بعض هذه الطرق ستستدعي طرق Crashlytics وتُظهر أخطاءً، فإنّ قدرة Crashlytics على رصد هذه الأخطاء لا تعتمد على استدعاء هذه الطرق أولاً. بدلاً من ذلك، سيتم تحسين تقارير الأعطال التي يتم إنشاؤها من خلال رصد الأخطاء تلقائيًا باستخدام المعلومات التي تتم إضافتها بهذه الطرق.
افتح DebugMenu.cs
، ثم ابحث عن الطرق التالية:
طُرق إنشاء مشاكل Crashlytics وإضافة تعليقات توضيحية إليها:
CrashNow
LogNonfatalError
LogStringsAndCrashNow
SetAndOverwriteCustomKeyThenCrash
SetLogsAndKeysBeforeANR
طُرق تسجيل أحداث "إحصاءات Google" للمساعدة في تصحيح الأخطاء:
LogProgressEventWithStringLiterals
LogIntScoreWithBuiltInEventAndParams
في الخطوات اللاحقة من هذا الدرس التطبيقي حول الترميز، ستنفّذ هذه الطرق وتتعرّف على كيفية مساعدتها في معالجة مواقف معيّنة يمكن أن تحدث أثناء تطوير الألعاب.
6. ضمان تسليم تقارير الأعطال أثناء التطوير
قبل البدء في تنفيذ طرق تصحيح الأخطاء هذه والاطّلاع على كيفية تأثيرها في تقارير الأعطال، تأكَّد من فهم كيفية إرسال الأحداث إلى Crashlytics.
بالنسبة إلى مشاريع Unity، يتم على الفور كتابة أحداث الأعطال والاستثناءات في لعبتك على القرص. بالنسبة إلى الاستثناءات غير المعالَجة التي لا تؤدي إلى تعطُّل لعبتك (على سبيل المثال، استثناءات C# غير المعالَجة في منطق اللعبة)، يمكنك أن تطلب من حزمة تطوير البرامج (SDK) في Crashlytics إعداد تقارير عنها كأحداث قاتلة من خلال ضبط السمة Crashlytics.ReportUncaughtExceptionsAsFatal
على true
في المكان الذي تُهيّئ فيه Crashlytics في مشروع Unity. يتم إرسال هذه الأحداث إلى Crashlytics في الوقت الفعلي بدون الحاجة إلى أن يعيد المستخدم النهائي تشغيل اللعبة. يُرجى العِلم أنّه يتم دائمًا تسجيل الأعطال الأصلية كأحداث خطيرة وإرسالها عند إعادة تشغيل المستخدم النهائي للعبة.
بالإضافة إلى ذلك، يجب الانتباه إلى الاختلافات الصغيرة، ولكن المهمة، التالية بين الطريقة التي ترسل بها بيئات وقت التشغيل المختلفة معلومات Crashlytics إلى Firebase:
محاكي iOS:
- يتم إعداد تقارير عن معلومات Crashlytics في حال فصل Xcode عن المحاكي فقط. في حال ربط Xcode، سيتم رصد الأخطاء في المصدر، ما يمنع تسليم المعلومات.
الأجهزة الجوّالة المادية (Android وiOS):
- خاص بنظام Android: لا يتم الإبلاغ عن أخطاء ANR إلا على الإصدار 11 من نظام التشغيل Android أو الإصدارات الأحدث. ويتم الإبلاغ عن أخطاء ANR والأحداث غير الفادحة عند التشغيل التالي.
Unity Editor:
- لا يتم تسجيل معلومات Crashlytics أو تحميلها إلى Firebase من المحرّر في وضع التشغيل أو في وضع التطبيق المستقل. بالإضافة إلى ذلك، لا يتيح سير عمل تطوير تطبيقات سطح المكتب في Firebase استخدام Crashlytics.
اختبار تعطُّل لعبتك بضغطة زر في CrashNow()
بعد إعداد Crashlytics في لعبتك، تسجِّل حزمة تطوير البرامج (SDK) في Crashlytics تلقائيًا الأعطال والاستثناءات غير المعالَجة وتحمّلها إلى Firebase لتحليلها. ويتم عرض التقارير في لوحة بيانات Crashlytics في وحدة تحكّم Firebase.
- لإثبات أنّ هذا الإجراء تلقائي بالفعل، افتح
DebugMenu.cs
، ثمّ استبدِل الطريقةCrashNow()
على النحو التالي:void CrashNow() { TestCrash(); }
- أنشئ تطبيقك.
- (على أجهزة Android فقط) حمِّل الرموز عن طريق تنفيذ أمر Firebase CLI التالي:
firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
- انقر على الزر تعطُّل التطبيق الآن، ثم انتقِل إلى الخطوة التالية من هذا الدرس العملي لمعرفة كيفية عرض تقرير الأعطال وتفسيره.
7. التعرّف على تقارير المشاكل في وحدة تحكّم Firebase
عند الاطّلاع على تقارير الأعطال، هناك بعض المعلومات الإضافية التي يجب معرفتها للاستفادة منها إلى أقصى حد. ستوضّح كل طريقة تكتبها كيفية إضافة أنواع مختلفة من المعلومات إلى تقارير Crashlytics.
- انقر على الزر تعطُّل الآن، ثم أعِد تشغيل تطبيقك.
- انتقِل إلى لوحة بيانات Crashlytics. انتقِل إلى أسفل لوحة البيانات إلى جدول المشاكل حيث يجمع Crashlytics الأحداث التي لها السبب الجذري نفسه في "مشاكل".
- انقر على المشكلة الجديدة المُدرَجة في جدول المشاكل. سيؤدي ذلك إلى عرض ملخّص الأحداث حول كل حدث فردي تم إرساله إلى Firebase.
يجب أن يظهر لك شيء مشابه للقطة الشاشة التالية. لاحظ كيف يعرض ملخّص الحدث بشكل بارز تتبُّع تسلسل استدعاء الدوال البرمجية للمكالمة التي أدّت إلى تعطُّل التطبيق.
البيانات الوصفية الإضافية
علامة التبويب المفيدة الأخرى هي علامة التبويب بيانات Unity الوصفية. يقدّم لك هذا القسم معلومات عن سمات الجهاز الذي وقع عليه الحدث، بما في ذلك الميزات المادية وطراز وحدة المعالجة المركزية (CPU) ومواصفاتها وجميع أنواع مقاييس وحدة معالجة الرسومات (GPU).
في ما يلي مثال على الحالات التي قد تكون فيها المعلومات الواردة في علامة التبويب هذه مفيدة:
لنفترض أنّ لعبتك تستخدم الكثير من برامج التظليل لتحقيق مظهر معيّن، ولكن لا تحتوي جميع الهواتف على وحدات معالجة الرسومات (GPU) التي يمكنها عرض هذه الميزة. يمكن أن تمنحك المعلومات الواردة في علامة التبويب بيانات Unity الوصفية فكرة أفضل عن الأجهزة التي يجب أن يختبرها تطبيقك عند تحديد الميزات التي يجب إتاحتها تلقائيًا أو إيقافها تمامًا.
على الرغم من أنّه قد لا يحدث خطأ أو عُطل على جهازك، فإنّ التنوّع الكبير في أجهزة Android المتاحة يساعد في فهم "نقاط الضعف" المحدّدة في أجهزة جمهورك بشكل أفضل.
8. طرح استثناء ورصده وتسجيله
في كثير من الأحيان، بصفتك مطوّرًا، حتى إذا كان الرمز البرمجي الخاص بك يرصد استثناء وقت التشغيل ويتعامل معه بشكل صحيح، من المفيد تدوين حدوثه والظروف التي حدث فيها. يمكن استخدام Crashlytics.LogException
لهذا الغرض تحديدًا، أي لإرسال حدث استثناء إلى Firebase حتى تتمكّن من تصحيح الخطأ بشكلٍ أكبر في وحدة تحكّم Firebase.
- في
Assets/Hamster/Scripts/States/DebugMenu.cs
، أضِف ما يلي إلى عباراتusing
:// Import Firebase using Firebase.Crashlytics;
- في
DebugMenu.cs
، استبدِلLogNonfatalError()
بما يلي:void LogNonfatalError() { try { throw new System.Exception($"Test exception thrown in {nameof(LogNonfatalError)}"); } catch(System.Exception exception) { Crashlytics.LogException(exception); } }
- أنشئ تطبيقك.
- (على أجهزة Android فقط) حمِّل الرموز عن طريق تنفيذ أمر Firebase CLI التالي:
firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
- انقر على الزر تسجيل خطأ غير فادح، ثم أعِد تشغيل تطبيقك.
- انتقِل إلى لوحة بيانات Crashlytics، وسيظهر لك شيء مشابه لما رأيته في الخطوة الأخيرة من هذا الدرس البرمجي.
- في هذه المرة، احصر فلتر نوع الحدث على الأخطاء غير الفادحة حتى لا تظهر لك سوى الأخطاء غير الفادحة، مثل الخطأ الذي سجّلته للتو.
9. تسجيل سلاسل السجلّ في Crashlytics لفهم سير تنفيذ البرنامج بشكل أفضل
هل حاولت يومًا معرفة سبب ظهور استثناء أو حدوث عطل فجائي في سطر من الرمز البرمجي يتم استدعاؤه من مسارات متعددة، مئات المرات إن لم يكن آلاف المرات في كل جلسة؟ مع أنّ التنقّل بين أسطر الرمز في بيئة تطوير متكاملة (IDE) وإلقاء نظرة فاحصة على القيم قد يكون أمرًا جيدًا، ماذا لو حدث ذلك لنسبة صغيرة جدًا من المستخدمين؟ والأسوأ من ذلك، ماذا ستفعل إذا لم تتمكّن من تكرار هذا التعطُّل مهما فعلت؟
في حالات كهذه، يمكن أن يُحدث توفّر بعض السياق فرقًا كبيرًا. باستخدام Crashlytics.Log
، يمكنك كتابة السياق الذي تحتاجه. يمكنك اعتبار هذه الرسائل تلميحات إلى نفسك في المستقبل حول ما قد يحدث.
على الرغم من إمكانية استخدام السجلات بطرق عديدة، إلا أنّها تكون عادةً أكثر فائدة لتسجيل الحالات التي يكون فيها ترتيب المكالمات و/أو عدم إجرائها جزءًا مهمًا للغاية من المعلومات.
- في
Assets/Hamster/Scripts/States/DebugMenu.cs
، استبدِلLogStringsAndCrashNow()
بما يلي:void LogStringsAndCrashNow() { Crashlytics.Log($"This is the first of two descriptive strings in {nameof(LogStringsAndCrashNow)}"); const bool RUN_OPTIONAL_PATH = false; if(RUN_OPTIONAL_PATH) { Crashlytics.Log(" As it stands, this log should not appear in your records because it will never be called."); } else { Crashlytics.Log(" A log that will simply inform you which path of logic was taken. Akin to print debugging."); } Crashlytics.Log($"This is the second of two descriptive strings in {nameof(LogStringsAndCrashNow)}"); TestCrash(); }
- أنشئ تطبيقك.
- (على أجهزة Android فقط) حمِّل الرموز عن طريق تنفيذ أمر Firebase CLI التالي:
firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
- انقر على الزر سلاسل السجلّ والتعطُّل الآن، ثم أعِد تشغيل تطبيقك.
- ارجع إلى لوحة بيانات Crashlytics، وانقر على أحدث مشكلة مُدرَجة في جدول المشاكل. مرة أخرى، من المفترض أن تظهر لك مشكلة مشابهة للمشاكل السابقة.
- ومع ذلك، إذا نقرت على علامة التبويب السجلات ضمن ملخّص حدث، سيظهر لك عرض على النحو التالي:
10. كتابة مفتاح مخصّص واستبداله
لنفترض أنّك تريد فهم عُطل يتوافق مع متغيرات تم ضبطها على عدد صغير من القيم أو الإعدادات. قد يكون من المفيد أن تتمكّن من الفلترة استنادًا إلى مجموعة المتغيّرات والقيم المحتملة التي تبحث عنها في أي وقت.
بالإضافة إلى تسجيل السلاسل العشوائية، توفّر Crashlytics نموذجًا آخر لتصحيح الأخطاء عندما يكون من المفيد معرفة الحالة الدقيقة لبرنامجك عند تعطُّله: المفاتيح المخصّصة.
هذه هي أزواج المفتاح/القيمة التي يمكنك ضبطها لجلسة. على عكس السجلات التي تتراكم وتكون إضافية بحتة، يمكن استبدال المفاتيح لتعكس فقط الحالة الأحدث لمتغير أو شرط.
بالإضافة إلى كونها سجلاً لآخر حالة مسجَّلة للبرنامج، يمكن استخدام هذه المفاتيح كفلاتر فعّالة لمشاكل Crashlytics.
- في
Assets/Hamster/Scripts/States/DebugMenu.cs
، استبدِلSetAndOverwriteCustomKeyThenCrash()
بما يلي:void SetAndOverwriteCustomKeyThenCrash() { const string CURRENT_TIME_KEY = "Current Time"; System.TimeSpan currentTime = System.DateTime.Now.TimeOfDay; Crashlytics.SetCustomKey( CURRENT_TIME_KEY, DayDivision.GetPartOfDay(currentTime).ToString() // Values must be strings ); // Time Passes currentTime += DayDivision.DURATION_THAT_ENSURES_PHASE_CHANGE; Crashlytics.SetCustomKey( CURRENT_TIME_KEY, DayDivision.GetPartOfDay(currentTime).ToString() ); TestCrash(); }
- أنشئ تطبيقك.
- (على أجهزة Android فقط) حمِّل الرموز عن طريق تنفيذ أمر Firebase CLI التالي:
firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
- انقر على الزر ضبط المفتاح المخصّص وتعطُّل التطبيق، ثم أعِد تشغيل تطبيقك.
- ارجع إلى لوحة بيانات Crashlytics، وانقر على أحدث مشكلة مُدرَجة في جدول المشاكل. مرة أخرى، من المفترض أن يظهر لك شيء مشابه للمشاكل السابقة.
- في هذه المرة، انقر على علامة التبويب المفاتيح في ملخّص الحدث حتى تتمكّن من عرض قيمة المفاتيح، بما في ذلك
Current Time
:
لماذا قد تحتاج إلى استخدام مفاتيح مخصّصة بدلاً من السجلات المخصّصة؟
- تُعد السجلات مناسبة لتخزين البيانات التسلسلية، ولكن المفاتيح المخصّصة تكون أفضل إذا كنت تريد الحصول على قيمة الأحدث فقط.
- في وحدة تحكّم Firebase، يمكنك فلترة المشاكل بسهولة حسب قيم المفاتيح في مربّع البحث في جدول المشاكل.
ومع ذلك، كما هو الحال مع السجلات، هناك حدّ أقصى لعدد المفاتيح المخصّصة. تسمح Crashlytics بحد أقصى 64 زوجًا من المفتاح/القيمة. بعد بلوغ هذا الحدّ، لن يتم حفظ القيم الإضافية. يمكن أن يصل حجم كل زوج مفتاح/قيمة إلى 1 كيلوبايت.
11. (على أجهزة Android فقط) استخدام المفاتيح والسجلات المخصّصة لفهم خطأ ANR وتشخيصه
من أصعب أنواع المشاكل التي يواجهها مطوّرو تطبيقات Android عند تصحيح الأخطاء هو خطأ التطبيق لا يستجيب (ANR). تحدث أخطاء ANR عندما يتعذّر على التطبيق الاستجابة للإدخال لأكثر من 5 ثوانٍ. إذا حدث ذلك، يعني أنّ التطبيق إما توقّف عن العمل أو يعمل ببطء شديد. يظهر مربّع حوار للمستخدمين، ويمكنهم اختيار "انتظار" أو "إغلاق التطبيق".
تُعدّ أخطاء ANR تجربة سيئة للمستخدمين، ويمكن أن تؤثر (كما هو موضّح في رابط أخطاء ANR أعلاه) في قابلية اكتشاف تطبيقك في "متجر Google Play". وبسبب تعقيدها، ولأنّها غالبًا ما تحدث بسبب رموز برمجية متعددة مؤشرات الترابط ذات سلوك مختلف تمامًا على طُرز الهواتف المختلفة، يكون من الصعب جدًا، إن لم يكن من المستحيل، إعادة إنتاج أخطاء ANR أثناء تصحيح الأخطاء. لذلك، فإنّ أفضل طريقة للتعامل معها هي تحليلها واستنتاج الحلول.
في هذه الطريقة، سنستخدم مزيجًا من Crashlytics.LogException
وCrashlytics.Log
وCrashlytics.SetCustomKey
لتكميل عملية تسجيل المشاكل تلقائيًا وللحصول على مزيد من المعلومات.
- في
Assets/Hamster/Scripts/States/DebugMenu.cs
، استبدِلSetLogsAndKeysBeforeANR()
بما يلي:void SetLogsAndKeysBeforeANR() { System.Action<string,long> WaitAndRecord = (string methodName, long targetCallLength)=> { System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); const string CURRENT_FUNCTION = "Current Async Function"; // Initialize key and start timing Crashlytics.SetCustomKey(CURRENT_FUNCTION, methodName); stopWatch.Start(); // The actual (simulated) work being timed. BusyWaitSimulator.WaitOnSimulatedBlockingWork(targetCallLength); // Stop timing stopWatch.Stop(); if(stopWatch.ElapsedMilliseconds>=BusyWaitSimulator.EXTREME_DURATION_MILLIS) { Crashlytics.Log($"'{methodName}' is long enough to cause an ANR."); } else if(stopWatch.ElapsedMilliseconds>=BusyWaitSimulator.SEVERE_DURATION_MILLIS) { Crashlytics.Log($"'{methodName}' is long enough it may cause an ANR"); } }; WaitAndRecord("DoSafeWork",1000L); WaitAndRecord("DoSevereWork",BusyWaitSimulator.SEVERE_DURATION_MILLIS); WaitAndRecord("DoExtremeWork",2*BusyWaitSimulator.EXTREME_DURATION_MILLIS); }
- أنشئ تطبيقك.
- حمِّل الرموز عن طريق تنفيذ أمر Firebase CLI التالي:
firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
- انقر على الزر الذي يحمل التصنيف ضبط السجلات والمفاتيح ← أخطاء ANR، ثم أعِد تشغيل تطبيقك.
- ارجع إلى لوحة بيانات Crashlytics، ثم انقر على المشكلة الجديدة في جدول المشاكل لعرض ملخّص الحدث. إذا تمّت المكالمة بشكلٍ صحيح، من المفترض أن يظهر لك ما يلي:
كما ترى، حدّدت Firebase الانتظار النشط في سلسلة التعليمات باعتباره السبب الرئيسي لظهور خطأ ANR في تطبيقك. - إذا نظرت إلى السجلّات في علامة التبويب السجلّات ضمن ملخّص الأحداث، ستلاحظ أنّ آخر طريقة تم تسجيلها على أنّها مكتملة هي
DoSevereWork
.
في المقابل، آخر طريقة تم إدراجها على أنّها بدأت هيDoExtremeWork
، ما يشير إلى حدوث خطأ ANR أثناء هذه الطريقة، وتم إغلاق اللعبة قبل أن تتمكّن من تسجيلDoExtremeWork
.
ما أهمية إجراء ذلك؟
- يصعب للغاية إعادة إنتاج أخطاء ANR، لذا فإنّ القدرة على الحصول على معلومات مفصّلة حول منطقة الرمز والمقاييس مهمة للغاية لتحديدها بشكل استنتاجي.
- باستخدام المعلومات المخزَّنة في المفاتيح المخصّصة، يمكنك الآن معرفة سلسلة التعليمات غير المتزامنة التي استغرقت أطول وقت لتنفيذها، وتلك التي كانت معرَّضة لخطر حدوث أخطاء ANR. سيُظهر لك هذا النوع من البيانات المنطقية والرقمية ذات الصلة الأماكن التي يكون فيها التحسين ضروريًا في الرمز.
12. إضافة أحداث "إحصاءات Google" لإثراء التقارير بشكل أكبر
يمكن أيضًا استدعاء الطرق التالية من "قائمة تصحيح الأخطاء"، ولكن بدلاً من إنشاء المشاكل بأنفسها، فإنّها تستخدم "إحصاءات Google" كمصدر آخر للمعلومات لفهم طريقة عمل لعبتك بشكل أفضل.
على عكس الطرق الأخرى التي كتبتها في هذا الدرس العملي، يجب استخدام هذه الطرق مع الطرق الأخرى. يمكنك استدعاء هذه الطرق (عن طريق الضغط على الزر المقابل في "قائمة تصحيح الأخطاء") بأي ترتيب عشوائي تريده قبل تشغيل إحدى الطرق الأخرى. بعد ذلك، عند فحص المعلومات في مشكلة Crashlytics المحدّدة، سيظهر لك سجلّ مرتّب لأحداث "إحصاءات Google". ويمكن استخدام هذه البيانات في إحدى الألعاب لفهم مجموعة من تدفق البرنامج أو إدخال المستخدم بشكل أفضل، وذلك حسب طريقة إعداد تطبيقك.
- في
Assets/Hamster/Scripts/States/DebugMenu.cs
، استبدِل عمليات التنفيذ الحالية للطرق التالية:public void LogProgressEventWithStringLiterals() { Firebase.Analytics.FirebaseAnalytics.LogEvent("progress", "percent", 0.4f); }
public void LogIntScoreWithBuiltInEventAndParams() { Firebase.Analytics.FirebaseAnalytics .LogEvent( Firebase.Analytics.FirebaseAnalytics.EventPostScore, Firebase.Analytics.FirebaseAnalytics.ParameterScore, 42 ); }
- أنشئ لعبتك ونفِّذها، ثم أدخِل قائمة تصحيح الأخطاء.
- (على أجهزة Android فقط) حمِّل الرموز عن طريق تنفيذ أمر Firebase CLI التالي:
firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
- اضغط على أحد الأزرار التالية مرة واحدة أو أكثر لتنفيذ الوظائف المذكورة أعلاه:
- Log String Event
- Log Int Event
- اضغط على الزر تعطُّل التطبيق الآن.
- أعِد تشغيل لعبتك لتحميل حدث التعطّل إلى Firebase.
- عند تسجيل تسلسلات مختلفة عشوائية من أحداث "إحصاءات Google"، ثم إنشاء لعبتك لحدث ينشئ Crashlytics تقريرًا منه (كما فعلت للتو)، تتم إضافة هذه التسلسلات إلى علامة التبويب السجلات في ملخّص الأحداث في Crashlytics على النحو التالي:
13. مواصلة التقدم
بهذا نكون قد قدّمنا لك أساسًا نظريًا أفضل يمكنك الاستناد إليه لتكميل تقارير الأعطال التي يتم إنشاؤها تلقائيًا. تتيح لك هذه المعلومات الجديدة استخدام الحالة الحالية وسجلات الأحداث السابقة وأحداث "إحصاءات Google" الحالية لتصنيف تسلسل الأحداث والمنطق الذي أدّى إلى النتيجة بشكلٍ أفضل.
إذا كان تطبيقك يستهدف الإصدار 11 من نظام التشغيل Android (المستوى 30 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، ننصحك بدمج GWP-ASan، وهي ميزة مخصّصة لتخصيص الذاكرة الأصلية ومفيدة لتصحيح الأخطاء في الأعطال الناتجة عن أخطاء الذاكرة الأصلية، مثل أخطاء use-after-free
وheap-buffer-overflow
. للاستفادة من ميزة تصحيح الأخطاء هذه، عليك تفعيل GWP-ASan بشكل صريح.
الخطوات التالية
انتقِل إلى برنامج Instrument your Unity game with Remote Config التعليمي العملي، حيث ستتعرّف على كيفية استخدام ميزة "الإعداد عن بُعد" و"اختبار A/B" في Unity.