Home | History | Annotate | Download | only in preference
      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.AudioAttributes;
     23 import android.media.RingtoneManager;
     24 import android.net.Uri;
     25 import android.provider.Settings.System;
     26 import android.text.TextUtils;
     27 import android.util.AttributeSet;
     28 
     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
     34  * {@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"
     37  * 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  */
     43 public 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 
     54     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);
     59         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 
     68     public RingtonePreference(Context context, AttributeSet attrs, int defStyleAttr) {
     69         this(context, attrs, defStyleAttr, 0);
     70     }
     71 
     72     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);
    144         PreferenceFragment owningFragment = getPreferenceManager().getFragment();
    145         if (owningFragment != null) {
    146             owningFragment.startActivityForResult(intent, mRequestCode);
    147         } else {
    148             getPreferenceManager().getActivity().startActivityForResult(intent, mRequestCode);
    149         }
    150     }
    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);
    172         ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, getTitle());
    173         ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_AUDIO_ATTRIBUTES_FLAGS,
    174                 AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY);
    175     }
    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 }
    256