net.sf.sprockets.app.ui.SprocketsPreferenceFragment.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.sprockets.app.ui.SprocketsPreferenceFragment.java

Source

/*
 * Copyright 2014-2015 pushbit <pushbit@gmail.com>
 *
 * This file is part of Sprockets.
 *
 * Sprockets is free software: you can redistribute it and/or modify it under the terms of the GNU
 * Lesser General Public License as published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * Sprockets is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with Sprockets. If
 * not, see <http://www.gnu.org/licenses/>.
 */

package net.sf.sprockets.app.ui;

import android.app.Activity;
import android.app.backup.BackupManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.TypedArray;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.MultiSelectListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.preference.RingtonePreference;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;

import com.google.android.gms.analytics.Tracker;

import net.sf.sprockets.R;
import net.sf.sprockets.app.Fragments;
import net.sf.sprockets.content.Managers;
import net.sf.sprockets.gms.analytics.Trackers;
import net.sf.sprockets.util.Elements;

import org.apache.commons.collections.primitives.ArrayIntList;
import org.apache.commons.collections.primitives.IntList;

import java.util.Arrays;
import java.util.Set;

import static net.sf.sprockets.gms.analytics.Trackers.event;

/**
 * Sets preference values as their summary for {@link EditTextPreference},
 * {@link MultiSelectListPreference}, {@link RingtonePreference}, and {@link Preference}. This can
 * already be accomplished for {@link ListPreference} by including {@code %s} in its
 * {@link ListPreference#setSummary(CharSequence) summary}. Also
 * {@link BackupManager#dataChanged() requests a backup} when a preference value changes.
 * <p>
 * <strong>Note:</strong> If you want a callback when the user changes a Preference value, override
 * {@link #onPreferenceChange(Preference, Object) onPreferenceChange}. This class already sets
 * itself as the {@link OnPreferenceChangeListener OnPreferenceChangeListener} for each Preference.
 * </p>
 * <p>XML Attributes:</p>
 * <ul>
 * <li>{@link #newInstance(int) preferences}</li>
 * <li>{@link #newInstance(int, boolean) trackChanges}</li>
 * </ul>
 * <p>
 * <a href="https://github.com/pushbit/sprockets-android/blob/master/samples/src/main/res/layout/settings.xml"
 * target="_blank">Sample Usage</a>
 * </p>
 * <p>
 * <a href="https://github.com/pushbit/sprockets-android/blob/master/samples/src/main/res/xml/preferences.xml"
 * target="_blank">Sample Preferences XML</a>
 * </p>
 */
public class SprocketsPreferenceFragment extends PreferenceFragment implements OnPreferenceChangeListener {
    /**
     * Arguments key for a resource reference.
     */
    private static final String PREFS = SprocketsPreferenceFragment.class.getName() + ".prefs";

    /**
     * Arguments key, true to send changes to analytics.
     */
    private static final String TRACK_CHANGES = SprocketsPreferenceFragment.class.getName() + ".trackChanges";

    /**
     * Shortcut to {@link #getActivity()}.
     */
    protected Activity a;

    /**
     * Display the preferences.
     */
    public static SprocketsPreferenceFragment newInstance(int prefsResId) {
        return newInstance(prefsResId, false);
    }

    /**
     * Display the preferences and send changes to analytics.
     *
     * @param trackChanges if true, {@link Trackers#use(Context, Tracker) Trackers.use} must have
     *                     already been called
     * @since 2.6.0
     */
    public static SprocketsPreferenceFragment newInstance(int prefsResId, boolean trackChanges) {
        SprocketsPreferenceFragment frag = new SprocketsPreferenceFragment();
        Bundle args = Fragments.arguments(frag);
        args.putInt(PREFS, prefsResId);
        args.putBoolean(TRACK_CHANGES, trackChanges);
        return frag;
    }

