Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

when android's isValidFragment() from PreferenceActivity gets called?

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.

like image 644
Shirish Herwade Avatar asked Jan 06 '14 16:01

Shirish Herwade


2 Answers

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.

like image 79
Camille Sévigny Avatar answered Oct 13 '22 00:10

Camille Sévigny


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).

like image 39
leRobot Avatar answered Oct 13 '22 01:10

leRobot