blob: a76bb0953cc1818193ac5f607f6966ceef5255fb [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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;
Jean-Michel Trivi02fc19e2015-05-21 11:45:57 -070022import android.media.AudioAttributes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.media.RingtoneManager;
24import android.net.Uri;
25import android.provider.Settings.System;
26import android.text.TextUtils;
27import android.util.AttributeSet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028
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
Patrick Scott3156bb002009-04-13 09:57:38 -070034 * {@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"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037 * 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
Alan Viverette617feb92013-09-09 18:09:13 -070054 public RingtonePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
55 super(context, attrs, defStyleAttr, defStyleRes);
56
57 final TypedArray a = context.obtainStyledAttributes(attrs,
58 com.android.internal.R.styleable.RingtonePreference, defStyleAttr, defStyleRes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059 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
Alan Viverette617feb92013-09-09 18:09:13 -070068 public RingtonePreference(Context context, AttributeSet attrs, int defStyleAttr) {
69 this(context, attrs, defStyleAttr, 0);
70 }
71
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072 public RingtonePreference(Context context, AttributeSet attrs) {
73 this(context, attrs, com.android.internal.R.attr.ringtonePreferenceStyle);
74 }
75
76 public RingtonePreference(Context context) {
77 this(context, null);
78 }
79
80 /**
81 * Returns the sound type(s) that are shown in the picker.
82 *
83 * @return The sound type(s) that are shown in the picker.
84 * @see #setRingtoneType(int)
85 */
86 public int getRingtoneType() {
87 return mRingtoneType;
88 }
89
90 /**
91 * Sets the sound type(s) that are shown in the picker.
92 *
93 * @param type The sound type(s) that are shown in the picker.
94 * @see RingtoneManager#EXTRA_RINGTONE_TYPE
95 */
96 public void setRingtoneType(int type) {
97 mRingtoneType = type;
98 }
99
100 /**
101 * Returns whether to a show an item for the default sound/ringtone.
102 *
103 * @return Whether to show an item for the default sound/ringtone.
104 */
105 public boolean getShowDefault() {
106 return mShowDefault;
107 }
108
109 /**
110 * Sets whether to show an item for the default sound/ringtone. The default
111 * to use will be deduced from the sound type(s) being shown.
112 *
113 * @param showDefault Whether to show the default or not.
114 * @see RingtoneManager#EXTRA_RINGTONE_SHOW_DEFAULT
115 */
116 public void setShowDefault(boolean showDefault) {
117 mShowDefault = showDefault;
118 }
119
120 /**
121 * Returns whether to a show an item for 'Silent'.
122 *
123 * @return Whether to show an item for 'Silent'.
124 */
125 public boolean getShowSilent() {
126 return mShowSilent;
127 }
128
129 /**
130 * Sets whether to show an item for 'Silent'.
131 *
132 * @param showSilent Whether to show 'Silent'.
133 * @see RingtoneManager#EXTRA_RINGTONE_SHOW_SILENT
134 */
135 public void setShowSilent(boolean showSilent) {
136 mShowSilent = showSilent;
137 }
138
139 @Override
140 protected void onClick() {
141 // Launch the ringtone picker
142 Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
143 onPrepareRingtonePickerIntent(intent);
Amith Yamasani82e7bc12010-09-23 15:07:58 -0700144 PreferenceFragment owningFragment = getPreferenceManager().getFragment();
145 if (owningFragment != null) {
146 owningFragment.startActivityForResult(intent, mRequestCode);
147 } else {
148 getPreferenceManager().getActivity().startActivityForResult(intent, mRequestCode);
149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 }
151
152 /**
153 * Prepares the intent to launch the ringtone picker. This can be modified
154 * to adjust the parameters of the ringtone picker.
155 *
156 * @param ringtonePickerIntent The ringtone picker intent that can be
157 * modified by putting extras.
158 */
159 protected void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent) {
160
161 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI,
162 onRestoreRingtone());
163
164 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, mShowDefault);
165 if (mShowDefault) {
166 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI,
167 RingtoneManager.getDefaultUri(getRingtoneType()));
168 }
169
170 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, mShowSilent);
171 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, mRingtoneType);
Amith Yamasani023f8e02011-08-10 16:25:31 -0700172 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, getTitle());
Jean-Michel Trivi02fc19e2015-05-21 11:45:57 -0700173 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_AUDIO_ATTRIBUTES_FLAGS,
174 AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 }
176
177 /**
178 * Called when a ringtone is chosen.
179 * <p>
180 * By default, this saves the ringtone URI to the persistent storage as a
181 * string.
182 *
183 * @param ringtoneUri The chosen ringtone's {@link Uri}. Can be null.
184 */
185 protected void onSaveRingtone(Uri ringtoneUri) {
186 persistString(ringtoneUri != null ? ringtoneUri.toString() : "");
187 }
188
189 /**
190 * Called when the chooser is about to be shown and the current ringtone
191 * should be marked. Can return null to not mark any ringtone.
192 * <p>
193 * By default, this restores the previous ringtone URI from the persistent
194 * storage.
195 *
196 * @return The ringtone to be marked as the current ringtone.
197 */
198 protected Uri onRestoreRingtone() {
199 final String uriString = getPersistedString(null);
200 return !TextUtils.isEmpty(uriString) ? Uri.parse(uriString) : null;
201 }
202
203 @Override
204 protected Object onGetDefaultValue(TypedArray a, int index) {
205 return a.getString(index);
206 }
207
208 @Override
209 protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValueObj) {
210 String defaultValue = (String) defaultValueObj;
211
212 /*
213 * This method is normally to make sure the internal state and UI
214 * matches either the persisted value or the default value. Since we
215 * don't show the current value in the UI (until the dialog is opened)
216 * and we don't keep local state, if we are restoring the persisted
217 * value we don't need to do anything.
218 */
219 if (restorePersistedValue) {
220 return;
221 }
222
223 // If we are setting to the default value, we should persist it.
224 if (!TextUtils.isEmpty(defaultValue)) {
225 onSaveRingtone(Uri.parse(defaultValue));
226 }
227 }
228
229 @Override
230 protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
231 super.onAttachedToHierarchy(preferenceManager);
232
233 preferenceManager.registerOnActivityResultListener(this);
234 mRequestCode = preferenceManager.getNextRequestCode();
235 }
236
237 public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
238
239 if (requestCode == mRequestCode) {
240
241 if (data != null) {
242 Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
243
244 if (callChangeListener(uri != null ? uri.toString() : "")) {
245 onSaveRingtone(uri);
246 }
247 }
248
249 return true;
250 }
251
252 return false;
253 }
254
255}