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