Android- deprecated method warning regarding PreferenceActivity

30,308

Solution 1

As the method is deprecated, it is recommended that you don't use it in your code, as it is entirely possible that it can be removed in future versions of Android. However, I am yet to come across a deprecated method that has actually been removed from Android.

No alternative method is provided in the method's description because the preferred approach (as of API level 11) is to instantiate PreferenceFragment objects to load your preferences from a resource file. See the sample code here: PreferenceActivity

Solution 2

PreferenceActivity() is deprecated, but PreferenceFragment() is now as well. PreferenceFragmentCompat() is now the way to go:

Add dependency

implementation "androidx.preference:preference:1.1.1"

Or in case you are still using the support library:

implementation "com.android.support:preference-v7:28.0.0"

Extend PreferenceFragmentCompat

class MyPreferenceFragment : PreferenceFragmentCompat() {
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        addPreferencesFromResource(R.xml.app_preferences)
    }
}

Show your Fragment

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    supportFragmentManager.beginTransaction().replace(android.R.id.content, MyPreferenceFragment()).commit()
}

Specify preferenceTheme

In your AppTheme, add either of the following preference themes, depending of which one you think looks better:

<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>

Solution 3

If you face a deprecation warning from a method like this :

addPreferencesFromResource(R.xml.default_values);

You have to use PreferenceFragment because API 11 and above requires such a method.

Here is an example of how to use PreferenceFragment :

1.Create /res/xml/preferences.xml to define our preferences.

 <PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">

<PreferenceCategory
        android:title="PreferenceCategory A">

    <CheckBoxPreference
            android:key="checkbox_preference"
            android:title="title_checkbox_preference"
            android:summary="summary_checkbox_preference" />

</PreferenceCategory>

<PreferenceCategory
        android:title="PreferenceCategory B">

    <EditTextPreference
            android:key="edittext_preference"
            android:title="title_edittext_preference"
            android:summary="summary_edittext_preference"
            android:dialogTitle="dialog_title_edittext_preference" />

</PreferenceCategory>

2.Create PrefsFragment.java extends PreferenceFragment to addPreferencesFromResource.

   package com.example.androidpreferencefragment;

   import android.os.Bundle;
   import android.preference.PreferenceFragment;

   public class PrefsFragment extends PreferenceFragment {

   @Override
   public void onCreate(Bundle savedInstanceState) {
   // TODO Auto-generated method stub
   super.onCreate(savedInstanceState);

   // Load the preferences from an XML resource
    addPreferencesFromResource(R.xml.preferences);
   }

 }

3.Create SetPreferenceActivity.java to load PrefsFragment.

package com.example.androidpreferencefragment;

import android.app.Activity;
import android.os.Bundle;

public class SetPreferenceActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  super.onCreate(savedInstanceState);

  getFragmentManager().beginTransaction().replace(android.R.id.content,
                new PrefsFragment()).commit();
 }

}

4.Modify the main layout, /res/layout/activity_main.xml, to show the preference.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="@dimen/padding_medium"
    android:text="@string/hello_world"
    tools:context=".MainActivity" />

<CheckBox
    android:id="@+id/prefCheckBox"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="CheckBoxPreference" />

<TextView
    android:id="@+id/prefEditText"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />

</LinearLayout>

5.The main activity, MainActivity.java.

package com.example.androidpreferencefragment;

import android.os.Bundle;
import android.preference.PreferenceManager;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.CheckBox;
import android.widget.TextView;

public class MainActivity extends Activity {

 CheckBox prefCheckBox;
 TextView prefEditText;

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    prefCheckBox = (CheckBox)findViewById(R.id.prefCheckBox);
 prefEditText = (TextView)findViewById(R.id.prefEditText);

 loadPref();
}

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {

  /*
   * Because it's onlt ONE option in the menu.
   * In order to make it simple, We always start SetPreferenceActivity
   * without checking.
   */

  Intent intent = new Intent();
    intent.setClass(MainActivity.this, SetPreferenceActivity.class);
    startActivityForResult(intent, 0); 

    return true;
 }

  @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  // TODO Auto-generated method stub
  //super.onActivityResult(requestCode, resultCode, data);

  /*
   * To make it simple, always re-load Preference setting.
   */

  loadPref();
 }

 private void loadPref(){
  SharedPreferences mySharedPreferences =        PreferenceManager.getDefaultSharedPreferences(this);

  boolean my_checkbox_preference = mySharedPreferences.getBoolean("checkbox_preference", false);
  prefCheckBox.setChecked(my_checkbox_preference);

  String my_edittext_preference = mySharedPreferences.getString("edittext_preference", "");
  prefEditText.setText(my_edittext_preference);

 }

}

