For some application on which I was working, for devices with API level 19 I'm getting exception
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.
Then, I found out that for those applications android frameworks protected boolean isValidFragment(String fragmentName)
is getting called, which has code
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;
}
Then I tried to replicate the error
I took my sample app's code from Preferences Activity Example
and added line <uses-sdk android:targetSdkVersion="19" />
in manifest.
But strangely, I'm not getting the error(isValidFragment() not getting called in that case).
So please tell me how to replicate that error in my sample app.
The answer to your question is in this post. This is a duplicate question:
isValidFragment Android API 19
--Updated--
Here is what the solution is:
Basically, whichever Activity is using your fragment "com...$" in the error above, you must update it with the fix below. You should update all the Activities in your project with this fix for any Acitvity that uses a Fragment.
The documentation states:
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.
You can fix this error by overriding this method to the Activity/FragmentActivity:
@Override
protected boolean isValidFragment (String fragmentName) {
return [YOUR_FRAGMENT_NAME_HERE].class.getName().equals(fragmentName);
}
If you are being lazy and just want to test out if this fix works before coding all your fragments into this method, you can simply return true without any checking:
@Override
protected boolean isValidFragment (String fragmentName) {
return true;
}
I had the same issues when testing on the emulator and this was the solution.
Seems to be a bug or a 4.4 security restriction. Workaraound is to use anything below 19 that is still compatible with PreferenceActivity
, and bite the bullet for compiling with an older target.
I am using the headers "pattern" for the PreferenceActivity (overriding public void onBuildHeaders(List<Header> target)
), and I assume the OP is too, most likely being the place where stuff happens and crashes.
In my case, I have narrowed this exception to <uses-sdk android:targetSdkVersion="19" />
, and anything in [14-18] build targets will compile and run without issues.
Suggestion (for Eclipse): I never messed directly messed with such stuff, but I'm assuming if you compile your PreferenceActivity
(and maybe fragments) on a different project, targeting 18 or under (pun not intended :O ), and then using that project as a library for your main project targeting KitKat (19), perhaps you can avoid the crash scenario at run-time while still using the features you need from the latest build (as long as those features aren't in the build-18-bound PreferenceActivity
). If this does not succeed, try with that project in jar form (pre-compiled) instead of using project as library.
UPDATE: also take note of Camille Sévigny's answer. If the issue has anything to do with that other question (50% chance IMHO), all apps targeting API 18 are vulnerable to fragment injection attacks (see his linked question).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With