Unity-ANR-Fehler können aus verschiedenen Gründen auftreten. Die häufigsten ANR-Fehler werden durch Missbrauch von Android- und Unity-Komponenten und deren Missverständnisse
WebView
WebView
ist eine Android-Klasse, in der Webseiten angezeigt werden. Drittanbieter
SDKs (z. B. Anzeigen) verwenden WebView
, um dynamische Webinhalte anzuzeigen
bei anderen Aktivitäten als UnityPlayerActivity
. ANR-Fehler treten auf, wenn Drittanbieter
SDKs missbrauchen WebView
.
Stacktrace
Der Stacktrace ist Ihre erste Möglichkeit, die Ursache des ANR-Fehlers zu verstehen.
/data/app/~~p-0ksfCD6bF6Sdq6kpVePg==/com.google.android.webview-5YQZOqKbbqp-uoLY6WYnTw==/base.apk!libmonochrome.so
at J.N.Mhc_M_H$ (Native method)
at org.chromium.components.viz.service.frame_sinks.ExternalBeginFrameSourceAndroid.doFrame (chromium-TrichromeWebViewGoogle.aab-stable-579013831:60)
at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1054)
at android.view.Choreographer.doCallbacks (Choreographer.java:878)
at android.view.Choreographer.doFrame (Choreographer.java:807)
at android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:1041)
at android.os.Handler.handleCallback (Handler.java:938)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loop (Looper.java:223)
at android.app.ActivityThread.main (ActivityThread.java:7721)
at java.lang.reflect.Method.invoke (Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:952)
Abbildung 1.ANR-Stacktrace, der durch eine Futex-Wartezeit verursacht wird.
Ursache
Bislang ist die Ursache dieses Problems unklar. Einige mögliche Ursachen können umfassen:
- Schlechte Anzeigenimplementierung
- Eine veraltete Version von
WebView
, da der Nutzer sich möglicherweise gegen das Update entschieden hat die App automatisch. - Hohe Nutzung der Systemressourcen (CPU, GPU usw.), was möglicherweise viel Profilerstellung.
- Die Shader-Kompilierung stürzt ab, was darauf hindeuten könnte, dass der
Der Inhalt weist einen inkompatiblen Shader oder einen alten
WebView
auf Version installiert ist.
Lösung
- Um herauszufinden, welche Art von Inhalten der
WebView
blockiert, Logs zu eurem Spiel hinzufügen, sobald eine Webseite geladen, angezeigt und angezeigt wird, oder geschlossen ist.- Sie können Backtrace oder Crashlytics verwenden. Meldedienste.
- Wenn Sie die Daten analysiert und das Problem gefunden haben, versuchen Sie, die die als problematisch erachtet werden.
- Fügen Sie Arbeitsspeicherprotokolle hinzu, um sicherzustellen, dass das Problem nicht mit dem Arbeitsspeicher zusammenhängt.
- Benachrichtigen Sie den Nutzer, die
WebView
in Google Play zu aktualisieren. Ab Android 5.0 (API-Level 21) und höher, wurdeWebView
in ein APK verschoben. Daher kann es sein, unabhängig von der Android-Plattform aktualisiert werden. So finden Sie heraus, welche Version vonWebView
auf einem Gerät verwendet wird, rufen Sie Einstellungen > Apps > Android-System WebView und sehen Sie sich die Version unten auf der Seite an.
Unity-Pause
Wenn UnityPlayerActivity
einen onPause()
-Aufruf empfängt, wird die folgende Kette von
Vorgänge beginnt:
UnityPlayerActivity
benachrichtigt die Unity-Laufzeit-Engine, dass die Aktivität pausiert.- Unity ruft alle
MonoBehaviour
auf, in denen dieOnApplicationPause
-Ereignis. - Unity stoppt seine Komponenten und Module, z. B. die Tonwiedergabe, das Rendering, eine Spielschleife und eine Animation.
- Sowohl
Unity Android Player
(UAP) als auch die Engine synchronisiert werden, wartet das UAP 4 Sekunden, bis die Suchmaschine abgeschaltet wird. - Wenn dieser Vorgang länger als 5 Sekunden dauert, löst das System einen ANR-Fehler aus.
Stacktrace
"main" tid=1 Timed Waiting
jdk.internal.misc.Unsafe.park (Native method)
java.util.concurrent.locks.LockSupport.parkNanos (LockSupport.java:234)
java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedNanos (AbstractQueuedSynchronizer.java:1079)
java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos (AbstractQueuedSynchronizer.java:1369)
java.util.concurrent.Semaphore.tryAcquire (Semaphore.java:415)
com.unity3d.player.UnityPlayer.pauseUnity (UnityPlayer.java:833)
com.unity3d.player.UnityPlayer.pause (UnityPlayer.java:796)
com.unity3d.player.UnityPlayerActivity.onPause (UnityPlayerActivity.java:117)
android.app.Activity.performPause (Activity.java:8517)
android.app.Instrumentation.callActivityOnPause (Instrumentation.java:1618)
android.app.ActivityThread.performPauseActivityIfNeeded (ActivityThread.java:5061)
android.app.ActivityThread.performPauseActivity (ActivityThread.java:5022)
android.app.ActivityThread.handlePauseActivity (ActivityThread.java:4974)
android.app.servertransaction.PauseActivityItem.execute (PauseActivityItem.java:48)
android.app.servertransaction.ActivityTransactionItem.execute (ActivityTransactionItem.java:45)
android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:179)
android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:2303)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loopOnce (Looper.java:201)
android.os.Looper.loop (Looper.java:288)
android.app.ActivityThread.main (ActivityThread.java:7884)
java.lang.reflect.Method.invoke (Native method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:936)
Abbildung 3: ANR-Fehler aufgrund einer nie veröffentlichten Semaphore.
Lösung
Achten Sie darauf, dass die Ausführung des C#-Spielcodes während einer Pausieren oder Fortsetzen des Termins.
- Profil für dein Spiel erstellen und prüfen, ob
OnApplicationPause
teuer ist . Sie können einenStopwatch
verwenden. - Vermeiden Sie E/A-Vorgänge oder synchrone Netzwerkanfragen.
- Verschieben Sie die Vorgänge mithilfe der Methode
Thread
Task
Unity 2023.1 unterstützt eine vereinfachte asynchrones Programmiermodell mit C#async
undawait
Keywords.
UnitySendMessage blockiert
Java Unity-Plug-ins und -SDKs senden Daten mithilfe von JNI an die C#-Spieleebene. Diese Kommunikation kann jedoch den Hauptthread aufgrund einer nativen wie einem Mutex, der aufgrund eines Sperrkonflikts einen ANR-Fehler verursacht.
Stacktrace
Der ANR-Fehler in Abbildung 4 wurde durch einen langen Vorgang im C#-Code verursacht, der von einem Java-Plug-in. Die Unity-Engine verwendet eine übernommene Übernahme ohne Priorität. mutex für eine korrekte Ausführung an.
libc.so NonPI::MutexLockWithTimeout(pthread_mutex_internal_t*, bool, timespec const*) + 604
com.unity3d.player.UnityPlayer.nativeUnitySendMessage (Native method)
com.unity3d.player.UnityPlayer.UnitySendMessage (UnityPlayer.java:665)
Abbildung 4: ANR-Fehler aufgrund eines Sperrkonflikts.
Ursache
Das Problem ist, dass mehrere Nachrichten gesendet werden, wenn die Anwendung wird fortgesetzt. Die Nachrichten befinden sich in der Warteschlange, da sie während des Spiels nicht gesendet werden können. im Hintergrund. Die Nachrichten werden alle gleichzeitig gesendet, wenn der wird die App fortgesetzt.
Während einer Pause speichern Sie die Informationen zu Ihrem Spiel in der Regel im Server; z. B. die Position eines Spielers im Spiel, wenn das Spiel fortgesetzt wird.
Diese Arbeitslast, kombiniert mit anderem Code von Drittanbietern, erstellt eine eigene Arbeitslast, die Ressourcen des Geräts, insbesondere den Hauptthread, überlasten kann. Die wichtigsten führt die Benutzeroberfläche einer App aus und ist oft der Hauptort von ANR-Fehlern. Also: Jede zusätzliche Arbeitslast im Hauptthread erhöht das Risiko eines ANR-Fehlers.
Lösung
Prüfen Sie, ob während einer App-Pause alle Codeaktionen erforderlich sind, oder versuchen Sie, den Status des Nutzers im lokalen Arbeitsspeicher des Geräts zu speichern. Und natürlich können Sie sich ob Sie diese Aktionen auch außerhalb der Pause ausführen können.
Einige Ansätze:
- C#-Vorgang, der eine Nachricht verarbeitet, in einen Thread verschieben
als der Hauptthread.
- Wenn Ihr Code nicht vom Kontext des Hauptthreads von Unity abhängt, verwenden Sie
Task
für Kommunikation statt Nachrichten.
- Wenn Ihr Code nicht vom Kontext des Hauptthreads von Unity abhängt, verwenden Sie
- Senden Sie nicht mehrere Nachrichten über Ihr Plug-in, wenn das Spiel pausiert ist.
- Während das Spiel im Hintergrund läuft, kann die Engine keine Nachrichten senden.
- Senden Sie nur dann den letzten Datenstatus an Ihr Spiel, wenn dies keine Auswirkungen auf Ihr Spiel hat. Funktionalität.
Verweis-URL installieren
Die Play Install Referrer ist ein eindeutiger String, der jedes Mal an den Play Store gesendet wird, auf eine Anzeige klickt. Es ist eine Android-spezifische ID für das Anzeigen-Tracking. Einmal installiert haben, sendet die App die Verweis-URL für die Installation an den Attributionspartner, der der Quelle mit der Installation übereinstimmt (die Conversion wird zugeordnet).
Stacktrace
Abbildung 5 zeigt einen ANR-Stacktrace eines Spiels, das das Facebook SDK verwendet, um und rufen Sie die Attribution der Installationen ab.
<ph type="x-smartling-placeholder">Ursache
Der ANR-Fehler wurde durch einen langsamen Binder-Aufruf verursacht. Die Grundursache kann jedoch nicht ohne Zugriff auf den SDK-Quellcode festzulegen.
Lösung
Zur Lösung dieses Problems muss mit dem SDK-Entwickler oder einem häufig online nach einer möglichen Lösung gesucht, Version des SDK den ANR-Fehler für andere behebt für die Einführungsstrategie.
Google stellt eine SDK-Index-Seite zur Verfügung, auf der Nutzungsdaten von Google Play-Apps mit durch Codeerkennung erfassten Informationen bieten Attribute und Signale, die Ihnen bei der Entscheidung helfen, ein SDK aus Ihrer App zu behalten oder zu entfernen.
Weitere Informationen
Weitere Informationen zu ANR-Fehlern finden Sie in den folgenden Ressourcen:
- ANR-Fehler beheben – Android-Spieleentwicklung
- ANRs – App-Qualität