2014-01-06 29 views
7

对于一些上我的工作,对设备与API 19级我得到异常当android的isValidFragment()来自PreferenceActivity被调用?

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 和添加的行清单中的。

但奇怪的是,我没有得到错误(isValidFragment()没有被调用的情况下)。

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

+0

如果我写了一个应用程序,并在3年​​前出版,为什么不能让Google运行,而是设置此ANR – matheszabi

回答

6

似乎是一个错误或4.4安全限制。工作原理是使用低于19的任何东西,仍然与PreferenceActivity兼容,并咬住子弹与旧的目标进行编译。

我为PreferenceActivity使用头文件“模式”(覆盖public void onBuildHeaders(List<Header> target)),并且我假设OP也是如此,最有可能是事情发生和崩溃的地方。

就我而言,我已经缩小这一例外<uses-sdk android:targetSdkVersion="19" />,以及任何在[14-18]构建目标将编译,没有问题的运行。建议(适用于Eclipse):我从来没有把这些东西直接搞砸,但我假设你是否在另一个项目上编译你的PreferenceActivity(也许是片段),目标是18或者下(双关不打算:O) ,然后将该项目作为用于您针对KitKat(19)的主项目,也许您可​​以在运行时避免崩溃情况,同时仍然使用最新版本中所需的功能(只要这些功能不是在构建18绑定的PreferenceActivity中)。如果这没有成功,请尝试使用jar表单(预编译)中的该项目,而不是将项目用作库。

UPDATE:还记得CamilleSévigny的回答。如果问题与其他问题有任何关系(50%的可能性),那么所有针对API 18的应用程序都容易受到碎片注入攻击(请参阅他的链接问题)。

+0

这是个坏主意! - 尤其是当开始偏好活动,你会设置额外 - > Intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMEN,Fragment.class.getName()); Intent.putExtra(PreferenceActivity.EXTRA_NO_HEADERS,true);那么你在黑洞:) - 我的投票下来! – ceph3us

+0

所以你刚刚失去了声望投下我的答案,已经有一个4月3日14更新说明这是一个坏主意。更多的权力给你然后:P – leRobot

+0

我只指出,使用onBuildsHeaders永远不会被调用,所以你不能在这个方法上设置片段进行验证 - isValidFragment被调用,而事务被提交交换片段 – ceph3us

20

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

isValidFragment Android API 19

--Updated--

这里是解决办法是什么:

基本上,无论是活动使用您的片段“COM ... $“在上面的错误中,您必须使用下面的修复更新它。您应该使用此修补程序更新项目中的所有活动,以便使用片段的任何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. 

您可以通过重写此方法的活动/ 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; 
} 

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

+0

首先,它不是重复的,因为在你给出的链接中,他无法删除错误,而且我无法在示例应用程序中重现它。另外我的问题是,当它被调用,而不是如何修复它 –

+0

第二件事,你能详细说明链接的文章吗?将文章链接为答案通常被认为是不好的答案。而且我也无法在你的链接中找到我的问题的答案。 –

+0

@ShirishHerwade我已经更新了我的答案。 –

4

在这里,你去!

拍这个在那里,你很好!

收集此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; 
} 
+1

这是正确的,如果你有更多的类(即片段) – user1616685

+0

优雅的解决方案,谢谢! – TechnIx

+0

很好的解决方案,无法调试 - >发布过渡 – John

相关问题