isValidFragment Android API 19

前端 未结 9 1935
你的背包
你的背包 2020-12-01 03:00

When I try my app with Android KitKat I have an error in PreferenceActivity.

Subclasses of PreferenceActivity must override isValidFragment(String) to ve

相关标签:
9条回答
  • 2020-12-01 03:10

    this is my solution:

    • if u need dynamic rebuild headers
    • if u use extras to start preference activity - onBuildHeaders() approach will fail! (with below start intent extras - why ??? - simple because onBuildHeaders() is never called):

      Intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMEN,Fragment.class.getName()); Intent.putExtra(PreferenceActivity.EXTRA_NO_HEADERS, true);

    This is example class:

    /**
     * Preference Header for showing settings and add view as two panels for tablets
     * for ActionBar we need override onCreate and setContentView
     */
    public class SettingsPreferenceActivity extends PreferenceActivity {
    
        /** valid fragment list declaration */
        private List<String> validFragmentList;
    
        /** some example irrelevant class for holding user session  */
        SessionManager _sessionManager;
    
        @Override
        public void onBuildHeaders(List<Header> target) {
            /** load header from res */
            loadHeadersFromResource(getValidResId(), target);
        }
    
        /**
         * this API method was added due to a newly discovered vulnerability.
         */
        @Override
        protected boolean isValidFragment(String fragmentName) {
            List<Header> headers = new ArrayList<>();
            /** fill fragments list */
            tryObtainValidFragmentList(getValidResId(), headers);
            /** check  id valid */
            return validFragmentList.contains(fragmentName);
        }
    
        /** try fill list of valid fragments */
        private void tryObtainValidFragmentList(int resourceId, List<Header> target) {  
            /** check for null */
            if(validFragmentList==null) {
                /** init */
                validFragmentList = new ArrayList();
            } else {
                /** clear */
                validFragmentList.clear();
            }
            /** load headers to list */
            loadHeadersFromResource(resourceId, target);
            /** set headers class names to list */
            for (Header header : target) {
                /** fill */
                validFragmentList.add(header.fragment);
            }
        }
    
        /** obtain valid res id to build headers */
        private int getValidResId() {
            /** get session manager */
            _sessionManager = SessionManager.getInstance();
            /** check if user is authorized */
            if (_sessionManager.getCurrentUser().getWebPart().isAuthorized()) {
                /** if is return full preferences header */
                return R.xml.settings_preferences_header_logged_in;
            } else {
                /** else return short header */
                return R.xml.settings_preferences_header_logged_out;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-01 03:14

    Try this... this is how we check validity of fragment.

    protected boolean isValidFragment(String fragmentName) {
      return StockPreferenceFragment.class.getName().equals(fragmentName);
    }
    
    0 讨论(0)
  • 2020-12-01 03:15

    Verified with an actual 4.4 device:

    (1) if your proguard.cfg file has this line (which many define anyway):

    -keep public class com.fullpackage.MyPreferenceFragment
    

    (2) than the most efficient implementation would be:

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public class EditPreferencesHC extends PreferenceActivity {
    ...
       protected boolean isValidFragment (String fragmentName) {
    
         return "com.fullpackage.MyPreferenceFragment".equals(fragmentName);
    
       }
    }
    
    0 讨论(0)
  • 2020-12-01 03:15

    I am not sure if lane's implementation is free of the vulnerabilities discussed here but if it is, then i think a better solution would be to avoid using that static list and simply do the following :

     @Override
        protected boolean isValidFragment(String fragmentName)
        {
            ArrayList<Header> target = new ArrayList<>();
            loadHeadersFromResource(R.xml.pref_headers, target);
            for (Header h : target) {
                if (fragmentName.equals(h.fragment)) return true;
            }
            return false;
        }
    
    0 讨论(0)
  • 2020-12-01 03:16

    Out of pure curiosity, you can also do this as well:

    @Override
    protected boolean isValidFragment(String fragmentName) {
        return MyPreferenceFragmentA.class.getName().equals(fragmentName)
                || MyPreferenceFragmentB.class.getName().equals(fragmentName)
                || // ... Finish with your last fragment.
    
    ;}
    
    0 讨论(0)
  • 2020-12-01 03:19

    my solution (instead of creating ArrayList of class) since the fragments that are loaded suppose to be subclass of PreferenceFragment.class run this check in the @OverRide method

    @Override
    protected boolean isValidFragment(String fragmentName) {
        try {
            Class cls = Class.forName(fragmentName);
            return (cls.getSuperclass().equals(PreferenceFragment.class));
                                      // true if superclass is PreferenceFragmnet
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return false;
    }
    
    0 讨论(0)
提交回复
热议问题