/ rawフォルダーにサウンドがあり、RingtonePreferenceとまったく同じように、ユーザーがプリファレンスで1つのサウンドを選択できるようにしたいと思いますが、自分のサウンドのみを使用します。
質問する
4337 次
4 に答える
3
それで最後に、ListPreferenceのソースコードを調べて、いくつかの変更を加えて同じようにしました。com.android.internal.R.styleable.ListPreferenceを使用できないため、attrs.xmlで独自のスタイラブルを作成する必要がありました。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ListPreference">
<attr name="entries" format="string"></attr>
<attr name="entryValues" format="string"></attr>
</declare-styleable>
<declare-styleable name="Preference">
<attr name="summary" format="string"></attr>
</declare-styleable>
</resources>
次に、次のように、preferences.xmlファイルにインポートします。
xmlns:foo="http://schemas.android.com/apk/res/com.abe.abemoto"
そしてそれを使用します:
<com.abe.abemoto.preference.CustomSoundListPreference
android:defaultValue="@string/pref_alert_ring_value_1"
android:key="@string/pref_alert_sound_choice_for_notif_key"
android:title="Sonnerie de notification"
foo:entries="@array/pref_alert_ring_entries"
foo:entryValues="@array/pref_alert_ring_values"
foo:summary="Choisissez la sonnerie pour les notifications" />
私のクラスCustomSoundListPreferenceで、クリックされたアイテムでサウンドを再生するようにメソッドonPrepareDialogBuilderを変更しました。
@Override
protected void onPrepareDialogBuilder(Builder builder) {
super.onPrepareDialogBuilder(builder);
mMediaPlayer = new MediaPlayer();
if (mEntries == null || mEntryValues == null) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array.");
}
mClickedDialogEntryIndex = getValueIndex();
builder.setSingleChoiceItems(mEntries, mClickedDialogEntryIndex,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mClickedDialogEntryIndex = which;
String value = mEntryValues[which].toString();
Resources res = getContext().getResources();
int resId = res.getIdentifier(value, "raw",
getContext().getPackageName());
Uri uri = Uri.parse(String.format(getContext()
.getString(R.string.resource_sound),
getContext().getPackageName(), resId));
Log.d(TAG, "uri sound = " + uri);
try {
mMediaPlayer.reset();
mMediaPlayer.setDataSource(getContext(), uri);
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
builder.setPositiveButton("Ok", this);
builder.setNegativeButton("Annuler", this);
}
于 2012-08-05T15:27:00.807 に答える
2
着信音の設定と同様に、カスタム ListPreference の完全なコードを次に示します。
import java.io.IOException;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.ListPreference;
import android.provider.MediaStore;
import android.util.AttributeSet;
import android.util.Log;
public class CustomListPreference extends ListPreference{
private MediaPlayer mMediaPlayer;
private Context mContext;
CharSequence[] mEntries;
CharSequence[] mEntryValues;
private int mClickedDialogEntryIndex;
private String mValue;
public CustomListPreference(Context context) {
super(context);
mContext = context;
}
/**
* Sets the value of the key. This should be one of the entries in
* {@link #getEntryValues()}.
*
* @param value The value to set for the key.
*/
public void setValue(String value) {
mValue = value;
persistString(value);
}
/**
* Sets the value to the given index from the entry values.
*
* @param index The index of the value to set.
*/
public void setValueIndex(int index) {
if (mEntryValues != null) {
setValue(mEntryValues[index].toString());
}
}
/**
* Returns the value of the key. This should be one of the entries in
* {@link #getEntryValues()}.
*
* @return The value of the key.
*/
public String getValue() {
return mValue;
}
/**
* Returns the entry corresponding to the current value.
*
* @return The entry corresponding to the current value, or null.
*/
public CharSequence getEntry() {
int index = getValueIndex();
return index >= 0 && mEntries != null ? mEntries[index] : null;
}
public int findIndexOfValue(String value) {
if (value != null && mEntryValues != null) {
for (int i = mEntryValues.length - 1; i >= 0; i--) {
if (mEntryValues[i].equals(value)) {
return i;
}
}
}
return -1;
}
private int getValueIndex() {
return findIndexOfValue(mValue);
}
@Override
protected void onPrepareDialogBuilder(Builder builder) {
super.onPrepareDialogBuilder(builder);
mMediaPlayer = new MediaPlayer();
mEntries = getEntries();
mEntryValues = getEntryValues();
if (mEntries == null || mEntryValues == null) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array.");
}
mClickedDialogEntryIndex = getValueIndex();
builder.setSingleChoiceItems(mEntries, mClickedDialogEntryIndex,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mClickedDialogEntryIndex = which;
String value = mEntryValues[which].toString();
String path = findPathFromName(value);
try {
playSong(path);
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
builder.setPositiveButton("Ok", this);
builder.setNegativeButton("Cancel", this);
}
private void playSong(String path) throws IllegalArgumentException,
IllegalStateException, IOException {
Log.d("ringtone", "playSong :: " + path);
mMediaPlayer.reset();
mMediaPlayer.setDataSource(path);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_RING);
// mMediaPlayer.setLooping(true);
mMediaPlayer.prepare();
mMediaPlayer.start();
}
public String findPathFromName(String name) {
Cursor mCursor = getContext().getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null,
MediaStore.Audio.Media.TITLE + "='" + name + "'", null, null );
String path = "";
if(mCursor.moveToFirst()){
path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Audio.Media.DATA));
}
mCursor.close();
mCursor = null;
return path;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state == null || !state.getClass().equals(SavedState.class)) {
// Didn't save state for us in onSaveInstanceState
super.onRestoreInstanceState(state);
return;
}
SavedState myState = (SavedState) state;
super.onRestoreInstanceState(myState.getSuperState());
setValue(myState.value);
}
private static class SavedState extends BaseSavedState {
String value;
public SavedState(Parcel source) {
super(source);
value = source.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(value);
}
public SavedState(Parcelable superState) {
super(superState);
}
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult && mClickedDialogEntryIndex >= 0 && mEntryValues != null) {
String value = mEntryValues[mClickedDialogEntryIndex].toString();
if (callChangeListener(value)) {
setValue(value);
}
}
mMediaPlayer.stop();
mMediaPlayer.release();
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return a.getString(index);
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
setValue(restoreValue ? getPersistedString(mValue) : (String) defaultValue);
}
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
if (isPersistent()) {
// No need to save instance state since it's persistent
return superState;
}
final SavedState myState = new SavedState(superState);
myState.value = getValue();
return myState;
}
}
これが誰かに役立つことを願っています。
于 2013-02-27T12:47:02.210 に答える