SeekBar で音量調節な設定ダイアログを作った件

作った、とは言え某所で発見した実装のパクリですが。
要件としては

  • 音量調節したい
  • 音出しながら具合を確認したい

とのこと。
実装をでっちあげて commit 作った後に気づいたのですが dialog の外をタッチすると dialog が終了します。これはアレだな、と思いつつも setCanceledOnTouchOutside なメソドを呼び出す場所が分からない。むむむ、と言いつつ Google 先生に聞いて以下を発見。

やれやれ、と言いつつ以下を追加させて頂いて事無きを得ております。

    @Override
    protected void onPrepareDialogBuilder(Builder builder) {
        super.onPrepareDialogBuilder(builder);
        builder.setCancelable(false);
    }

それにしてもボタンを押してサンプル音源を鳴らしつつ

            mBgmPlayer = MediaPlayer.create(mContext, R.raw.sample_audio);
            mBgmPlayer.setLooping(true);
            mBgmPlayer.start();

SeekBar で音量変わるとなかなかに違う意味での効果がアレですね (何
とりあえず参考まで、ソース全部以下に晒しておきます。

package jp.shuri.android.yamanetoshi;

import java.io.IOException;

import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.preference.DialogPreference;
import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;

public class VolumePrefDialog extends DialogPreference 
    implements SeekBar.OnSeekBarChangeListener {
    
    private String TAG = "VolumePrefDialog";
    
    private static SharedPreferences sp;
    private AudioManager am;
    private SeekBar mSeekBar;
    private Button mButton;
    
    private boolean isPlaying;
    private MediaPlayer mBgmPlayer;
    
    private Context mContext;

    public VolumePrefDialog(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        sp = PreferenceManager.getDefaultSharedPreferences(context);
        am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
        
        isPlaying = false;

        setDialogLayoutResource(R.layout.preferences_layout);
    }

    @Override
    protected void onPrepareDialogBuilder(Builder builder) {
        super.onPrepareDialogBuilder(builder);
        builder.setCancelable(false);
    }

    @Override
    protected void onBindDialogView(View view) {
        super.onBindDialogView(view);
        
        mSeekBar = (SeekBar)view.findViewById(R.id.prefVolSeekBar);
        mSeekBar.setOnSeekBarChangeListener(this);
        mSeekBar.setProgress(getVal());

        mButton = (Button)view.findViewById(R.id.prefButton);
        mButton.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
                Log.d(TAG, "button clicked");
                Log.d(TAG, "value : " + getVal());
                if (isPlaying) {
                    isPlaying = false;
                    mBgmPlayer.stop();
                    try {
                        mBgmPlayer.prepare();
                    } catch (IllegalStateException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } else {
                    isPlaying = true;
                    mBgmPlayer = MediaPlayer.create(mContext, R.raw.sample_audio);
                    mBgmPlayer.setLooping(true);
                    mBgmPlayer.start();
                }
            }
        });
    }
    
    @Override
    protected void onDialogClosed(boolean positiveResult) {
        if (positiveResult) {
            setVal(mSeekBar.getProgress());
        }

        if (isPlaying) {
            isPlaying = false;
            mBgmPlayer.stop();
            try {
                mBgmPlayer.prepare();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onProgressChanged(SeekBar arg0, int progress, boolean arg2) {
        am.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0);
    }

    @Override
    public void onStartTrackingTouch(SeekBar arg0) {
        
    }

    @Override
    public void onStopTrackingTouch(SeekBar arg0) {
        
    }

    private void setVal(int value) {
        Editor e = sp.edit();
        e.putInt(getKey(), value);
        e.commit();
    }
    
    private int getVal() {
        return sp.getInt(getKey(), 0);
    }

}

res/xml/ 配下の xml の一部が以下な形です。

        <jp.shuri.yamanetoshi.VolumePrefDialog
            android:selectable="true"
             android:enabled="true"
             android:title="音量設定"
             android:key="pref_volume">
        </jp.shuri.yamanetoshi.VolumePrefDialog>

あ、参考にさせて頂いたのは以下です。感謝を込めて。