When is android isValidFragment () from PreferenceActivity called?

For some applications I have been working on, for devices with level 19 API I get an 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 that are developing Android frameworks, protected boolean isValidFragment(String fragmentName) , 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 the sample application code from the Example settings action and added the line <uses-sdk android:targetSdkVersion="19" /> to the manifest.

But strangely, I am not getting an error (isValidFragment () does not receive the call in this case).

So please tell me how to copy this error in my sample application.

+7
android android-activity exception sdk android-fragments
source share
3 answers

This seems to be a bug or security restriction 4.4. Workaraound - Use anything below 19, which is still compatible with PreferenceActivity , and bite the bullet to compile with an older target.

I use the header template for PreferenceActivity (overriding public void onBuildHeaders(List<Header> target) ), and I assume that the OP is also most likely the place where something happens and happens.

In my case, I eliminated this exception in <uses-sdk android:targetSdkVersion="19" /> , and everything that in [14-18] builds will compile and run without problems.

Suggestion (for Eclipse): I never messed up, so I wasnโ€™t wrong, but I assume that you will compile your PreferenceActivity (and possibly fragments) in another project targeting 18 or lower (pun intended: O), and then using this project as a library for your main KitKat (19) oriented project, maybe you can avoid the runtime crash scenario while still using the functions you need from the last build (as long as these functions are not in build-18-bound PreferenceActivity ). If this fails, try this project in jar form (precompiled) instead of using as a library.

UPDATE : also pay attention to Camilla Sevigny's answer. If the problem has anything to do with this other issue (IMHO 50% chance), all API 18-oriented applications are vulnerable to fragmentation attacks (see His related question).

+6
source share

The answer to your question is in this post. This is a recurring question:

isValidFragment Android API 19

- Updated -

Here is what the solution is:

Basically, whatever activity your "com ... $" snippet uses in the above error, you should update it with the fix below. You must update all the activities in your project with this patch for any Acitvity that uses the 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 in Activity / FragmentActivity:

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

If you are lazy and just want to check if this fix works before encoding all your fragments into this method, you can simply return true without any check:

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

I had the same problems when testing on an emulator, and that was the solution.

+20
source share

Here you go!

Listen to it there and you are good!

Collect all the inner classes found in this PreferenceActivity. I decided to put the list in a static field variable:

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

Then override the ValidFragment method and make sure that the fragment that should be displayed is one of the types of parent activity:

  /** * 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; } 
+5
source share

All Articles