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