RingtonePreference.java revision 3156bb00dd3ab3d6ec732bb6a64a2e84d08c34f0
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.preference;
18
19import android.content.Context;
20import android.content.Intent;
21import android.content.res.TypedArray;
22import android.media.RingtoneManager;
23import android.net.Uri;
24import android.provider.Settings.System;
25import android.text.TextUtils;
26import android.util.AttributeSet;
27import android.util.Log;
28
29/**
30 * A {@link Preference} that allows the user to choose a ringtone from those on the device.
31 * The chosen ringtone's URI will be persisted as a string.
32 * <p>
33 * If the user chooses the "Default" item, the saved string will be one of
34 * {@link System#DEFAULT_RINGTONE_URI},
35 * {@link System#DEFAULT_NOTIFICATION_URI}, or
36 * {@link System#DEFAULT_ALARM_ALERT_URI}. If the user chooses the "Silent"
37 * item, the saved string will be an empty string.
38 *
39 * @attr ref android.R.styleable#RingtonePreference_ringtoneType
40 * @attr ref android.R.styleable#RingtonePreference_showDefault
41 * @attr ref android.R.styleable#RingtonePreference_showSilent
42 */
43public class RingtonePreference extends Preference implements
44        PreferenceManager.OnActivityResultListener {
45
46    private static final String TAG = "RingtonePreference";
47
48    private int mRingtoneType;
49    private boolean mShowDefault;
50    private boolean mShowSilent;
51
52    private int mRequestCode;
53
54    public RingtonePreference(Context context, AttributeSet attrs, int defStyle) {
55        super(context, attrs, defStyle);
56
57        TypedArray a = context.obtainStyledAttributes(attrs,
58                com.android.internal.R.styleable.RingtonePreference, defStyle, 0);
59        mRingtoneType = a.getInt(com.android.internal.R.styleable.RingtonePreference_ringtoneType,
60                RingtoneManager.TYPE_RINGTONE);
61        mShowDefault = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showDefault,
62                true);
63        mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent,
64                true);
65        a.recycle();
66    }
67
68    public RingtonePreference(Context context, AttributeSet attrs) {
69        this(context, attrs, com.android.internal.R.attr.ringtonePreferenceStyle);
70    }
71
72    public RingtonePreference(Context context) {
73        this(context, null);
74    }
75
76    /**
77     * Returns the sound type(s) that are shown in the picker.
78     *
79     * @return The sound type(s) that are shown in the picker.
80     * @see #setRingtoneType(int)
81     */
82    public int getRingtoneType() {
83        return mRingtoneType;
84    }
85
86    /**
87     * Sets the sound type(s) that are shown in the picker.
88     *
89     * @param type The sound type(s) that are shown in the picker.
90     * @see RingtoneManager#EXTRA_RINGTONE_TYPE
91     */
92    public void setRingtoneType(int type) {
93        mRingtoneType = type;
94    }
95
96    /**
97     * Returns whether to a show an item for the default sound/ringtone.
98     *
99     * @return Whether to show an item for the default sound/ringtone.
100     */
101    public boolean getShowDefault() {
102        return mShowDefault;
103    }
104
105    /**
106     * Sets whether to show an item for the default sound/ringtone. The default
107     * to use will be deduced from the sound type(s) being shown.
108     *
109     * @param showDefault Whether to show the default or not.
110     * @see RingtoneManager#EXTRA_RINGTONE_SHOW_DEFAULT
111     */
112    public void setShowDefault(boolean showDefault) {
113        mShowDefault = showDefault;
114    }
115
116    /**
117     * Returns whether to a show an item for 'Silent'.
118     *
119     * @return Whether to show an item for 'Silent'.
120     */
121    public boolean getShowSilent() {
122        return mShowSilent;
123    }
124
125    /**
126     * Sets whether to show an item for 'Silent'.
127     *
128     * @param showSilent Whether to show 'Silent'.
129     * @see RingtoneManager#EXTRA_RINGTONE_SHOW_SILENT
130     */
131    public void setShowSilent(boolean showSilent) {
132        mShowSilent = showSilent;
133    }
134
135    @Override
136    protected void onClick() {
137        // Launch the ringtone picker
138        Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
139        onPrepareRingtonePickerIntent(intent);
140        getPreferenceManager().getActivity().startActivityForResult(intent, mRequestCode);
141    }
142
143    /**
144     * Prepares the intent to launch the ringtone picker. This can be modified
145     * to adjust the parameters of the ringtone picker.
146     *
147     * @param ringtonePickerIntent The ringtone picker intent that can be
148     *            modified by putting extras.
149     */
150    protected void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent) {
151
152        ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI,
153                onRestoreRingtone());
154
155        ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, mShowDefault);
156        if (mShowDefault) {
157            ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI,
158                    RingtoneManager.getDefaultUri(getRingtoneType()));
159        }
160
161        ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, mShowSilent);
162        ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, mRingtoneType);
163    }
164
165    /**
166     * Called when a ringtone is chosen.
167     * <p>
168     * By default, this saves the ringtone URI to the persistent storage as a
169     * string.
170     *
171     * @param ringtoneUri The chosen ringtone's {@link Uri}. Can be null.
172     */
173    protected void onSaveRingtone(Uri ringtoneUri) {
174        persistString(ringtoneUri != null ? ringtoneUri.toString() : "");
175    }
176
177    /**
178     * Called when the chooser is about to be shown and the current ringtone
179     * should be marked. Can return null to not mark any ringtone.
180     * <p>
181     * By default, this restores the previous ringtone URI from the persistent
182     * storage.
183     *
184     * @return The ringtone to be marked as the current ringtone.
185     */
186    protected Uri onRestoreRingtone() {
187        final String uriString = getPersistedString(null);
188        return !TextUtils.isEmpty(uriString) ? Uri.parse(uriString) : null;
189    }
190
191    @Override
192    protected Object onGetDefaultValue(TypedArray a, int index) {
193        return a.getString(index);
194    }
195
196    @Override
197    protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValueObj) {
198        String defaultValue = (String) defaultValueObj;
199
200        /*
201         * This method is normally to make sure the internal state and UI
202         * matches either the persisted value or the default value. Since we
203         * don't show the current value in the UI (until the dialog is opened)
204         * and we don't keep local state, if we are restoring the persisted
205         * value we don't need to do anything.
206         */
207        if (restorePersistedValue) {
208            return;
209        }
210
211        // If we are setting to the default value, we should persist it.
212        if (!TextUtils.isEmpty(defaultValue)) {
213            onSaveRingtone(Uri.parse(defaultValue));
214        }
215    }
216
217    @Override
218    protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
219        super.onAttachedToHierarchy(preferenceManager);
220
221        preferenceManager.registerOnActivityResultListener(this);
222        mRequestCode = preferenceManager.getNextRequestCode();
223    }
224
225    public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
226
227        if (requestCode == mRequestCode) {
228
229            if (data != null) {
230                Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
231
232                if (callChangeListener(uri != null ? uri.toString() : "")) {
233                    onSaveRingtone(uri);
234                }
235            }
236
237            return true;
238        }
239
240        return false;
241    }
242
243}
244