49 votes

isValidFragment API Android 19

Lorsque j'essaie mon application avec Android KitKat, j'ai une erreur dans PreferenceActivity.

Les sous-classes de PreferenceActivity doivent surcharger isValidFragment(String) pour vérifier que la classe Fragment est valide ! com.crbin1.labeltodo.ActivityPreference n'a pas vérifié si le fragment com.crbin1.labeltodo.StockPreferenceFragment est valide

Dans la documentation, je trouve l'explication suivante

Protégé boolean isValidFragment (String fragmentName)

Ajouté au niveau 19 de l'API

Les sous-classes doivent surcharger cette méthode et vérifier que le fragment donné est un type valide pour être attaché à cette activité. L'implémentation par défaut renvoie true pour les applications construites pour Android:targetSdkVersion plus ancienne que KITKAT. Pour les versions ultérieures, une exception sera levée.

Je ne trouve pas d'exemple pour résoudre le problème.

0 votes

Avez-vous essayé de le contourner ?

0 votes

Si je surcharge la méthode avec un simple "return true", cela fonctionne, mais maintenant la question est : "quel contrôle dois-je effectuer dans cette méthode surchargée" ?

1 votes

Je pense que la première question devrait être : "qu'est-ce qu'un fragment valide ?"

65voto

user2098324 Points 386

Essayez ceci... c'est la façon dont nous vérifions la validité du fragment.

protected boolean isValidFragment(String fragmentName) {
  return StockPreferenceFragment.class.getName().equals(fragmentName);
}

0 votes

"StockPreferenceFragment" est la classe de fragment que vous voulez utiliser. David, a posté une réponse ci-dessous, qui montre une solution possible. Cependant, existe-t-il une solution plus propre, permettant d'utiliser plus d'un nom de fragment ?

4 votes

Doit-on le faire pour CHAQUE FRAGMENT ? ou suffit-il de le faire pour la PRÉFÉRENCE ? !

1 votes

@Wolkenjaeger vous pouvez garder vos noms de fragments dans un tableau, et lire à partir de là. L'API compare le nom, vous devez donc trouver un moyen pour que votre code corresponde à la chaîne. Il ne devrait pas être difficile de l'abstraire suffisamment en utilisant les pratiques standard de String. Après tout, c'est vous qui êtes chargé de renvoyer un simple booléen au système. C'est à vous de créer votre propre logique de code.

24voto

David Cesarino Points 7258

Par pure curiosité, vous pouvez aussi le faire :

@Override
protected boolean isValidFragment(String fragmentName) {
    return MyPreferenceFragmentA.class.getName().equals(fragmentName)
            || MyPreferenceFragmentB.class.getName().equals(fragmentName)
            || // ... Finish with your last fragment.

;}

19voto

lane Points 21

J'ai découvert que je pouvais récupérer une copie des noms de mes fragments à partir de ma ressource d'en-tête lorsqu'elle était chargée :

public class MyActivity extends PreferenceActivity
{
    private static List<String> fragments = new ArrayList<String>();

    @Override
    public void onBuildHeaders(List<Header> target)
    {
        loadHeadersFromResource(R.xml.headers,target);
        fragments.clear();
        for (Header header : target) {
            fragments.add(header.fragment);
        }
    }
...
    @Override
    protected boolean isValidFragment(String fragmentName)
    {
        return fragments.contains(fragmentName);
    }
}

Ainsi, je ne dois pas me souvenir de mettre à jour une liste de fragments enfouie dans le code si je veux les mettre à jour.

J'avais espéré utiliser getHeaders() et la liste existante d'en-têtes directement, mais il semble que l'activité est détruite après que onBuildHeaders() et recréé avant isValidFragment() s'appelle.

Cela peut s'expliquer par le fait que la Nexus 7 sur laquelle je fais mes tests ne permet pas de réaliser des activités de préférences à deux volets. D'où la nécessité d'un membre de liste statique également.

18voto

Roee Hay Points 151

Cette API a été ajoutée en raison d'une vulnérabilité récemment découverte. Veuillez consulter http://ibm.co/1bAA8kF o http://ibm.co/IDm2Es

10 décembre 2013 "Nous avons récemment divulgué une nouvelle vulnérabilité à l'équipe de sécurité Android. [...] Pour être plus précis, toute application qui étendait la classe PreferenceActivity en utilisant une activité exportée était automatiquement vulnérable. Un correctif a été fourni dans Android KitKat. Si vous vous demandez pourquoi votre code est maintenant cassé, cela est dû au correctif d'Android KitKat qui exige que les applications surchargent la nouvelle méthode, PreferenceActivity.isValidFragment, qui a été ajoutée au Framework Android." -- Du premier lien ci-dessus

8 votes

Bonjour @RoeeHay, pouvez-vous s'il vous plaît élaborer sur l'article lié ? Il est souvent considéré comme une mauvaise réponse de lier des articles comme réponses. Pouvez-vous indiquer les points importants de la vulnérabilité ? Je vois que l'article lui-même est écrit par vous et qu'il explique beaucoup de choses. pourquoi il a été introduit. J'aimerais beaucoup que cette réponse soit notée positivement, car elle explique de loin le pourquoi plutôt que le comment du problème.

3voto

uval Points 2127

Vérifié avec un appareil 4.4 réel :

(1) si votre fichier proguard.cfg comporte cette ligne ( que beaucoup définissent de toute façon ) :

-keep public class com.fullpackage.MyPreferenceFragment

(2) que la mise en œuvre la plus efficace :

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class EditPreferencesHC extends PreferenceActivity {
...
   protected boolean isValidFragment (String fragmentName) {

     return "com.fullpackage.MyPreferenceFragment".equals(fragmentName);

   }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X