Les erreurs ANR Unity se produisent pour diverses raisons. Les erreurs ANR les plus courantes sont causées par les usages abusifs des composants Android et Unity, ainsi que leurs problèmes de communication.
WebView
WebView
est une classe Android qui affiche des pages Web. Tierce
Les SDK (tels que les annonces) utilisent WebView
pour afficher du contenu Web dynamique
dans des activités autres que UnityPlayerActivity
. Des erreurs ANR se produisent lorsque des
Les SDK utilisent WebView
de manière abusive.
Trace de la pile
La trace de la pile est votre premier recours pour comprendre la cause de l'erreur ANR.
/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)
Figure 1 : Trace de la pile ANR causée par une attente futex
Cause
Jusqu'à présent, la cause racine de ce problème n'est pas claire. Certaines causes potentielles peuvent incluent:
- Mauvaise mise en œuvre de l'annonce.
- Version obsolète de
WebView
, car l'utilisateur a peut-être choisi de ne pas la mettre à jour automatiquement l'application. - Utilisation élevée des ressources système (processeur, GPU, etc.), ce qui peut nécessiter beaucoup de et le profilage.
- La compilation de nuanceurs plante, ce qui peut indiquer que le
le contenu comporte un nuanceur incompatible ou que l'utilisateur dispose d'un ancien
WebView
installée.
Solution
- Pour identifier le type de contenu qui entraîne le blocage de
WebView
thread principal, ajoutez des journaux à votre jeu chaque fois qu'une page Web est chargée, affichée, ou fermé.- Vous pouvez utiliser Backtrace ou Crashlytics de création de rapports.
- Après avoir analysé les données et identifié le problème, essayez de désactiver le les fournisseurs d'annonces incriminés.
- Incluez des journaux de mémoire pour vous assurer que le problème n'est pas lié à la mémoire.
- Demandez à l'utilisateur de mettre à jour le
WebView
depuis Google Play. À partir d'Android 5.0 (niveau d'API 21) ou version ultérieure,WebView
a été transféré vers un APK. Par conséquent, il peut être mis à jour séparément de la plate-forme Android. Pour connaître la version deWebView
est en cours d'utilisation sur un appareil, accédez à Paramètres > Applications > Système Android WebView et examinez la version en bas de la page.
Pause de l'unité
Lorsque UnityPlayerActivity
reçoit un appel onPause()
, la chaîne suivante de
début des opérations:
UnityPlayerActivity
informe le moteur d'exécution Unity que l'activité a en pause.- Unity appelle chaque élément
MonoBehaviour
qui implémente le l'événementOnApplicationPause
. - Unity arrête ses composants et modules, comme la lecture audio, le rendu, la boucle de jeu et l'animation.
- Pour vous assurer que
Unity Android Player
(UAP) et le moteur sont synchronisés, l'UAP attend 4 secondes que le moteur s'arrête. - Si cette opération prend plus de cinq secondes, le système déclenche une erreur ANR.
Trace de la pile
"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)
Figure 3. ANR causée par un sémaphore qui n'est jamais publié.
Solution
Assurez-vous que l'exécution du code de votre jeu C# ne prend pas trop de temps lors d'une suspendre ou reprendre l'événement.
- Profilez votre jeu et vérifiez si
OnApplicationPause
est cher opération. Vous pouvez utiliser unStopwatch
. - Évitez les opérations d'E/S ou les requêtes réseau synchrones.
- Déplacez les opérations vers un autre objet
Thread
à l'aide de la méthodeTask
Unity 2023.1 prend en charge un modèle de programmation asynchrone avec C#.async
etawait
.
UnitySendMessage bloqué
Les plug-ins et SDK Unity de Java envoient des données à la couche de jeu C# à l'aide de JNI. Cependant, cette communication peut bloquer le thread principal en raison d'un de synchronisation d'une routine de synchronisation telle qu'un mutex, ce qui provoque une erreur ANR due à un conflit de verrouillage.
Trace de la pile
L'erreur ANR de la figure 4 est causée par une longue opération dans le code C# appelée par un Plug-in Java. Le moteur Unity utilise un héritage non prioritaire mutex pour garantir une exécution correcte.
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)
Figure 4. ANR provoqué par un conflit de verrouillage.
Cause
Le problème est que plusieurs messages sont distribués lorsque l'application est réactivée. Les messages sont en file d'attente, car ils ne peuvent pas être envoyés pendant le jeu en arrière-plan. Les messages sont tous distribués simultanément lorsque l'application reprend.
Pendant une période de pause, vous stockez généralement les informations de votre jeu sur le serveur ; Par exemple, vous enregistrez la position d'un joueur dans le jeu peut revenir au même endroit lorsque la partie reprend.
Cette charge de travail, combinée à d'autres codes tiers créant sa propre charge de travail, peut surcharger les ressources de l'appareil, en particulier le thread principal. La principale Le thread exécute l'interface utilisateur d'une application et constitue souvent l'emplacement principal des erreurs ANR. Donc, toute charge de travail supplémentaire sur le thread principal augmente le risque d'erreur ANR.
Solution
Lors de la mise en pause d'une application, assurez-vous que toutes les actions liées au code sont nécessaires. essayez d'enregistrer l'état de l'utilisateur dans la mémoire locale de l'appareil. Et, bien sûr, voir si vous pouvez aussi effectuer ces actions en dehors de la période de suspension.
Voici quelques approches:
- Déplacer l'opération C# qui gère un message vers un thread
autre que le thread principal.
- Si votre code ne dépend pas du contexte du thread principal Unity, utilisez
Task
pour la communication au lieu du message.
- Si votre code ne dépend pas du contexte du thread principal Unity, utilisez
- N'envoyez pas plusieurs messages depuis votre plug-in lorsque le jeu est mis en pause.
- Le moteur ne peut pas envoyer de messages lorsque le jeu est en arrière-plan.
- N'envoyez le dernier état des données à votre jeu que si cela n'a pas d'incidence sur votre jeu de Google Cloud.
Installer Referrer
Play Install Referrer est une chaîne unique envoyée au Play Store chaque fois qu'un clique sur une annonce. Il s'agit d'un identifiant de suivi d'annonce spécifique à Android. Une fois l'application envoie l'URL de provenance de l'installation au partenaire d'attribution, qui associe la source à l'installation (attribution de la conversion).
Trace de la pile
La figure 5 montre une trace de la pile ANR d'un jeu qui utilise le SDK Facebook pour récupérer l'attribution des installations.
Cause
L'erreur ANR a été causée par un appel de liaison lent. Cependant, la cause racine ne peut pas être déterminé sans accéder au code source du SDK.
Solution
La résolution de ce type de problème implique une communication avec le développeur du SDK ou un qui recherchent en ligne une solution potentielle, qu'ils vérifient du SDK permet de résoudre l'erreur ANR pour d'autres utilisateurs, voire d'expérimenter avec un petit stratégie de déploiement.
Google fournit une page SDK Index qui regroupe les données d'utilisation. depuis les applications Google Play avec des informations collectées via la détection de code fournissent des attributs et des signaux conçus pour vous aider à décider d'adopter ou non, conserver ou supprimer un SDK de votre application.
Ressources supplémentaires
Pour en savoir plus sur les erreurs ANR, consultez les ressources suivantes:
- Déboguer les erreurs ANR : développement de jeux Android
- ANR : qualité de l'application