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