• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.notification;
18 
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.media.AudioManager;
22 import android.net.Uri;
23 import android.preference.PreferenceManager;
24 import android.preference.SeekBarPreference;
25 import android.preference.SeekBarVolumizer;
26 import android.text.TextUtils;
27 import android.util.AttributeSet;
28 import android.util.Log;
29 import android.view.View;
30 import android.widget.ImageView;
31 import android.widget.SeekBar;
32 import android.widget.TextView;
33 
34 import com.android.settings.R;
35 
36 import java.util.Objects;
37 
38 /** A slider preference that directly controls an audio stream volume (no dialog) **/
39 public class VolumeSeekBarPreference extends SeekBarPreference
40         implements PreferenceManager.OnActivityStopListener {
41     private static final String TAG = "VolumeSeekBarPreference";
42 
43     private int mStream;
44     private SeekBar mSeekBar;
45     private SeekBarVolumizer mVolumizer;
46     private Callback mCallback;
47     private ImageView mIconView;
48     private TextView mSuppressionTextView;
49     private String mSuppressionText;
50     private boolean mMuted;
51     private boolean mZenMuted;
52     private int mIconResId;
53     private int mMuteIconResId;
54     private boolean mStopped;
55 
VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)56     public VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
57             int defStyleRes) {
58         super(context, attrs, defStyleAttr, defStyleRes);
59         setLayoutResource(R.layout.preference_volume_slider);
60     }
61 
VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr)62     public VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
63         this(context, attrs, defStyleAttr, 0);
64     }
65 
VolumeSeekBarPreference(Context context, AttributeSet attrs)66     public VolumeSeekBarPreference(Context context, AttributeSet attrs) {
67         this(context, attrs, 0);
68     }
69 
VolumeSeekBarPreference(Context context)70     public VolumeSeekBarPreference(Context context) {
71         this(context, null);
72     }
73 
setStream(int stream)74     public void setStream(int stream) {
75         mStream = stream;
76     }
77 
setCallback(Callback callback)78     public void setCallback(Callback callback) {
79         mCallback = callback;
80     }
81 
onActivityResume()82     public void onActivityResume() {
83         if (mStopped) {
84             init();
85         }
86     }
87 
88     @Override
onActivityStop()89     public void onActivityStop() {
90         mStopped = true;
91         if (mVolumizer != null) {
92             mVolumizer.stop();
93         }
94     }
95 
96     @Override
onBindView(View view)97     protected void onBindView(View view) {
98         super.onBindView(view);
99         if (mStream == 0) {
100             Log.w(TAG, "No stream found, not binding volumizer");
101             return;
102         }
103         mSeekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
104         mIconView = (ImageView) view.findViewById(com.android.internal.R.id.icon);
105         mSuppressionTextView = (TextView) view.findViewById(R.id.suppression_text);
106         init();
107     }
108 
init()109     private void init() {
110         if (mSeekBar == null) return;
111         getPreferenceManager().registerOnActivityStopListener(this);
112         final SeekBarVolumizer.Callback sbvc = new SeekBarVolumizer.Callback() {
113             @Override
114             public void onSampleStarting(SeekBarVolumizer sbv) {
115                 if (mCallback != null) {
116                     mCallback.onSampleStarting(sbv);
117                 }
118             }
119             @Override
120             public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
121                 if (mCallback != null) {
122                     mCallback.onStreamValueChanged(mStream, progress);
123                 }
124             }
125             @Override
126             public void onMuted(boolean muted, boolean zenMuted) {
127                 if (mMuted == muted && mZenMuted == zenMuted) return;
128                 mMuted = muted;
129                 mZenMuted = zenMuted;
130                 updateIconView();
131             }
132         };
133         final Uri sampleUri = mStream == AudioManager.STREAM_MUSIC ? getMediaVolumeUri() : null;
134         if (mVolumizer == null) {
135             mVolumizer = new SeekBarVolumizer(getContext(), mStream, sampleUri, sbvc);
136         }
137         mVolumizer.start();
138         mVolumizer.setSeekBar(mSeekBar);
139         updateIconView();
140         mCallback.onStreamValueChanged(mStream, mSeekBar.getProgress());
141         updateSuppressionText();
142         if (!isEnabled()) {
143             mSeekBar.setEnabled(false);
144             mVolumizer.stop();
145         }
146     }
147 
148     // during initialization, this preference is the SeekBar listener
149     @Override
onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch)150     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
151         super.onProgressChanged(seekBar, progress, fromTouch);
152         mCallback.onStreamValueChanged(mStream, progress);
153     }
154 
updateIconView()155     private void updateIconView() {
156         if (mIconView == null) return;
157         if (mIconResId != 0) {
158             mIconView.setImageResource(mIconResId);
159         } else if (mMuteIconResId != 0 && mMuted && !mZenMuted) {
160             mIconView.setImageResource(mMuteIconResId);
161         } else {
162             mIconView.setImageDrawable(getIcon());
163         }
164     }
165 
showIcon(int resId)166     public void showIcon(int resId) {
167         // Instead of using setIcon, which will trigger listeners, this just decorates the
168         // preference temporarily with a new icon.
169         if (mIconResId == resId) return;
170         mIconResId = resId;
171         updateIconView();
172     }
173 
setMuteIcon(int resId)174     public void setMuteIcon(int resId) {
175         if (mMuteIconResId == resId) return;
176         mMuteIconResId = resId;
177         updateIconView();
178     }
179 
getMediaVolumeUri()180     private Uri getMediaVolumeUri() {
181         return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
182                 + getContext().getPackageName()
183                 + "/" + R.raw.media_volume);
184     }
185 
setSuppressionText(String text)186     public void setSuppressionText(String text) {
187         if (Objects.equals(text, mSuppressionText)) return;
188         mSuppressionText = text;
189         updateSuppressionText();
190     }
191 
updateSuppressionText()192     private void updateSuppressionText() {
193         if (mSuppressionTextView != null && mSeekBar != null) {
194             mSuppressionTextView.setText(mSuppressionText);
195             final boolean showSuppression = !TextUtils.isEmpty(mSuppressionText);
196             mSuppressionTextView.setVisibility(showSuppression ? View.VISIBLE : View.INVISIBLE);
197             mSeekBar.setVisibility(showSuppression ? View.INVISIBLE : View.VISIBLE);
198         }
199     }
200 
201     public interface Callback {
onSampleStarting(SeekBarVolumizer sbv)202         void onSampleStarting(SeekBarVolumizer sbv);
onStreamValueChanged(int stream, int progress)203         void onStreamValueChanged(int stream, int progress);
204     }
205 }
206