5.Finally, modify AndroidManifest.xml to add SetPreferenceActivity.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidpreferencefragment"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="11"
    android:targetSdkVersion="15" />

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/title_activity_main" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".SetPreferenceActivity"
        android:label="@string/title_activity_main" >
    </activity>
</application>

Solution 4

The preferred implementation now uses Fragments. The following will work:

public class DefaultValues extends Activity {

    static final String PREFS_NAME = "defaults";    
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        // Display the fragment as the main content.
        if (savedInstanceState == null)
            getFragmentManager().beginTransaction().add(android.R.id.content, new PrefFragment()).commit();
    }

    public static class PrefFragment extends PreferenceFragment
    {
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);

            getPreferenceManager().setSharedPreferencesName(PREFS_NAME);
            addPreferencesFromResource(R.xml.default_values);
        }
    }
}

Solution 5

Raghav Sood is correct. But if you need PreferenceFragment bad (I needed in tab) you can use this. But it can brake in the future so better to use this only for old apis. It's a little modified PreferenceFragment I made with SupportLibrary and reflection.

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.Preference;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.support.v4.app.Fragment;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnKeyListener;
import android.widget.ListView;

@SuppressLint("HandlerLeak")
public abstract class PreferenceFragment
        extends Fragment
{

    private static final String PREFERENCES_TAG = "android:preferences";

    private PreferenceManager mPreferenceManager;
    private ListView mList;
    private boolean viewCreated;
    // private boolean mHavePrefs;
    // private boolean mInitDone;

    /**
     * The starting request code given out to preference framework.
     */
    private static final int FIRST_REQUEST_CODE = 100;

    private static final int MSG_BIND_PREFERENCES = 1;
    private final Handler mHandler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            switch (msg.what) {

            case MSG_BIND_PREFERENCES:
                if (viewCreated) {
                    bindPreferences();
                }
                break;
            }
        }
    };

    private final Runnable mRequestFocus = new Runnable()
    {
        @Override
        public void run()
        {
            mList.focusableViewAvailable(mList);
        }
    };

    /**
     * Interface that PreferenceFragment's containing activity should implement
     * to be able to process preference items that wish to switch to a new
     * fragment.
     */
    public interface OnPreferenceStartFragmentCallback
    {
        /**
         * Called when the user has clicked on a Preference that has a fragment
         * class name associated with it. The implementation to should
         * instantiate and switch to an instance of the given fragment.
         */
        boolean onPreferenceStartFragment(PreferenceFragment caller,
                Preference pref);
    }

    @SuppressLint("NewApi")
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        try {
            Constructor<?> constructor = PreferenceManager.class
                    .getDeclaredConstructor(Activity.class, int.class);
            constructor.setAccessible(true);
            mPreferenceManager = (PreferenceManager) constructor.newInstance(
                    getActivity(), FIRST_REQUEST_CODE);
        } catch (Throwable e) {
            throw new RuntimeException(
                    "Could not instantiate PreferenceManager: "
                            + e.getMessage());
        }

    }

    @Override
    public final View onCreateView(LayoutInflater inflater,
            ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.activity_preferences, null);
        this.viewCreated = true;
        return v;
    }

    // @Override
    // public View onCreateView(LayoutInflater inflater, ViewGroup container,
    // Bundle savedInstanceState) {
    // return inflater.inflate(R.layout.preference_list_fragment, container,
    // false);
    // }

    @Override
    public void onActivityCreated(Bundle savedInstanceState)
    {
        super.onActivityCreated(savedInstanceState);

        // if (mHavePrefs) {
        bindPreferences();
        // }

        // mInitDone = true;

        if (savedInstanceState != null) {
            Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
            if (container != null) {
                final PreferenceScreen preferenceScreen = getPreferenceScreen();
                if (preferenceScreen != null) {
                    preferenceScreen.restoreHierarchyState(container);
                }
            }
        }
    }

    // @Override
    // public void onStart() {
    // super.onStart();
    // IllegalAccessException
    // try {
    // Method m = PreferenceManager.class
    // .getDeclaredMethod("setOnPreferenceTreeClickListener",
    // Class.forName("android.preference.PreferenceManager$OnPreferenceTreeClickListener"));
    // m.invoke(mPreferenceManager, this);
    // } catch (Exception e) {
    // e.printStackTrace();
    // }
    // mPreferenceManager.setOnPreferenceTreeClickListener(this);
    // }

    @Override
    public void onStop()
    {
        super.onStop();
        try {
            Method m = PreferenceManager.class
                    .getDeclaredMethod("dispatchActivityStop");
            m.setAccessible(true);
            m.invoke(mPreferenceManager);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // IllegalAccessException
        // try {
        // Method m = PreferenceManager.class
        // .getDeclaredMethod("setOnPreferenceTreeClickListener",
        // Class.forName("android.preference.PreferenceManager$OnPreferenceTreeClickListener"));
        // m.invoke(mPreferenceManager, (Object) null);
        // } catch (Exception e) {
        // e.printStackTrace();
        // }
        // mPreferenceManager.setOnPreferenceTreeClickListener(null);
    }

    @Override
    public void onDestroyView()
    {
        this.viewCreated = false;
        mList = null;
        mHandler.removeCallbacks(mRequestFocus);
        mHandler.removeMessages(MSG_BIND_PREFERENCES);
        super.onDestroyView();
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();
        try {
            Method m = PreferenceManager.class
                    .getDeclaredMethod("dispatchActivityDestroy");
            m.setAccessible(true);
            m.invoke(mPreferenceManager);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState)
    {
        super.onSaveInstanceState(outState);

        final PreferenceScreen preferenceScreen = getPreferenceScreen();
        if (preferenceScreen != null) {
            Bundle container = new Bundle();
            preferenceScreen.saveHierarchyState(container);
            outState.putBundle(PREFERENCES_TAG, container);
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);

        try {
            Method m = PreferenceManager.class.getDeclaredMethod(
                    "dispatchActivityResult", int.class, int.class,
                    Intent.class);
            m.setAccessible(true);
            m.invoke(mPreferenceManager, requestCode, resultCode, data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Returns the {@link PreferenceManager} used by this fragment.
     * 
     * @return The {@link PreferenceManager}.
     */
    public PreferenceManager getPreferenceManager()
    {
        return mPreferenceManager;
    }

    /**
     * Sets the root of the preference hierarchy that this fragment is showing.
     * 
     * @param preferenceScreen
     *            The root {@link PreferenceScreen} of the preference hierarchy.
     */
    public void setPreferenceScreen(PreferenceScreen preferenceScreen)
    {
        try {
            Method m = PreferenceManager.class.getDeclaredMethod(
                    "setPreferences", PreferenceScreen.class);
            m.setAccessible(true);
            boolean result = (Boolean) m.invoke(mPreferenceManager,
                    preferenceScreen);
            if (result && preferenceScreen != null) {
                postBindPreferences();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Gets the root of the preference hierarchy that this fragment is showing.
     * 
     * @return The {@link PreferenceScreen} that is the root of the preference
     *         hierarchy.
     */
    public PreferenceScreen getPreferenceScreen()
    {
        try {
            Method m = PreferenceManager.class
                    .getDeclaredMethod("getPreferenceScreen");
            m.setAccessible(true);
            return (PreferenceScreen) m.invoke(mPreferenceManager);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Adds preferences from activities that match the given {@link Intent}.
     * 
     * @param intent
     *            The {@link Intent} to query activities.
     */
    public void addPreferencesFromIntent(Intent intent)
    {
        requirePreferenceManager();
        try {
            Method m = PreferenceManager.class
                    .getDeclaredMethod("inflateFromIntent");
            m.setAccessible(true);
            PreferenceScreen ps = (PreferenceScreen) m.invoke(
                    mPreferenceManager, intent, getPreferenceScreen());
            setPreferenceScreen(ps);
        } catch (Throwable e) {

        }
    }

    /**
     * Inflates the given XML resource and adds the preference hierarchy to the
     * current preference hierarchy.
     * 
     * @param preferencesResId
     *            The XML resource ID to inflate.
     */
    public void addPreferencesFromResource(int preferencesResId)
    {
        requirePreferenceManager();

        try {
            Method m = PreferenceManager.class.getDeclaredMethod(
                    "inflateFromResource", Context.class, int.class,
                    PreferenceScreen.class);
            m.setAccessible(true);
            PreferenceScreen prefScreen = (PreferenceScreen) m.invoke(
                    mPreferenceManager, getActivity(), preferencesResId,
                    getPreferenceScreen());
            setPreferenceScreen(prefScreen);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * {@inheritDoc}
     */
    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
            Preference preference)
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            try {
                Method m = Preference.class.getDeclaredMethod("getFragment");
                Object o = m.invoke(preference);
                if (o != null
                        && getActivity() instanceof OnPreferenceStartFragmentCallback) {
                    return ((OnPreferenceStartFragmentCallback) getActivity())
                            .onPreferenceStartFragment(this, preference);
                }
            } catch (Throwable e) {
            }
        }
        return false;
    }

    /**
     * Finds a {@link Preference} based on its key.
     * 
     * @param key
     *            The key of the preference to retrieve.
     * @return The {@link Preference} with the key, or null.
     * @see PreferenceGroup#findPreference(CharSequence)
     */
    public Preference findPreference(CharSequence key)
    {
        if (mPreferenceManager == null) {
            return null;
        }
        return mPreferenceManager.findPreference(key);
    }

    private void requirePreferenceManager()
    {
        if (mPreferenceManager == null) {
            throw new RuntimeException(
                    "This should be called after super.onCreate.");
        }
    }

    private void postBindPreferences()
    {
        if (mHandler.hasMessages(MSG_BIND_PREFERENCES))
            return;
        mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
    }

    private void bindPreferences()
    {
        final PreferenceScreen preferenceScreen = getPreferenceScreen();
        if (preferenceScreen != null) {
            preferenceScreen.bind(getListView());
        }
    }

    /** @hide */
    public ListView getListView()
    {
        ensureList();
        return mList;
    }

    private void ensureList()
    {
        if (mList != null) {
            return;
        }
        View root = getView();
        if (root == null) {
            throw new IllegalStateException("Content view not yet created");
        }
        View rawListView = root.findViewById(android.R.id.list);
        if (!(rawListView instanceof ListView)) {
            throw new RuntimeException(
                    "Content has view with id attribute 'android.R.id.list' "
                            + "that is not a ListView class");
        }
        mList = (ListView) rawListView;
        if (mList == null) {
            throw new RuntimeException(
                    "Your content must have a ListView whose id attribute is "
                            + "'android.R.id.list'");
        }
        mList.setOnKeyListener(mListOnKeyListener);
        mHandler.post(mRequestFocus);
    }

    private OnKeyListener mListOnKeyListener = new OnKeyListener()
    {

        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event)
        {
            Object selectedItem = mList.getSelectedItem();
            if (selectedItem instanceof Preference) {
                View selectedView = mList.getSelectedView();
                Preference p = (Preference) selectedItem;
                try {
                    Method m = Preference.class.getDeclaredMethod("onKey",
                            View.class, int.class, KeyEvent.class);
                    m.setAccessible(true);
                    boolean result = (Boolean) m.invoke(p, selectedView,
                            keyCode, event);
                    return result;
                } catch (Throwable e) {
                }
            }
            return false;
        }

    };
}
Share:
30,308

Related videos on Youtube

jillianjiggs
Author by

jillianjiggs

Updated on July 09, 2022

Comments

  • jillianjiggs
    jillianjiggs almost 2 years

    When I attempt to follow Android's Developer guides and tutorials for creating a Settings Activity using Preferences, I receive warnings such as:

    "The method addPreferencesFromResource(int) from the type PreferenceActivity is deprecated"

    for both of these lines in the code:

    getPreferenceManager().setSharedPreferencesName(PREFS_NAME);
    addPreferencesFromResource(R.xml.default_values);
    

    I know these are just warnings, but I was wondering if they will cause any issues, now or in the future, when I am running the application that I am designing.

    public class DefaultValues extends PreferenceActivity {
    
        static final String PREFS_NAME = "defaults";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            getPrefs(this);
            getPreferenceManager().setSharedPreferencesName(PREFS_NAME);
            addPreferencesFromResource(R.xml.default_values);
        }
    
        static SharedPreferences getPrefs(Context context) {
            PreferenceManager.setDefaultValues(context, PREFS_NAME, MODE_PRIVATE,
                    R.xml.default_values, false);
            return context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
        }
    }
    
  • Phantômaxx
    Phantômaxx over 10 years
    It will work only if you're using API Level > 10. For lower API levels, you still have to use PreferenceActivity, since the support library doesn't include the PreferenceFragment.