    @Override
    public void onInflate(Activity a, AttributeSet attrs, Bundle savedInstanceState) {
        super.onInflate(a, attrs, savedInstanceState);
        TypedArray array = a.obtainStyledAttributes(attrs, R.styleable.SprocketsPreferenceFragment);
        Bundle args = Fragments.arguments(this);
        args.putInt(PREFS, array.getResourceId(R.styleable.SprocketsPreferenceFragment_preferences, 0));
        args.putBoolean(TRACK_CHANGES,
                array.getBoolean(R.styleable.SprocketsPreferenceFragment_trackChanges, false));
        array.recycle();
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        a = activity;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SprocketsFragment.onCreate(this, savedInstanceState);
        int prefs = Fragments.arguments(this).getInt(PREFS);
        if (prefs > 0) {
            addPreferencesFromResource(prefs);
        }
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        PreferenceScreen screen = getPreferenceScreen();
        int count = screen.getPreferenceCount();
        for (int i = 0; i < count; i++) {
            Preference pref = screen.getPreference(i);
            setSummary(pref);
            pref.setOnPreferenceChangeListener(this);
        }
        getPreferenceManager().getSharedPreferences()
                .registerOnSharedPreferenceChangeListener(mGlobalChangeListener);
    }

    /**
     * Sets the preference value as its summary when it is changed by the user or anything else.
     */
    private final OnSharedPreferenceChangeListener mGlobalChangeListener = new OnSharedPreferenceChangeListener() {
        @Override
        public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
            Preference pref = findPreference(key);
            if (pref != null) {
                setSummary(pref);
            }
        }
    };

    /**
     * Shortcut to {@link #getActivity()}, casting to your assignment type.
     */
    public <T extends Activity> T a() {
        return (T) a;
    }

    /**
     * Set the preference's value(s) as its summary.
     */
    protected void setSummary(Preference pref) {
        SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
        if (pref instanceof RingtonePreference) {
            String val = prefs.getString(pref.getKey(), null);
            if (!TextUtils.isEmpty(val)) {
                Ringtone tone = RingtoneManager.getRingtone(a, Uri.parse(val));
                if (tone != null) {
                    pref.setSummary(tone.getTitle(a));
                }
            } else {
                pref.setSummary(R.string.none);
            }
        } else if (pref instanceof MultiSelectListPreference) {
            Set<String> vals = prefs.getStringSet(pref.getKey(), null);
            if (vals != null) {
                if (!vals.isEmpty()) {
                    MultiSelectListPreference multi = (MultiSelectListPreference) pref;
                    IntList indexList = new ArrayIntList(vals.size());
                    for (String val : vals) { // find selected entry indexes
                        int i = multi.findIndexOfValue(val);
                        if (i >= 0) {
                            indexList.add(i);
                        }
                    }
                    int[] indexes = indexList.toArray();
                    Arrays.sort(indexes); // to display in same order as dialog
                    pref.setSummary(TextUtils.join(getString(R.string.delimiter),
                            Elements.slice(multi.getEntries(), indexes)));
                } else {
                    pref.setSummary(R.string.none);
                }
            }
        } else if (pref instanceof EditTextPreference) {
            pref.setSummary(prefs.getString(pref.getKey(), null));
        } else if (pref.getClass() == Preference.class) {
            String val = prefs.getString(pref.getKey(), null);
            if (!TextUtils.isEmpty(val)) { // don't clear existing summary
                pref.setSummary(val);
            }
        }
    }

    private String mCategory = "settings";

    /**
     * Use the category when sending changes to analytics. Default value: "settings".
     *
     * @since 2.6.0
     */
    public SprocketsPreferenceFragment setAnalyticsCategory(String category) {
        mCategory = category;
        return this;
    }

    @Override
    public boolean onPreferenceChange(Preference pref, Object newValue) {
        if (pref.hasKey()) {
            Managers.backup(a).dataChanged();
            if (Fragments.arguments(this).getBoolean(TRACK_CHANGES)) {
                event(mCategory, "set " + pref.getKey(),
                        pref instanceof EditTextPreference || pref instanceof RingtonePreference ? null
                                : newValue.toString());
            }
        }
        return true;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        SprocketsFragment.onSaveInstanceState(this, outState);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        getPreferenceManager().getSharedPreferences()
                .unregisterOnSharedPreferenceChangeListener(mGlobalChangeListener);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        a = null;
    }
}