web-dev-qa-db-ja.com

Android HTMLselectタグ付きのOS8WebViewがアプリをクラッシュさせるのはなぜですか

ハイブリッドCordovaAndroidアプリがあり、ユーザーがAndroid OS8で実行されているWebViewのドロップダウンボックスをタップするとアプリがクラッシュします。シンプルなものを作成しました。 <select>タグが付いたページで、問題は再現可能です。自分でポップアップアラートを実行して選択するという回避策がありますが、これが他の誰かに起こっているのか、これがOS8のWebViewバグであるのか疑問に思っています。

以下は<select>タグ付きの簡単なページです

https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_select

以下は私のクラッシュログです

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)

私の問題はこれと同じではありません

Android WebViewでSELECTタグを開こうとすると、アプリケーションがクラッシュします

2018年1月9日の更新:まだ解決策がありません。一時的な回避策は、タグを削除して入力を使用することです。ユーザーがこの要素を選択すると、イベントがネイティブコードに渡され、選択用のダイアログがポップアップ表示され、ユーザーが選択すると入力が更新されます。

2018年3月23日の更新:さらに調査した後、WebViewがフラグメントにある場合にのみクラッシュし、アクティビティにはないことに気付きました。

私はこの投稿からのコメントを以下に見つけました:

Android WebViewでSELECTタグを開こうとすると、アプリケーションがクラッシュします

「SELECTタグをクリックすると、AndroidはネイティブAlertDialogを使用してそのオプションを内部的に表示します。AlertDialogインスタンスにはアクティビティコンテキストが必要なため、Webviewはアクティビティコンテキストで作成する必要があります。

これはAndroidのバグであり、おそらくフラグメントのコンテキストを適切に処理していないと思います。

2018年4月17日更新:

Kenyeeが指摘したように、ここから https://issuetracker.google.com/issues/77246450 、Googleは言います

リソースオブジェクトをサブクラス化してはなりません。これはサポートされておらず、偶然にのみ可能でした(これが非推奨としてマークされている理由です)。フレームワークは、webviewがロードされたときにそれらを更新できるように、すべてのリソースオブジェクトについて知る必要があります(webviewはアセットマネージャーに追加のパスを追加するため)。

2018年11月29日編集この問題は多くの人を悩ませているようです。

  • 私が試し、テストして機能する解決策は、リソースをサブクラス化しないことです。
  • コンパイルSDKとサポートされているライブラリバージョンの更新は、一部の人にとってはうまくいきました。
  • リソースにラッパークラスを追加すると機能する場合があります。最初の調査でこのアプローチを試しましたが、[選択]のクラッシュの問題は解決しましたが、テキストビューをクリックしたままにして[コピー]、[貼り付け]オプションをポップアップするとクラッシュします。 。
16
Dennis Hui

このバグのように見えます: https://issuetracker.google.com/issues/7724645

リソースをサブクラス化しないでください...明らかに修正されません。

2
kenyee

Android 8.0でも同じ問題が発生します。最終的には解決します。compileSdkVersionを26に更新し、com.Android.support:appcompat-v7を26に更新してみてください。

3
Steven Zhang

AndroidXランド(最小のcompileSDKVersion 28に制限されています)では、ポップアップスピナーを備えたMarshmallowエミュレーターでもこの問題が発生していました。私はResourcesの近くには行かないので、これはまだサポートライブラリの1つに関するプラットフォームの問題です。

Webビューをアクティビティに移動するのではなく(実際に試しましたが、不要でした)、ラップされたコンテキストと標準のAppCompatテーマを使用してプログラムで追加することで機能させることができました。

val webView = WebView(ContextThemeWrapper(activity, R.style.Theme_AppCompat_Light))
binding.webViewContainer.addView(webView)

Wtfがここで行われていることはわかりませんが、現在は機能しています。頑張ってください!

[〜#〜] edit [〜#〜]私はこれをさらに詳しく調べて、問題を引き起こしている依存関係を見つけました。マテリアルコンポーネントライブラリの特定のバージョンは、実際にWebビューでこれを引き起こしています(正確には1.1.0-alpha06)。 ここで質問しました 、サンプルプロジェクト付き。

3
Daniel Wilson

誰かがまだこの問題を抱えている場合は、Resourcesクラスをサブクラス化していたのは私のコードではなく、使用していたGoogleサポートライブラリのバージョンであることがわかりました。サポートライブラリのバージョンを更新し、それは魅力のように機能しました!

3
Arash Tadayon

クラッシュログを掘り下げました。この答えはあなたの問題を解決しませんが、あなたはいくつかの有用な洞察を得るかもしれません

なぜそれがAndroid 8.0で起こっているのかわかりませんが、Android 8.0エミュレーターではこれを再現できませんでした

1
Akhil

ContextWrapperクラスでカスタムActivityを使用しているかもしれません。私の場合、attachBaseContextメソッドをオーバーライドします。このメソッドを確認し、super.attachBaseContext(newBase)を使用してください。

0
rz0

調査の結果、OS8のFragment内のWebViewのみに問題を切り分けました。私の回避策は、その特定のフローにフラグメントではなくアクティビティを使用することです。私にはAndroidフラグメントの欠陥のようです。

0
Dennis Hui

実際、少し前にこれの回避策を見つけました。これにより、Resourcesのサブクラス化を続行し、WebViewをクラッシュさせないようにすることができました。注意点は、WebViewにリソースサブクラスを表示または操作させることはできず、プログラムでWebViewを作成する必要があることです。最初のステップは、Resourcesサブクラスのメソッドを公開して、元のリソースを引き出すことです。

リソースサブクラスがCustomResourcesWrapperと呼ばれ、ContextWrapperサブクラスがCustomContextWrapperと呼ばれるとします。

まず、CustomResourcesWrapperを更新して、元のResourcesオブジェクトにアクセスできるようにします。

_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;
    }
}
_

また、CustomContextWrapperは次のようになっていると想定しています...

_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;
    }
}
_

次に、静的ヘルパーメソッドを作成して、カスタムリソースを「アンラップ」し、非表示にします。

_// 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);
}
_

WebViewを作成するときは、WebViewに渡すContextが上記のメソッド、つまりWebView webView = new WebView(unwrapCustomContext(context))を介して実行されることを確認してください。理由は100%わかりませんが、ContextThemeWrapperはこのハックの必須部分です。

0
Geoff