我有这个RingtonePreference(来自Android Studio的默认设置活动):
pref_notification.xml:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<RingtonePreference
android:dependency="notifications_alarm"
android:key="notifications_alarm_ringtone"
android:title="@string/pref_title_ringtone"
android:ringtoneType="notification|all"
android:defaultValue="content://settings/system/notification_sound" />
SettingsActivity.java:
private void setupSimplePreferencesScreen() {
if (!isSimplePreferences(this)) {
return;
}
// Add 'general' preferences.
addPreferencesFromResource(R.xml.pref_general);
// Add 'notifications' preferences, and a corresponding header.
PreferenceCategory fakeHeader = new PreferenceCategory(this);
fakeHeader.setTitle(R.string.pref_header_notifications);
getPreferenceScreen().addPreference(fakeHeader);
addPreferencesFromResource(R.xml.pref_notification);
bindPreferenceSummaryToValue(findPreference("notifications_alarm_ringtone"));
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class NotificationPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_notification);
bindPreferenceSummaryToValue(findPreference("notifications_alarm_ringtone"));
}
}
我想将我的应用程序的自定义铃声从res / raw文件夹添加到列表中。 (我不需要它们可用于其他应用。)
答案 0 :(得分:6)
选项1:复制到设备存储空间
将铃声文件复制到设备的存储空间。我基本上为GitHub上的一个应用程序here做了这个,在那里我将警报音从原始资源复制到设备的警报目录(你需要替换&#34;的所有实例;闹钟和#34;铃声&#34;)。然后我们使用ContentValues
创建元数据,告诉系统文件是铃声,然后使用MediaStore.Audio.Media.getContentUriForPath
然后context.getContentResolver().insert(contentUri, contentValues)
将铃声添加到设备的数据库中,这样他们就可以#39} ;将包含在RingtonePreference
列表中。
您也可以使用RingtoneManager.setActualDefaultRingtoneUri()
将铃声设置为默认铃声,但您需要WRITE_SETTINGS
权限。
另外,请记住在调用getContentUriForPath()
和getContentResolver().insert()
时使用从RingtoneManager.setActualDefaultRingtoneUri()
获得的URI。
并且,请确保添加到AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
选项2:自定义偏好
创建自定义首选项,如this guide所示,或者您可以使用(或子类)ListPreference。您需要使用RingtoneManager.getCursor()
(docs)检索所有设备的铃声并将其添加到列表中,并同时包含您的自定义铃声。
然后,在您的preferences.xml文件中,您将使用
而不是RingtonePreference<com.yourapp.CustomPreference android:key="your_key"
...
在您的情况下,如果其他应用也可以访问铃声也可以,我建议使用第一种方法,因为一般来说我觉得最好不要复制已经由系统提供的功能,因为它最好利用用户已经熟悉的内容。
答案 1 :(得分:3)
最后,我根据这个答案制作了自己的ExtraRingtonePreference:In preferences, select my sound just like with RingtonePreference
我会在此处加入以供将来参考:
的src /主/ JAVA / COM / fletech /机器人/偏好/ ExtraRingtonePreference.java:
package com.fletech.android.preference;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import com.fletech.android.redalert.R;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
public class ExtraRingtonePreference extends DialogPreference {
private Context mContext;
private String mValue;
private Ringtone ringtone;
private int mRingtoneType;
private boolean mShowSilent;
private boolean mShowDefault;
private CharSequence[] mExtraRingtones;
private CharSequence[] mExtraRingtoneTitles;
public ExtraRingtonePreference(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ExtraRingtonePreference, 0, 0);
mRingtoneType = a.getInt(R.styleable.ExtraRingtonePreference_ringtoneType, RingtoneManager.TYPE_RINGTONE);
mShowDefault = a.getBoolean(R.styleable.ExtraRingtonePreference_showDefault, true);
mShowSilent = a.getBoolean(R.styleable.ExtraRingtonePreference_showSilent, true);
mExtraRingtones = a.getTextArray(R.styleable.ExtraRingtonePreference_extraRingtones);
mExtraRingtoneTitles = a.getTextArray(R.styleable.ExtraRingtonePreference_extraRingtoneTitles);
a.recycle();
}
public ExtraRingtonePreference(Context context) {
this(context, null);
}
public String getValue() {
return mValue;
}
private Map<String, Uri> getSounds(int type) {
RingtoneManager ringtoneManager = new RingtoneManager(mContext);
ringtoneManager.setType(type);
Cursor cursor = ringtoneManager.getCursor();
Map<String, Uri> list = new TreeMap<String, Uri>();
while (cursor.moveToNext()) {
String notificationTitle = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX);
Uri notificationUri = ringtoneManager.getRingtoneUri(cursor.getPosition());
list.put(notificationTitle, notificationUri);
}
return list;
}
private Uri uriFromRaw(String name) {
int resId = mContext.getResources().getIdentifier(name, "raw", mContext.getPackageName());
return Uri.parse("android.resource://" + mContext.getPackageName() + "/" + resId);
}
public String getExtraRingtoneTitle(CharSequence name) {
if (mExtraRingtones != null && mExtraRingtoneTitles != null) {
int index = Arrays.asList(mExtraRingtones).indexOf(name);
return mExtraRingtoneTitles[index].toString();
}
return null;
}
@Override
public CharSequence getSummary() {
String ringtoneTitle = null;
if (mValue != null) {
if (mValue.length() == 0)
ringtoneTitle = mContext.getString(R.string.silent);
Uri mValueUri = Uri.parse(mValue);
if (ringtoneTitle == null && mExtraRingtones != null && mExtraRingtoneTitles != null) {
for (int i = 0; i < mExtraRingtones.length; i++) {
Uri uriExtra = uriFromRaw(mExtraRingtones[i].toString());
if (uriExtra.equals(mValueUri)) {
ringtoneTitle = mExtraRingtoneTitles[i].toString();
break;
}
}
}
if (ringtoneTitle == null) {
Ringtone ringtone = RingtoneManager.getRingtone(mContext, mValueUri);
if (ringtone != null) {
String title = ringtone.getTitle(mContext);
if (title != null && title.length() > 0) {
ringtoneTitle = title;
}
}
}
}
CharSequence summary = super.getSummary();
if (ringtoneTitle != null) {
// if (summary != null)
// return String.format(summary.toString(), ringtoneTitle);
// else
return ringtoneTitle;
} else return summary;
}
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
final Map<String, Uri> sounds = new LinkedHashMap<String, Uri>();
if (mExtraRingtones != null) {
for (CharSequence extraRingtone : mExtraRingtones) {
Uri uri = uriFromRaw(extraRingtone.toString());
String title = getExtraRingtoneTitle(extraRingtone);
sounds.put(title, uri);
}
}
if (mShowSilent)
sounds.put(mContext.getString(R.string.silent), Uri.parse(""));
if (mShowDefault) {
Uri uriDefault = RingtoneManager.getDefaultUri(mRingtoneType);
if (uriDefault != null) {
Ringtone ringtoneDefault = RingtoneManager.getRingtone(mContext, uriDefault);
if (ringtoneDefault != null) {
sounds.put(ringtoneDefault.getTitle(mContext), uriDefault);
}
}
}
sounds.putAll(getSounds(mRingtoneType));
final String[] titleArray = sounds.keySet().toArray(new String[0]);
final Uri[] uriArray = sounds.values().toArray(new Uri[0]);
int index = mValue != null ? Arrays.asList(uriArray).indexOf(Uri.parse(mValue)) : -1;
builder.setSingleChoiceItems(titleArray, index, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (ringtone != null)
ringtone.stop();
Uri uri = uriArray[which];
if (uri != null) {
if (uri.toString().length() > 0) {
ringtone = RingtoneManager.getRingtone(mContext, uri);
if (ringtone != null) {
ringtone.play();
}
}
mValue = uri.toString();
} else mValue = null;
}
});
builder.setPositiveButton(R.string.dialog_save, this);
builder.setNegativeButton(R.string.dialog_cancel, this);
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (ringtone != null)
ringtone.stop();
if (positiveResult && callChangeListener(mValue)) {
persistString(mValue);
notifyChanged();
}
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return a.getString(index);
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
if (restoreValue) {
mValue = getPersistedString("");
} else {
if (mExtraRingtones != null && defaultValue != null && defaultValue.toString().length() > 0) {
int index = Arrays.asList(mExtraRingtones).indexOf((CharSequence) defaultValue);
if (index >= 0) {
mValue = uriFromRaw(defaultValue.toString()).toString();
} else {
mValue = (String)defaultValue;
}
} else {
mValue = (String)defaultValue;
}
persistString(mValue);
}
}
}
的src /主/ RES / values.attrs.xml:
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<declare-styleable name="ExtraRingtonePreference">
<attr name="ringtoneType"><!-- Should correspond to RingtoneManager -->
<!-- TYPE_RINGTONE: Ringtones. -->
<flag name="ringtone" value="1" />
<!-- TYPE_NOTIFICATION: Notification sounds. -->
<flag name="notification" value="2" />
<!-- TYPE_ALARM: Alarm sounds. -->
<flag name="alarm" value="4" />
<!-- TYPE_ALL: All available ringtone sounds. -->
<flag name="all" value="7" />
</attr>
<attr name="showSilent" format="boolean"/>
<attr name="showDefault" format="boolean"/>
<attr name="extraRingtones" format="reference"/>
<attr name="extraRingtoneTitles" format="reference"/>
</declare-styleable>
</resources>
的src / RES /值/ ringtone_preference_strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ringtone_title">Ringtone</string>
<string name="silent">Silent</string>
<string name="dialog_save">Save</string>
<string name="dialog_cancel">Cancel</string>
<string-array name="extra_ringtones">
<item>beep</item>
<item>beep_beep</item>
<item>default</item>
<item>test</item>
</string-array>
<string-array name="extra_ringtone_titles">
<item>Beep</item>
<item>Beep-Beep</item>
<item>Default</item>
<item>Test</item>
</string-array>
</resources>
以及src / main / res / xml / pref_alarm.xml中的用法:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:auto="http://schemas.android.com/apk/res-auto">
<com.fletech.android.preference.ExtraRingtonePreference
android:key="notifications_alarm_ringtone"
android:title="@string/ringtone_title"
android:defaultValue="default"
auto:ringtoneType="alarm"
auto:showSilent="true"
auto:showDefault="true"
auto:extraRingtones="@array/extra_ringtones"
auto:extraRingtoneTitles="@array/extra_ringtone_titles"/>
</PreferenceScreen>