为什么带有HTML select标签的Android OS 8 WebVew会使应用程序崩溃

时间:2017-09-13 23:09:40

标签: android android-webview android-8.0-oreo

我有一个混合的Cordova Android应用程序,当用户点击我在Android OS 8上运行的WebView的下拉框时,应用程序崩溃。我创建了一个带有{{{ 1}}标签,问题是可重现的。我有一个解决方法是做我自己的弹出警报选择,但只是想知道这是否发生在其他任何人以及这是否是一个OS8 <select>错误。

以下是包含WebView标记

的简单页面

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

以下是我的崩溃日志

<select>

我的问题与此

不一样

Trying to open SELECT tag in Android WebView crashes the application

2018年1月9日更新: 我还没有解决方案,我的临时解决方法是删除标签并只使用输入。当用户选择此元素时,我们将事件传递给本机代码以弹出一个用于选择的对话框,并在用户进行选择后更新输入。

2018年3月23日更新: 经过一番调查后,我发现如果WebView在片段中,它只会崩溃,但不会在活动中崩溃。

我在下面的帖子中找到了评论:

Trying to open SELECT tag in Android WebView crashes the application

“单击SELECT标记时,Android会在内部使用本机AlertDialog显示其选项。 必须使用Activity上下文创建Webview,因为AlertDialog实例需要一个Activity上下文。“

我认为这是Android中的一个错误,可能无法正确处理Fragment的上下文。

2018年4月17日更新:

正如肯尼指出的那样,从https://issuetracker.google.com/issues/77246450开始,谷歌说

  

您不能继承资源对象的子类 - 这从未得到支持,并且只能偶然发生(这就是为什么它现在被标记为已弃用)。框架需要了解所有资源对象,以便在加载webview时更新它们(因为webview会向资产管理器添加其他路径)。

编辑2018年11月29日 似乎这个问题困扰了很多人。

  • 我尝试并经过测试的解决方案是不对资源进行子类化。
  • 更新编译sdk和支持的库版本适用于某些人。
  • 向Resource添加包装类可能有效,我在初步调查期间尝试过这种方法,它解决了Select崩溃问题,当您单击并按住文本视图以弹出“COPY”时仍然崩溃,“粘贴“选项。

9 个答案:

答案 0 :(得分:3)

我在Android 8.0上遇到同样的问题。 最后我解决了。 尝试将compileSdkVersion更新为26, 并将您的com.android.support:appcompat-v7更新为26。

答案 1 :(得分:2)

看起来像这个bug: https://issuetracker.google.com/issues/77246450

不要将资源分类......显然不会被修复。

答案 2 :(得分:2)

如果仍然有人遇到此问题,我发现不是我的代码在子类化Resources类,而是我在使用的Google支持库版本。更新了支持库版本,它的工作原理很吸引人!

答案 3 :(得分:0)

我深入了解崩溃日志。虽然这个答案无法解决您的问题,但您可能会获得一些有用的见解

我不确定为什么它会在Android 8.0上发生,但我无法在Android 8.0模拟器上重现这一点

答案 4 :(得分:0)

经过一番调查,我已经将问题分离到OS8内的Fragment中的WebView。我的解决方法是为该特定流使用Activity而不是Fragment。在我看来片段中的Android缺陷。

答案 5 :(得分:0)

也许您在ContextWrapper课程中使用自定义Activity。就我而言,我重写了attachBaseContext方法。检查此方法并使用super.attachBaseContext(newBase)

答案 6 :(得分:0)

实际上,不久前找到了一种解决方法,它使我们可以继续对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时,请确保我们传递给它的Context通过上述方法运行,即WebView webView = new WebView(unwrapCustomContext(context))。我不是100%知道为什么,但是ContextThemeWrapper是此hack的必需部分。

答案 7 :(得分:0)

在AndroidX平台上(限于最低compileSDKVersion 28),我还在带有弹出微调器的棉花糖模拟器上遇到了此问题。我没有在Resources附近走走,所以这仍然是其中一个支持库的平台问题。

我设法使其正常运行-不是通过将Webview移至Activity(尽管我确实尝试过,但这不是必需的),而是通过以包装的上下文和标准AppCompat主题以编程方式添加了它:

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

我不知道wtf会在这里发生,但现在可以正常工作。祝你好运!

编辑 我对此进行了更多研究,发现了导致我麻烦的依赖性。材料组件库的特定版本实际上是在webviews中进行归纳的(确切地说是1.1.0-alpha06)。 I have asked a question on it here,以及一个示例项目。

答案 8 :(得分:-1)

看起来你正在为Textview设置Integer值。尝试使用String.valueOf(value)在Textview中设置值。