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