J'ai une application hybride Cordova Android et l'application se bloque lorsque l'utilisateur appuie sur une liste déroulante dans ma WebView
sous Android OS 8. J'ai créé une simple page avec une balise <select>
et le problème est reproductible. J'ai une solution de contournement qui consiste à créer ma propre alerte contextuelle, mais je me demande simplement si cela arrive à quelqu'un d'autre et s'il s'agit d'un bogue OS8 WebView
.
Ci-dessous, une simple page avec la balise <select>
https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_select
Ci-dessous mon journal des crashs
11:04:58.643 3208-3208/com.****.****E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.****.****, PID: 3208 Android.content.res.Resources$NotFoundException: Resource ID #0x0
at Android.content.res.ResourcesImpl.getValue(ResourcesImpl.Java:195)
at Android.content.res.Resources.loadXmlResourceParser(Resources.Java:2133)
at Android.content.res.Resources.getLayout(Resources.Java:1142)
at Android.view.LayoutInflater.inflate(LayoutInflater.Java:421)
at Android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.Java:416)
at Android.widget.ArrayAdapter.getView(ArrayAdapter.Java:407)
at org.chromium.content.browser.input.SelectPopupAdapter.getView(SelectPopupAdapter.Java:53)
at Android.widget.AbsListView.obtainView(AbsListView.Java:2372)
at Android.widget.ListView.measureHeightOfChildren(ListView.Java:1408)
at Android.widget.ListView.onMeasure(ListView.Java:1315)
at Android.view.View.measure(View.Java:21998)
at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:6580)
at Android.widget.FrameLayout.onMeasure(FrameLayout.Java:185)
at Android.view.View.measure(View.Java:21998)
at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:6580)
at Android.widget.FrameLayout.onMeasure(FrameLayout.Java:185)
at Android.view.View.measure(View.Java:21998)
at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:6580)
at Android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.Java:1514)
at Android.widget.LinearLayout.measureVertical(LinearLayout.Java:806)
at Android.widget.LinearLayout.onMeasure(LinearLayout.Java:685)
at Android.view.View.measure(View.Java:21998)
at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:6580)
at Android.widget.FrameLayout.onMeasure(FrameLayout.Java:185)
at Android.view.View.measure(View.Java:21998)
at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:6580)
at Android.widget.FrameLayout.onMeasure(FrameLayout.Java:185)
at Android.view.View.measure(View.Java:21998)
at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:6580)
at Android.widget.FrameLayout.onMeasure(FrameLayout.Java:185)
at com.Android.internal.policy.DecorView.onMeasure(DecorView.Java:721)
at Android.view.View.measure(View.Java:21998)
at Android.view.ViewRootImpl.performMeasure(ViewRootImpl.Java:2410)
at Android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.Java:1471)
at Android.view.ViewRootImpl.performTraversals(ViewRootImpl.Java:1751)
at Android.view.ViewRootImpl.doTraversal(ViewRootImpl.Java:1386)
at Android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.Java:6733)
at Android.view.Choreographer$CallbackRecord.run(Choreographer.Java:911)
at Android.view.Choreographer.doCallbacks(Choreographer.Java:723)
at Android.view.Choreographer.doFrame(Choreographer.Java:658)
at Android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.Java:897)
at Android.os.Handler.handleCallback(Handler.Java:789)
at Android.os.Handler.dispatchMessage(Handler.Java:98)
at Android.os.Looper.loop(Looper.Java:164)
at Android.app.ActivityThread.main(ActivityThread.Java:6541)
at Java.lang.reflect.Method.invoke(Native Method)
at com.Android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.Java:240)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:767)
Mon problème n'est pas le même que celui-ci
Essayer d'ouvrir la balise SELECT dans Android WebView bloque l'application
MISE À JOUR DU 9 janvier 2018: Je n'ai pas encore de solution, ma solution temporaire consiste à supprimer la balise et à utiliser simplement une entrée. Lorsque l'utilisateur sélectionne cet élément, nous passons l'événement au code natif pour ouvrir une boîte de dialogue de sélection et mettre à jour l'entrée une fois que l'utilisateur a effectué une sélection.
MISE À JOUR DU 23 MARS 2018: Après une enquête plus approfondie, j'ai remarqué qu'elle se bloque uniquement si la WebView se trouve dans un fragment, mais pas dans une activité.
J'ai trouvé ci-dessous les commentaires de ce post:
Essayer d'ouvrir la balise SELECT dans Android WebView bloque l'application
"Lorsque l'utilisateur clique sur une balise SELECT, Android affiche en interne ses options à l'aide d'un AlertDialog natif. La vue Web doit être créée avec un contexte d'activité car l'instance d'AlertDialog a besoin d'un contexte d'activité."
Je crois que c'est un bug dans Android, probablement pas gérer correctement le contexte pour Fragment.
UPDATE 17 avril 2018:
Comme Kenyee l'a fait remarquer, à partir d'ici https://issuetracker.google.com/issues/77246450 , dit Google
Vous ne devez pas sous-classer l'objet ressources - cela n'a jamais été pris en charge et n'a été possible que par accident (c'est pourquoi il est désormais marqué comme obsolète). L'infrastructure a besoin de connaître tous les objets de ressources pour pouvoir les mettre à jour lorsque la vue Web est chargée (car la vue Web ajoute des chemins d'accès supplémentaires au gestionnaire d'actifs).
Éditer le 29 novembre 2018 On dirait que cette question a dérangé beaucoup de gens.
On dirait que ce bogue: https://issuetracker.google.com/issues/77246450
Ne pas sous-classer les ressources ... apparemment ne sera pas corrigé.
J'ai le même problème sur Android 8.0. Enfin, je le résous. Essayez de mettre à jour votre compilation compileSdkVersion à 26, Et mettez à jour votre ordinateur de poche.Android.support:appcompat-v7 .
Si ce problème persiste, j’ai constaté que ce n’était même pas mon code qui sous-classait la classe Resources, mais plutôt la version de la bibliothèque de prise en charge de Google que j’utilisais. Mise à jour de la version de la bibliothèque de support et cela a fonctionné à merveille!
Peut-être que vous utilisez custom ContextWrapper
dans votre classe Activity
. Dans mon cas, je remplace la méthode attachBaseContext
. Vérifiez cette méthode et utilisez super.attachBaseContext(newBase)
.
Après une enquête, j'ai isolé le problème de WebView dans Fragment sur OS8 uniquement. Ma solution consiste à utiliser l'activité au lieu de fragment pour ce flux particulier. Il me semble un défaut d'Android dans Fragment.
Nous avons en fait trouvé une solution de contournement à ce problème il y a quelques temps nous permettant de continuer à sous-classer Resources
et de ne pas bloquer nos WebViews. La mise en garde est que nous ne pouvons pas laisser notre WebView voir ou interagir avec notre sous-classe de ressources ET nous devons créer le WebView par programme. La première étape consiste à exposer une méthode dans la sous-classe Ressources pour extraire les ressources d'origine.
Disons que notre sous-classe de ressources s'appelle CustomResourcesWrapper
et que notre sous-classe ContextWrapper
s'appelle CustomContextWrapper
.
Tout d'abord, nous mettons à jour la CustomResourcesWrapper
afin de pouvoir accéder à l'objet Resources
d'origine
public class CustomResourcesWrapper {
public static Resources findOriginalResources(Context context) {
if (context.getResources() instanceof CustomResourcesWrapper) {
return ((CustomResourcesWrapper) context.getResources()).getOriginalResources();
}
if (context instanceof ContextWrapper) {
return findOriginalResources(((ContextWrapper) context).getBaseContext());
}
return context.getResources();
}
private Resources getOriginalResources() {
return originalResources;
}
}
Nous supposons également que la variable CustomContextWrapper
ressemble à ceci ...
public class CustomContextWrapper extends ContextWrapper {
private final Resources wrappedResources;
public CustomContextWrapper(Context base, Resources resources) {
super(base);
this.wrappedResources = resources;
}
@Override
public Resources getResources() {
return wrappedResources;
}
}
Ensuite, nous créons une méthode d'assistance statique pour "décompresser" nos ressources personnalisées et les masquer.
// the method name is a bit of a misnomer,
// we're actually unwrapping, then re-wrapping
public static Context unwrapCustomContext(Context wrapped) {
Resources originalResources = CustomResourcesWrapper.findOriginalResources(wrapped);
Context customUnwrappedContext = new CustomContextWrapper(wrapped, originalResources);
return new ContextThemeWrapper(customUnwrappedContext, Android.support.v7.appcompat.R.style.Theme_AppCompat_Light);
}
Lorsque vient le temps de créer une vue Web, assurez-vous que la variable Context
que nous lui avons transmise passe par la méthode ci-dessus, à savoir WebView webView = new WebView(unwrapCustomContext(context))
. Je ne suis pas tout à fait sûr de savoir pourquoi, mais la ContextThemeWrapper
est une partie obligatoire de ce hack.
J'ai creusé dans les journaux de crash. Bien que cette réponse ne résolve pas votre problème, vous pouvez obtenir des informations utiles.
Je ne suis pas sûr de savoir pourquoi cela se produit sur Android 8.0, je ne pouvais pas le reproduire sur l'émulateur d'Android 8.0