对于我工作的某些应用程序,对于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()没有被调用。)
请告诉我如何在我的示例应用中复制该错误。
答案 0 :(得分:21)
你的问题的答案在这篇文章中。这是一个重复的问题:
isValidFragment Android API 19
<强> - 更新 - 强>
以下是解决方案:
基本上,无论哪个Activity在上面的错误中使用您的片段“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.
您可以通过将此方法重写为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;
}
在模拟器上进行测试时遇到了同样的问题,这就是解决方案。
答案 1 :(得分:6)
似乎是一个bug或4.4安全限制。 Workaraound是使用仍然与PreferenceActivity
兼容的19以下的任何东西,并咬住用旧目标编译的子弹。
我正在使用PreferenceActivity的标题“pattern”(覆盖public void onBuildHeaders(List<Header> target)
),我认为OP也是,很可能是事情发生和崩溃的地方。
在我的情况下,我已将此异常缩小到<uses-sdk android:targetSdkVersion="19" />
,[14-18]构建目标中的任何内容都会编译并运行而不会出现问题。
建议(对于Eclipse):我从来没有直接搞砸这些东西,但是我假设你是否在另一个项目上编译你的PreferenceActivity
(也许是片段),目标是18或者不合适:O),然后将该项目用作针对KitKat(19)的主项目的库,也许您可以在运行时避免崩溃场景,同时仍然使用最新需要的功能构建(只要这些功能不在build-18-bound PreferenceActivity
中)。如果这不成功,请尝试使用 jar 表单(预编译)中的项目,而不是将项目用作库。
更新:还要注意CamilleSévigny的回答。如果该问题与其他问题有关(恕我直言的可能性为50%),则所有针对API 18的应用都容易受到片段注入攻击(请参阅他的链接问题)。
答案 2 :(得分:5)
你走了!
把它扯到那里,你就好了!
收集此PreferenceActivity中找到的所有内部类。 我选择将列表放在静态字段变量中:
public class whatever extends PreferenceActivity {
static final Class<?>[] INNER_CLASSES =
whatever.class.getDeclaredClasses();
然后,覆盖方法ValidFragment,并确保即将显示的片段是父母的一个&#39;活动意识到:
/**
* 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;
}