VolumeSeekBarPreference.java revision cb9f35171d14bec1af4bb313aac2e79ac2290fac
181bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock/*
281bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock * Copyright (C) 2014 The Android Open Source Project
381bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock *
481bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock * Licensed under the Apache License, Version 2.0 (the "License");
581bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock * you may not use this file except in compliance with the License.
681bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock * You may obtain a copy of the License at
781bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock *
881bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock *      http://www.apache.org/licenses/LICENSE-2.0
981bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock *
1081bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock * Unless required by applicable law or agreed to in writing, software
1181bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock * distributed under the License is distributed on an "AS IS" BASIS,
1281bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1381bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock * See the License for the specific language governing permissions and
1481bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock * limitations under the License.
1581bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock */
1681bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock
1781bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockpackage com.android.settings.notification;
1881bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock
1981bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockimport android.content.ContentResolver;
2081bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockimport android.content.Context;
2181bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockimport android.media.AudioManager;
2281bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockimport android.net.Uri;
2381bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockimport android.preference.PreferenceManager;
2481bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockimport android.preference.SeekBarPreference;
2581bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockimport android.preference.SeekBarVolumizer;
2681bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockimport android.util.AttributeSet;
2781bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockimport android.util.Log;
2881bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockimport android.view.View;
29cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandlerimport android.widget.ImageView;
3081bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockimport android.widget.SeekBar;
3181bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock
3281bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockimport com.android.settings.R;
3381bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock
3481bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock/** A slider preference that directly controls an audio stream volume (no dialog) **/
3581bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlockpublic class VolumeSeekBarPreference extends SeekBarPreference
3681bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        implements PreferenceManager.OnActivityStopListener {
3781bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    private static final String TAG = "VolumeSeekBarPreference";
3881bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock
3981bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    private int mStream;
4081bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    private SeekBar mSeekBar;
4181bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    private SeekBarVolumizer mVolumizer;
4281bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    private Callback mCallback;
43cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler    private ImageView mIconView;
4481bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock
45dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio    public VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
46dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio            int defStyleRes) {
47dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio        super(context, attrs, defStyleAttr, defStyleRes);
48dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio    }
49dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio
50dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio    public VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
51dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio        this(context, attrs, defStyleAttr, 0);
52dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio    }
53dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio
5481bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    public VolumeSeekBarPreference(Context context, AttributeSet attrs) {
55dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio        this(context, attrs, 0);
56dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio    }
57dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio
58dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio    public VolumeSeekBarPreference(Context context) {
59dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio        this(context, null);
6081bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    }
6181bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock
6281bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    public void setStream(int stream) {
6381bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        mStream = stream;
6481bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    }
6581bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock
6681bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    public void setCallback(Callback callback) {
6781bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        mCallback = callback;
6881bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    }
6981bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock
7081bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    @Override
7181bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    public void onActivityStop() {
7281bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        if (mVolumizer != null) {
7381bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock            mVolumizer.stop();
7481bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        }
7581bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    }
7681bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock
7781bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    @Override
7881bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    protected void onBindView(View view) {
7981bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        super.onBindView(view);
8081bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        if (mStream == 0) {
8181bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock            Log.w(TAG, "No stream found, not binding volumizer");
8281bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock            return;
8381bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        }
8481bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        getPreferenceManager().registerOnActivityStopListener(this);
8581bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        final SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
8681bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        if (seekBar == mSeekBar) return;
8781bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        mSeekBar = seekBar;
8881bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        final SeekBarVolumizer.Callback sbvc = new SeekBarVolumizer.Callback() {
8981bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock            @Override
9081bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock            public void onSampleStarting(SeekBarVolumizer sbv) {
9181bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock                if (mCallback != null) {
9281bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock                    mCallback.onSampleStarting(sbv);
9381bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock                }
9481bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock            }
9581bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        };
9681bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        final Uri sampleUri = mStream == AudioManager.STREAM_MUSIC ? getMediaVolumeUri() : null;
9785315533a19aa61a0c5fc27d3f783c3f21e3878fJohn Spurlock        if (mVolumizer == null) {
98cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler            mVolumizer = new SeekBarVolumizer(getContext(), mStream, sampleUri, sbvc) {
99cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler                // we need to piggyback on SBV's SeekBar listener to update our icon
100cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler                @Override
101cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler                public void onProgressChanged(SeekBar seekBar, int progress,
102cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler                        boolean fromTouch) {
103cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler                    super.onProgressChanged(seekBar, progress, fromTouch);
104cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler                    mCallback.onStreamValueChanged(mStream, progress);
105cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler                }
106cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler            };
10785315533a19aa61a0c5fc27d3f783c3f21e3878fJohn Spurlock        }
10885315533a19aa61a0c5fc27d3f783c3f21e3878fJohn Spurlock        mVolumizer.setSeekBar(mSeekBar);
109cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler        mIconView = (ImageView) view.findViewById(com.android.internal.R.id.icon);
110cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler        mCallback.onStreamValueChanged(mStream, mSeekBar.getProgress());
111cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler    }
112cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler
113cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler    // during initialization, this preference is the SeekBar listener
114cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler    @Override
115cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler    public void onProgressChanged(SeekBar seekBar, int progress,
116cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler            boolean fromTouch) {
117cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler        super.onProgressChanged(seekBar, progress, fromTouch);
118cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler        mCallback.onStreamValueChanged(mStream, progress);
119cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler    }
120cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler
121cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler    public void showIcon(int resId) {
122cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler        // Instead of using setIcon, which will trigger listeners, this just decorates the
123cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler        // preference temporarily with a new icon.
124cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler        if (mIconView != null) {
125cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler            mIconView.setImageResource(resId);
126cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler        }
12781bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    }
12881bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock
12981bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    private Uri getMediaVolumeUri() {
13081bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
131dbaf080f44c72dcd08136c8b026c782696102df6Fabrice Di Meglio                + getContext().getPackageName()
13281bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock                + "/" + R.raw.media_volume);
13381bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    }
13481bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock
13581bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    public interface Callback {
13681bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock        void onSampleStarting(SeekBarVolumizer sbv);
137cb9f35171d14bec1af4bb313aac2e79ac2290facDan Sandler        void onStreamValueChanged(int stream, int progress);
13881bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock    }
13981bef1d74568d623b9db3c5409740dc21c0bbc08John Spurlock}
140