blob: cd751cdedd58290a51f692590710d7b0879d8160 [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
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +010019import android.annotation.UnsupportedAppUsage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.content.Context;
21import android.content.Intent;
22import android.content.res.TypedArray;
Jean-Michel Trivi02fc19e2015-05-21 11:45:57 -070023import android.media.AudioAttributes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.media.RingtoneManager;
25import android.net.Uri;
26import android.provider.Settings.System;
27import android.text.TextUtils;
28import android.util.AttributeSet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
30/**
31 * A {@link Preference} that allows the user to choose a ringtone from those on the device.
32 * The chosen ringtone's URI will be persisted as a string.
33 * <p>
34 * If the user chooses the "Default" item, the saved string will be one of
Patrick Scott3156bb002009-04-13 09:57:38 -070035 * {@link System#DEFAULT_RINGTONE_URI},
36 * {@link System#DEFAULT_NOTIFICATION_URI}, or
37 * {@link System#DEFAULT_ALARM_ALERT_URI}. If the user chooses the "Silent"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038 * item, the saved string will be an empty string.
39 *
40 * @attr ref android.R.styleable#RingtonePreference_ringtoneType
41 * @attr ref android.R.styleable#RingtonePreference_showDefault
42 * @attr ref android.R.styleable#RingtonePreference_showSilent
43 */
44public class RingtonePreference extends Preference implements
45 PreferenceManager.OnActivityResultListener {
46
47 private static final String TAG = "RingtonePreference";
48
49 private int mRingtoneType;
50 private boolean mShowDefault;
51 private boolean mShowSilent;
52
Mathew Inwoodeac8d0a2018-08-17 13:51:26 +010053 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054 private int mRequestCode;
55
Alan Viverette617feb92013-09-09 18:09:13 -070056 public RingtonePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
57 super(context, attrs, defStyleAttr, defStyleRes);
58
59 final TypedArray a = context.obtainStyledAttributes(attrs,
60 com.android.internal.R.styleable.RingtonePreference, defStyleAttr, defStyleRes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 mRingtoneType = a.getInt(com.android.internal.R.styleable.RingtonePreference_ringtoneType,
62 RingtoneManager.TYPE_RINGTONE);
63 mShowDefault = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showDefault,
64 true);
65 mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent,
66 true);
67 a.recycle();
68 }
69
Alan Viverette617feb92013-09-09 18:09:13 -070070 public RingtonePreference(Context context, AttributeSet attrs, int defStyleAttr) {
71 this(context, attrs, defStyleAttr, 0);
72 }
73
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074 public RingtonePreference(Context context, AttributeSet attrs) {
75 this(context, attrs, com.android.internal.R.attr.ringtonePreferenceStyle);
76 }
77
78 public RingtonePreference(Context context) {
79 this(context, null);
80 }
81
82 /**
83 * Returns the sound type(s) that are shown in the picker.
84 *
85 * @return The sound type(s) that are shown in the picker.
86 * @see #setRingtoneType(int)
87 */
88 public int getRingtoneType() {
89 return mRingtoneType;
90 }
91
92 /**
93 * Sets the sound type(s) that are shown in the picker.
94 *
95 * @param type The sound type(s) that are shown in the picker.
96 * @see RingtoneManager#EXTRA_RINGTONE_TYPE
97 */
98 public void setRingtoneType(int type) {
99 mRingtoneType = type;
100 }
101
102 /**
103 * Returns whether to a show an item for the default sound/ringtone.
104 *
105 * @return Whether to show an item for the default sound/ringtone.
106 */
107 public boolean getShowDefault() {
108 return mShowDefault;
109 }
110
111 /**
112 * Sets whether to show an item for the default sound/ringtone. The default
113 * to use will be deduced from the sound type(s) being shown.
114 *
115 * @param showDefault Whether to show the default or not.
116 * @see RingtoneManager#EXTRA_RINGTONE_SHOW_DEFAULT
117 */
118 public void setShowDefault(boolean showDefault) {
119 mShowDefault = showDefault;
120 }
121
122 /**
123 * Returns whether to a show an item for 'Silent'.
124 *
125 * @return Whether to show an item for 'Silent'.
126 */
127 public boolean getShowSilent() {
128 return mShowSilent;
129 }
130
131 /**
132 * Sets whether to show an item for 'Silent'.
133 *
134 * @param showSilent Whether to show 'Silent'.
135 * @see RingtoneManager#EXTRA_RINGTONE_SHOW_SILENT
136 */
137 public void setShowSilent(boolean showSilent) {
138 mShowSilent = showSilent;
139 }
140
141 @Override
142 protected void onClick() {
143 // Launch the ringtone picker
144 Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
145 onPrepareRingtonePickerIntent(intent);
Amith Yamasani82e7bc12010-09-23 15:07:58 -0700146 PreferenceFragment owningFragment = getPreferenceManager().getFragment();
147 if (owningFragment != null) {
148 owningFragment.startActivityForResult(intent, mRequestCode);
149 } else {
150 getPreferenceManager().getActivity().startActivityForResult(intent, mRequestCode);
151 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 }
153
154 /**
155 * Prepares the intent to launch the ringtone picker. This can be modified
156 * to adjust the parameters of the ringtone picker.
157 *
158 * @param ringtonePickerIntent The ringtone picker intent that can be
159 * modified by putting extras.
160 */
161 protected void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent) {
162
163 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI,
164 onRestoreRingtone());
165
166 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, mShowDefault);
167 if (mShowDefault) {
168 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI,
169 RingtoneManager.getDefaultUri(getRingtoneType()));
170 }
171
172 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, mShowSilent);
173 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, mRingtoneType);
Amith Yamasani023f8e02011-08-10 16:25:31 -0700174 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, getTitle());
Jean-Michel Trivi02fc19e2015-05-21 11:45:57 -0700175 ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_AUDIO_ATTRIBUTES_FLAGS,
176 AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177 }
178
179 /**
180 * Called when a ringtone is chosen.
181 * <p>
182 * By default, this saves the ringtone URI to the persistent storage as a
183 * string.
184 *
185 * @param ringtoneUri The chosen ringtone's {@link Uri}. Can be null.
186 */
187 protected void onSaveRingtone(Uri ringtoneUri) {
188 persistString(ringtoneUri != null ? ringtoneUri.toString() : "");
189 }
190
191 /**
192 * Called when the chooser is about to be shown and the current ringtone
193 * should be marked. Can return null to not mark any ringtone.
194 * <p>
195 * By default, this restores the previous ringtone URI from the persistent
196 * storage.
197 *
198 * @return The ringtone to be marked as the current ringtone.
199 */
200 protected Uri onRestoreRingtone() {
201 final String uriString = getPersistedString(null);
202 return !TextUtils.isEmpty(uriString) ? Uri.parse(uriString) : null;
203 }
204
205 @Override
206 protected Object onGetDefaultValue(TypedArray a, int index) {
207 return a.getString(index);
208 }
209
210 @Override
211 protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValueObj) {
212 String defaultValue = (String) defaultValueObj;
213
214 /*
215 * This method is normally to make sure the internal state and UI
216 * matches either the persisted value or the default value. Since we
217 * don't show the current value in the UI (until the dialog is opened)
218 * and we don't keep local state, if we are restoring the persisted
219 * value we don't need to do anything.
220 */
221 if (restorePersistedValue) {
222 return;
223 }
224
225 // If we are setting to the default value, we should persist it.
226 if (!TextUtils.isEmpty(defaultValue)) {
227 onSaveRingtone(Uri.parse(defaultValue));
228 }
229 }
230
231 @Override
232 protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
233 super.onAttachedToHierarchy(preferenceManager);
234
235 preferenceManager.registerOnActivityResultListener(this);
236 mRequestCode = preferenceManager.getNextRequestCode();
237 }
238
239 public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
240
241 if (requestCode == mRequestCode) {
242
243 if (data != null) {
244 Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
245
246 if (callChangeListener(uri != null ? uri.toString() : "")) {
247 onSaveRingtone(uri);
248 }
249 }
250
251 return true;
252 }
253
254 return false;
255 }
256
257}