WebView exécute son contenu Web dans un processus de moteur de rendu distinct. Il peut arriver que ce processus soit interrompu. Cela se produit si le système arrête le moteur de rendu pour récupérer de la mémoire ou si le processus lui-même plante. Si vous ne gérez pas ces arrêts, votre application se fermera également.
Pourquoi la gestion de l'arrêt des processus est-elle essentielle ?
Sur les versions antérieures d'Android, les utilisateurs étaient moins susceptibles de remarquer un problème lorsqu'une application ne parvenait pas à gérer l'arrêt du processus de rendu. Cependant, les versions plus récentes d'Android utilisent des mécanismes plus complexes pour gérer la consommation de ressources des processus en arrière-plan. Par conséquent, si votre application n'implémente pas de gestionnaire pour onRenderProcessGone, il est désormais plus probable que les utilisateurs constatent des arrêts visibles au premier plan lorsqu'ils reviennent dans l'application. L'implémentation de l'API Termination Handling est requise pour que votre application se rétablisse correctement et maintienne une expérience utilisateur stable.
Utiliser l'API Termination Handling
Vous pouvez gérer ces situations en remplaçant onRenderProcessGone dans votre WebViewClient.
Exigences clés pour la récupération
Pour que votre application continue de s'exécuter après l'arrêt d'un processus de moteur de rendu, chaque WebView de votre application doit respecter les règles suivantes :
- Ne réutilisez pas l'instance WebView. Une fois le moteur de rendu supprimé, cet objet WebView spécifique est inutile. Vous devez supprimer l'objet WebView de votre hiérarchie des vues, le détruire et effacer toutes les références à cet objet dans votre activité ou votre fragment pour éviter de continuer à appeler accidentellement des méthodes sur l'instance WebView détruite.
- Créer une instance Si vous souhaitez continuer à afficher du contenu Web, vous devez créer une instance WebView.
- Renvoie "true". Votre implémentation doit renvoyer
truepour indiquer au code WebView que vous avez géré la situation. Si unWebViewutilisant ce processus de moteur de rendu ne renvoie pastrue, WebView arrêtera ou plantera votre application en fonction du motif de fermeture du processus de moteur de rendu.
Exemple de mise en œuvre
L'exemple suivant montre comment gérer ces arrêts dans une activité complète. Il utilise detail.didCrash() pour consigner si le processus a planté ou si le système a arrêté l'outil de rendu pour récupérer de la mémoire. Quelle qu'en soit la cause, le code effectue un nettoyage en supprimant la WebView inactive de la mise en page, en la détruisant et en effaçant les références de l'activité pour éviter les NullPointerException.
Il prépare ensuite une nouvelle instance et renvoie true pour que l'application ne se ferme pas.
Remarque : L'exemple suivant renvoie toujours true pour que l'application continue de s'exécuter.
Si vous souhaitez spécifiquement que votre application se termine lorsque le moteur de rendu WebView se termine, vous pouvez renvoyer false à partir de ce rappel. Toutefois, nous vous recommandons de gérer la recréation et de renvoyer true pour une expérience utilisateur stable.
class MyWebViewActivity : AppCompatActivity() {
private var webViewContainer: ViewGroup? = null
private var myWebView: WebView? = null
private var crashCount = 0
private val MAX_CRASHES = 3
// NEW FLAG: Tracks if the WebView crashed while the activity was hidden
private var isWebViewPendingRecovery = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my_web_view)
webViewContainer = findViewById(R.id.my_web_view_container)
initWebView()
}
// NEW LIFECYCLE HOOK: Triggers when the user brings the app back to the foreground
override fun onResume() {
super.onResume()
// If a crash happened in the background, rebuild it now that the user can see it
if (isWebViewPendingRecovery) {
isWebViewPendingRecovery = false
Log.i("MY_APP_TAG", "Activity resumed. Recovering pending WebView now.")
recoverWebView()
}
}
private fun initWebView() {
val webView = WebView(this)
myWebView = webView
webViewContainer?.addView(webView)
webView.webViewClient = object : WebViewClient() {
override fun onRenderProcessGone(view: WebView, detail: RenderProcessGoneDetail): Boolean {
if (detail.didCrash()) {
Log.e("MY_APP_TAG", "The WebView rendering process crashed!")
} else {
Log.e("MY_APP_TAG", "System killed the WebView rendering process to reclaim memory.")
}
// Safely clean up the dead WebView
webViewContainer?.removeView(webView)
webView.destroy()
myWebView = null
// MODIFIED LOGIC: Check the lifecycle state of the Activity
// lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED) means the activity is visible and active
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
Log.i("MY_APP_TAG", "Activity is in foreground. Recovering immediately.")
recoverWebView()
} else {
// The app is in the background. Mark it for later!
Log.w("MY_APP_TAG", "Activity is in background. Postponing recovery until user returns.")
isWebViewPendingRecovery = true
}
return true
}
}
webView.loadUrl("https://www.example.com")
}
// HELPER FUNCTION: Extracted the recovery logic to reuse it
private fun recoverWebView() {
if (crashCount < MAX_CRASHES) {
crashCount++
Log.w("MY_APP_TAG", "Recovering WebView... Attempt $crashCount")
initWebView()
} else {
Log.e("MY_APP_TAG", "WebView crashed too many times. Showing error UI.")
showErrorUI()
}
}
private fun showErrorUI() {
// Example: Inflate an error view
}
override fun onDestroy() {
super.onDestroy()
myWebView?.let {
webViewContainer?.removeView(it)
it.destroy()
}
myWebView = null
}
}
Remarques importantes
Lorsque vous implémentez onRenderProcessGone, tenez compte des points suivants pour assurer la stabilité de l'application et maintenir la visibilité sur les événements d'arrêt :
- Plantages répétés : si un moteur de rendu plante lors du chargement d'une page spécifique, ne vous contentez pas d'actualiser immédiatement la même page. Cela pourrait entraîner un nouveau plantage de WebView.
- Visibilité : les arrêts d'application causés par l'absence de ce rappel ne sont pas encore reflétés dans les rapports d'erreur de la Play Console. Bien que de futures mises à jour puissent combler cette lacune, vous devez résoudre ces problèmes dès maintenant pour garantir la stabilité de l'application. L'implémentation de ce gestionnaire permet de voir immédiatement pourquoi votre application se ferme.
- Distinguer l'arrêt du moteur de rendu de l'arrêt du processus de l'application :
onRenderProcessGonegère les situations où le processus du moteur de rendu est arrêté alors que le processus de votre application reste actif. Si l'ensemble du processus de l'application est arrêté par le système en arrière-plan, utilisezonSaveInstanceState()avecWebView.saveState()etWebView.restoreState()pour conserver et récupérer l'historique de navigation. Pour gérer l'état enregistré de manière sécurisée sans atteindre les limites de transaction, consultez Gérer efficacement l'état de WebView.