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