/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings; import android.content.Context; import android.content.Intent; import android.content.res.TypedArray; import android.media.AudioAttributes; import android.media.RingtoneManager; import android.net.Uri; import android.os.UserHandle; import android.provider.Settings.System; import android.text.TextUtils; import android.util.AttributeSet; import androidx.preference.Preference; import androidx.preference.PreferenceManager; /** * A {@link Preference} that allows the user to choose a ringtone from those on the device. * The chosen ringtone's URI will be persisted as a string. *
* If the user chooses the "Default" item, the saved string will be one of * {@link System#DEFAULT_RINGTONE_URI}, * {@link System#DEFAULT_NOTIFICATION_URI}, or * {@link System#DEFAULT_ALARM_ALERT_URI}. If the user chooses the "Silent" * item, the saved string will be an empty string. * * @attr ref android.R.styleable#RingtonePreference_ringtoneType * @attr ref android.R.styleable#RingtonePreference_showDefault * @attr ref android.R.styleable#RingtonePreference_showSilent * * Based of frameworks/base/core/java/android/preference/RingtonePreference.java * but extends androidx.preference.Preference instead. */ public class RingtonePreference extends Preference { private static final String TAG = "RingtonePreference"; private int mRingtoneType; private boolean mShowDefault; private boolean mShowSilent; private int mRequestCode; protected int mUserId; protected Context mUserContext; public RingtonePreference(Context context, AttributeSet attrs) { super(context, attrs); final TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.RingtonePreference, 0, 0); mRingtoneType = a.getInt(com.android.internal.R.styleable.RingtonePreference_ringtoneType, RingtoneManager.TYPE_RINGTONE); mShowDefault = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showDefault, true); mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent, true); setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER)); setUserId(UserHandle.myUserId()); a.recycle(); } public void setUserId(int userId) { mUserId = userId; mUserContext = Utils.createPackageContextAsUser(getContext(), mUserId); } public int getUserId() { return mUserId; } /** * Returns the sound type(s) that are shown in the picker. * * @return The sound type(s) that are shown in the picker. * @see #setRingtoneType(int) */ public int getRingtoneType() { return mRingtoneType; } /** * Sets the sound type(s) that are shown in the picker. * * @param type The sound type(s) that are shown in the picker. * @see RingtoneManager#EXTRA_RINGTONE_TYPE */ public void setRingtoneType(int type) { mRingtoneType = type; } /** * Returns whether to a show an item for the default sound/ringtone. * * @return Whether to show an item for the default sound/ringtone. */ public boolean getShowDefault() { return mShowDefault; } /** * Sets whether to show an item for the default sound/ringtone. The default * to use will be deduced from the sound type(s) being shown. * * @param showDefault Whether to show the default or not. * @see RingtoneManager#EXTRA_RINGTONE_SHOW_DEFAULT */ public void setShowDefault(boolean showDefault) { mShowDefault = showDefault; } /** * Returns whether to a show an item for 'Silent'. * * @return Whether to show an item for 'Silent'. */ public boolean getShowSilent() { return mShowSilent; } /** * Sets whether to show an item for 'Silent'. * * @param showSilent Whether to show 'Silent'. * @see RingtoneManager#EXTRA_RINGTONE_SHOW_SILENT */ public void setShowSilent(boolean showSilent) { mShowSilent = showSilent; } public int getRequestCode() { return mRequestCode; } /** * Prepares the intent to launch the ringtone picker. This can be modified * to adjust the parameters of the ringtone picker. * * @param ringtonePickerIntent The ringtone picker intent that can be * modified by putting extras. */ public void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent) { ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, onRestoreRingtone()); ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, mShowDefault); if (mShowDefault) { ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(getRingtoneType())); } ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, mShowSilent); ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, mRingtoneType); ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, getTitle()); ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_AUDIO_ATTRIBUTES_FLAGS, AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY); } /** * Called when a ringtone is chosen. *
* By default, this saves the ringtone URI to the persistent storage as a * string. * * @param ringtoneUri The chosen ringtone's {@link Uri}. Can be null. */ protected void onSaveRingtone(Uri ringtoneUri) { persistString(ringtoneUri != null ? ringtoneUri.toString() : ""); } /** * Called when the chooser is about to be shown and the current ringtone * should be marked. Can return null to not mark any ringtone. *
* By default, this restores the previous ringtone URI from the persistent * storage. * * @return The ringtone to be marked as the current ringtone. */ protected Uri onRestoreRingtone() { final String uriString = getPersistedString(null); return !TextUtils.isEmpty(uriString) ? Uri.parse(uriString) : null; } @Override protected Object onGetDefaultValue(TypedArray a, int index) { return a.getString(index); } @Override protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValueObj) { String defaultValue = (String) defaultValueObj; /* * This method is normally to make sure the internal state and UI * matches either the persisted value or the default value. Since we * don't show the current value in the UI (until the dialog is opened) * and we don't keep local state, if we are restoring the persisted * value we don't need to do anything. */ if (restorePersistedValue) { return; } // If we are setting to the default value, we should persist it. if (!TextUtils.isEmpty(defaultValue)) { onSaveRingtone(Uri.parse(defaultValue)); } } protected void onAttachedToHierarchy(PreferenceManager preferenceManager) { super.onAttachedToHierarchy(preferenceManager); } public boolean onActivityResult(int requestCode, int resultCode, Intent data) { if (data != null) { Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI); if (callChangeListener(uri != null ? uri.toString() : "")) { onSaveRingtone(uri); } } return true; } }