【问题标题】:when android's isValidFragment() from PreferenceActivity gets called?当 PreferenceActivity 中的 android isValidFragment() 被调用时?
【发布时间】:2014-01-24 02:22:55
【问题描述】:

对于我正在处理的某些应用程序,对于 API 级别 19 的设备,我遇到了异常

Caused by: java.lang.RuntimeException: Subclasses of PreferenceActivity must override isValidFragment(String) to verify that the Fragment class is valid! com... has not checked if fragment com...$. is valid.

然后,我发现对于那些应用程序,Android 框架 protected boolean isValidFragment(String fragmentName) 被调用,其中包含代码

if (getApplicationInfo().targetSdkVersion  >= android.os.Build.VERSION_CODES.KITKAT) {
        throw new RuntimeException(
                "Subclasses of PreferenceActivity must override isValidFragment(String)"
                + " to verify that the Fragment class is valid! " + this.getClass().getName()
                + " has not checked if fragment " + fragmentName + " is valid.");
    } else {
        return true;
}

然后我尝试复制错误

我从Preferences Activity Example 获取了我的示例应用程序代码 并在清单中添加了<uses-sdk android:targetSdkVersion="19" /> 行。

但奇怪的是,我没有收到错误消息(在这种情况下没有调用 isValidFragment())。

所以请告诉我如何在我的示例应用中复制该错误。

【问题讨论】:

  • 如果我写了一个应用程序并在 3 年前左右发布,为什么不能让 Google 运行而设置此 ANR

标签: android exception android-fragments sdk android-activity


【解决方案1】:

您的问题的答案在这篇文章中。这是一个重复的问题:

isValidFragment Android API 19

--更新--

解决方案如下:

基本上,无论哪个 Activity 在上述错误中使用您的片段“com...$”,您都必须使用下面的修复程序对其进行更新。对于任何使用 Fragment 的 Acitvity,您应该使用此修复更新项目中的所有活动。

文档说明:

protected boolean isValidFragment (String fragmentName)

Added in API level 19

Subclasses should override this method and verify that the given fragment is a 
valid type to be attached to this activity. The default implementation returns 
true for apps built for android:targetSdkVersion older than KITKAT. For later 
versions, it will throw an exception.

您可以通过将此方法覆盖到 Activity/FragmentActivity 来修复此错误:

@Override
protected boolean isValidFragment (String fragmentName) {
  return [YOUR_FRAGMENT_NAME_HERE].class.getName().equals(fragmentName);
}

如果你很懒,只是想在将所有片段编码到这个方法之前测试这个修复是否有效,你可以简单地返回 true 而不做任何检查:

@Override
protected boolean isValidFragment (String fragmentName) {
  return true;
}

我在模拟器上测试时遇到了同样的问题,这就是解决方案。

【讨论】:

  • 首先,它不是重复的,因为在您提供的链接中他无法删除错误,我无法在我的示例应用程序中重现它。另外我的问题是,何时调用而不是如何修复它
  • 第二件事,你能详细说明链接的文章吗?将文章链接为答案通常被认为是错误的答案。而且我无法在您的链接中找到我的问题的答案。
  • 当您在 Activity 中有多个类(如片段)时,这不起作用
  • +1 用于展示“惰性”解决方案 - 当然不应该在生产代码中使用。但为了完整起见,它应该包含在讨论中,如果只是为了表明它不应该被使用。
【解决方案2】:

给你!

把这个拍进去,你就很好了!

收集在这个 PreferenceActivity 中找到的所有内部类。 我选择将列表放在静态字段变量中:

public class whatever extends PreferenceActivity {

    static final Class<?>[] INNER_CLASSES = 
                                     whatever.class.getDeclaredClasses();

然后,重写方法 ValidFragment,并确保即将显示的片段是“父”活动知道的片段:

 /**
 *  Google found a 'security vulnerability' and imposed this hack.
 *  Have to check this fragment was actually conceived by this activity.
 */
@Override
protected boolean isValidFragment(String fragmentName) {

    Boolean knownFrag = false;

    for (Class<?> cls : INNER_CLASSES) {

       if ( cls.getName().equals(fragmentName) ){

           knownFrag = true;

           break;
       }
    }           

    return knownFrag;
}

【讨论】:

  • 这是对的,如果你有更多的类(即片段)
  • 不错的解决方案,调试失败->发布转换
【解决方案3】:

似乎是一个错误或 4.4 安全限制。解决方法是使用任何低于 19 且仍与 PreferenceActivity 兼容的东西,并硬着头皮编译旧目标。

我正在为 PreferenceActivity 使用标题“模式”(覆盖 public void onBuildHeaders(List&lt;Header&gt; target)),并且我认为 OP 也是如此,很可能是事情发生和崩溃的地方。

就我而言,我已将此例外范围缩小到 &lt;uses-sdk android:targetSdkVersion="19" /&gt;,并且 [14-18] 构建目标中的任何内容都将编译并运行而不会出现问题。

建议(针对 Eclipse):我从来没有直接弄乱过这些东西,但我假设你是否在不同的项目上编译你的 PreferenceActivity(可能还有片段),目标是 18 或以下(双关语不是有意的:O (只要这些功能不在 build-18-bound PreferenceActivity 中)。如果这不成功,请尝试以 jar 形式(预编译)使用该项目,而不是将项目用作库。

更新:还要注意 Camille Sévigny 的回答。如果该问题与其他问题有关(恕我直言,有 50% 的可能性),那么所有针对 API 18 的应用都容易受到片段注入攻击(请参阅他的链接问题)。

【讨论】:

  • 这是个坏主意!!! - 特别是当开始偏好活动并且你将设置额外内容时 -> Intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMEN,Fragment.class.getName()); Intent.putExtra(PreferenceActivity.EXTRA_NO_HEADERS, true);那你就在黑洞里了:) - 我投了反对票!
  • 所以你刚刚失去了投票否决我的答案的声誉,该答案已经有 14 年 4 月 3 日的更新说明这是一个坏主意。那么给你更多的力量:P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-29
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-19
相关资源
最近更新 更多