Dans Lollipop (API 22), chaque fois dans mon application, je montre une vue Web de l'application qui plante. J'ai plusieurs plantages dans ma Android liée à cet événement.
Inutile de dire que cela fonctionne sur Android 4, 6 et 7.
Lire la trace de la pile (posté à la fin de ce post), quelque chose me dérange
Caused by: Android.content.res.Resources$NotFoundException: String resource ID #0x2040003
J'ai cherché dans le R.Java généré sans aucune chance, évidemment parce que l'ID n'existe pas, mais cela valait la peine d'essayer.
La recherche sur le problème semble liée à la façon dont Lollipop gère la vue Web. J'ai commencé un nouveau AVD avec Lollipop basé sur un appareil que j'ai trouvé sur le reporter de crash dans GDC, et je peux reproduire le problème.
Trace de pile complète:
Android.view.InflateException: Binary XML file line #7: Error inflating class Android.webkit.WebView
at Android.view.LayoutInflater.createView(LayoutInflater.Java:633)
at com.Android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.Java:55)
at Android.view.LayoutInflater.onCreateView(LayoutInflater.Java:682)
at Android.view.LayoutInflater.createViewFromTag(LayoutInflater.Java:741)
at Android.view.LayoutInflater.rInflate(LayoutInflater.Java:806)
at Android.view.LayoutInflater.inflate(LayoutInflater.Java:504)
at Android.view.LayoutInflater.inflate(LayoutInflater.Java:414)
at it.artecoop.ibreviary.WebViewFragment.onCreateView(WebViewFragment.Java:67)
at Android.support.v4.app.Fragment.performCreateView(Fragment.Java:2087)
at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:1113)
at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:1295)
at Android.support.v4.app.BackStackRecord.run(BackStackRecord.Java:801)
at Android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.Java:1682)
at Android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.Java:541)
at Android.os.Handler.handleCallback(Handler.Java:739)
at Android.os.Handler.dispatchMessage(Handler.Java:95)
at Android.os.Looper.loop(Looper.Java:135)
at Android.app.ActivityThread.main(ActivityThread.Java:5254)
at Java.lang.reflect.Method.invoke(Native Method)
at Java.lang.reflect.Method.invoke(Method.Java:372)
at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:903)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:698)
Caused by: Java.lang.reflect.InvocationTargetException
at Java.lang.reflect.Constructor.newInstance(Native Method)
at Java.lang.reflect.Constructor.newInstance(Constructor.Java:288)
at Android.view.LayoutInflater.createView(LayoutInflater.Java:607)
at com.Android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.Java:55)
at Android.view.LayoutInflater.onCreateView(LayoutInflater.Java:682)
at Android.view.LayoutInflater.createViewFromTag(LayoutInflater.Java:741)
at Android.view.LayoutInflater.rInflate(LayoutInflater.Java:806)
at Android.view.LayoutInflater.inflate(LayoutInflater.Java:504)
at Android.view.LayoutInflater.inflate(LayoutInflater.Java:414)
at it.artecoop.ibreviary.WebViewFragment.onCreateView(WebViewFragment.Java:67)
at Android.support.v4.app.Fragment.performCreateView(Fragment.Java:2087)
at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:1113)
at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:1295)
at Android.support.v4.app.BackStackRecord.run(BackStackRecord.Java:801)
at Android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.Java:1682)
at Android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.Java:541)
at Android.os.Handler.handleCallback(Handler.Java:739)
at Android.os.Handler.dispatchMessage(Handler.Java:95)
at Android.os.Looper.loop(Looper.Java:135)
at Android.app.ActivityThread.main(ActivityThread.Java:5254)
at Java.lang.reflect.Method.invoke(Native Method)
at Java.lang.reflect.Method.invoke(Method.Java:372)
at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:903)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:698)
Caused by: Android.content.res.Resources$NotFoundException: String resource ID #0x2040003
at Android.content.res.Resources.getText(Resources.Java:299)
at Android.content.res.Resources.getString(Resources.Java:385)
at com.Android.org.chromium.content.browser.ContentViewCore.setContainerView(ContentViewCore.Java:684)
at com.Android.org.chromium.content.browser.ContentViewCore.initialize(ContentViewCore.Java:608)
at com.Android.org.chromium.Android_webview.AwContents.createAndInitializeContentViewCore(AwContents.Java:631)
at com.Android.org.chromium.Android_webview.AwContents.setNewAwContents(AwContents.Java:780)
at com.Android.org.chromium.Android_webview.AwContents.<init>(AwContents.Java:619)
at com.Android.org.chromium.Android_webview.AwContents.<init>(AwContents.Java:556)
at com.Android.webview.chromium.WebViewChromium.initForReal(WebViewChromium.Java:311)
at com.Android.webview.chromium.WebViewChromium.access$100(WebViewChromium.Java:96)
at com.Android.webview.chromium.WebViewChromium$1.run(WebViewChromium.Java:263)
at com.Android.webview.chromium.WebViewChromium$WebViewChromiumRunQueue.drainQueue(WebViewChromium.Java:123)
at com.Android.webview.chromium.WebViewChromium$WebViewChromiumRunQueue$1.run(WebViewChromium.Java:110)
at com.Android.org.chromium.base.ThreadUtils.runOnUiThread(ThreadUtils.Java:144)
at com.Android.webview.chromium.WebViewChromium$WebViewChromiumRunQueue.addTask(WebViewChromium.Java:107)
at com.Android.webview.chromium.WebViewChromium.init(WebViewChromium.Java:260)
at Android.webkit.WebView.<init>(WebView.Java:554)
at Android.webkit.WebView.<init>(WebView.Java:489)
at Android.webkit.WebView.<init>(WebView.Java:472)
at Android.webkit.WebView.<init>(WebView.Java:459)
at Java.lang.reflect.Constructor.newInstance(Native Method)
at Java.lang.reflect.Constructor.newInstance(Constructor.Java:288)
at Android.view.LayoutInflater.createView(LayoutInflater.Java:607)
at com.Android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.Java:55)
at Android.view.LayoutInflater.onCreateView(LayoutInflater.Java:682)
at Android.view.LayoutInflater.createViewFromTag(LayoutInflater.Java:741)
at Android.view.LayoutInflater.rInflate(LayoutInflater.Java:806)
at Android.view.LayoutInflater.inflate(LayoutInflater.Java:504)
at Android.view.LayoutInflater.inflate(LayoutInflater.Java:414)
at it.artecoop.ibreviary.WebViewFragment.onCreateView(WebViewFragment.Java:67)
at Android.support.v4.app.Fragment.performCreateView(Fragment.Java:2087)
at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:1113)
at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:1295)
at Android.support.v4.app.BackStackRecord.run(BackStackRecord.Java:801)
at Android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.Java:1682)
at Android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.Java:541)
at Android.os.Handler.handleCallback(Handler.Java:739)
at Android.os.Handler.dispatchMessage(Handler.Java:95)
at Android.os.Looper.loop(Looper.Java:135)
at Android.app.ActivityThread.main(ActivityThread.Java:5254)
at Java.lang.reflect.Method.invoke(Native Method)
at Java.lang.reflect.Method.invoke(Method.Java:372)
at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:903)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:698)
si vous utilisez "androidx.appcompat: appcompat: 1.1.0", essayez plutôt "androidx.appcompat: appcompat: 1.0.2". il semble que 1.1.0 ne gère pas le bogue avec la vue Web dans Android 5.1.1.
Si vous souhaitez gonfler le WebView à partir d'une disposition XML, vous pouvez l'envelopper dans une petite sous-classe Nice (basée sur réponse d'ikostet ):
public class LollipopFixedWebView extends WebView {
public LollipopFixedWebView(Context context) {
super(getFixedContext(context));
}
public LollipopFixedWebView(Context context, AttributeSet attrs) {
super(getFixedContext(context), attrs);
}
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(getFixedContext(context), attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.Lollipop)
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
}
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
super(getFixedContext(context), attrs, defStyleAttr, privateBrowsing);
}
public static Context getFixedContext(Context context) {
return context.createConfigurationContext(new Configuration());
}
}
EDIT: maintenant encore plus agréable avec Kotlin
class LollipopFixedWebView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : WebView(context.createConfigurationContext(Configuration()), attrs, defStyleAttr, defStyleRes)
Essayez d'utiliser pour créer une vue Web:
mWebView = new WebView(getActivity().createConfigurationContext(new Configuration()));
mon conseil est d'utiliser custom/new Configuration
uniquement lorsque "original one" cause des problèmes, donc Lollipop uniquement. Le code @SpaceBizon fonctionne bien jusqu'à Android 8.x, le 9 et Q (actuellement en version bêta), chaque pression de sélection/liste déroulante n'affichera pas le sélecteur AlertDialog
, au lieu de cette fuite de mémoire se produit ... sous la méthode getFixedContext
fixe avec le code de version correct "iffed"
public class LollipopFixedWebView extends WebView {
public LollipopFixedWebView(Context context) {
super(getFixedContext(context));
}
public LollipopFixedWebView(Context context, AttributeSet attrs) {
super(getFixedContext(context), attrs);
}
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(getFixedContext(context), attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.Lollipop)
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
}
private static Context getFixedContext(Context context) {
if (Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT < 23) // Android Lollipop 5.0 & 5.1
return context.createConfigurationContext(new Configuration());
return context;
}
}
J'ai pu reproduire ce problème sur une Nexus 7 API 22. Le problème est résolu en mettant à jour la version de la tablette de Android System WebView from version 39 (2237560-arm) = à version 79.0.3945.136
Ce n'est pas sous mon contrôle pour un utilisateur de le faire, mais c'est une solution si vous devez aider quelqu'un à utiliser votre application immédiatement.
Le code ci-dessous résoudra les problèmes. Veuillez l'ajouter dans votre Activity
:
@Override
public AssetManager getAssets() { return getResources().getAssets();
}
Dans mon cas, un problème de méthode
fun getUserId(): Int = userId
d'une activité principale. Je ne sais pas pourquoi cela affecte WebView
. getUserId()
n'est ni surchargée, ni méthode publique de la classe Activity
. Si je renomme ou supprime cette méthode, WebView
commence à s'ouvrir. Essayer également de changer
private var userId: Int = 0
à
var userId: Int = 0
private set
conduit à la même exception. J'ai compris que quand avait vu une exception: Caused by: Java.lang.SecurityException: Permission Denial: null asks to run as user 123456 but is calling from user 0; this requires Android.permission.INTERACT_ACROSS_USERS_FULL or Android.permission.INTERACT_ACROSS_USERS
. Dans ce cas, user = 123456 était en fait mon utilisateur autorisé, qui était utilisé dans certaines requêtes, pas dans WebView
. Je soupçonne Android utilise userId
comme id_utilisateur local pour ses processus.
Comme beaucoup d'autres personnes ont remarqué que nous pouvions utiliser appcompat:1.1.0
Ou 1.0.2
Et étendre la classe WebView
. Dans l'émulateur 21 sans les services Google Play, ce WebView
se bloquera sur une longue touche sur les étiquettes de texte, mais sur les appareils typiques, tout va bien.