资源简介

修复了Settings中音量设置的音量条存在回弹、显示的位置和实际数值不一致等问题。

资源截图

代码片段和文件信息

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License Version 2.0 (the “License“);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing software
 * distributed under the License is distributed on an “AS IS“ BASIS
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.preference;

import android.annotation.UnsupportedAppUsage;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.preference.VolumePreference.VolumeStore;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.provider.Settings.System;
import android.service.notification.ZenModeConfig;
import android.util.Log;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;

import com.android.internal.annotations.GuardedBy;

/**
 * 这个类用于供SeekBar设置音量使用,与SeekBar绑定,可以收一个使用者传入的回调接口SeekBarVolumizer.CallBack。
 * 当音量更改时该类会开始播放音乐,但是需要注意该类不会自动停止音乐的播放,因此需要该类的使用者在CallBack的onSampleStarting中,自己定义何时停止音乐播放,停止音乐播放需要调用该类的stopSample方法
 * 1、当进度条发生改变时,SeekBar的回调会触发CallBack的onProgressChange方法并将SeekBar的最新值更新到mLastProgress中,并构建一个VOLUME_SET通知后台线程去将该值存储到AudioManger中。
 * 2、后台线程更新完这个值后,AudioManager会发送一个广播通知音量已更改
 * 3、该类注册了一个广播接收器来监听音量更改事件,当音量发生更改时,该接收器在广播中取出音量值和音量类型,然后判断音量类型是否与当前类符合,如果符合则使用将当前音量更新mLastProgress,并通知Ui线程更新SeekBar
 *
 * 所以问题出现在第3点处,主要问题有两点:
 *   1、mLastProgress这个变量起了两个作用,第一个记录最新的SeekBar的值,第二个是记录广播发过来的值。
 *      因为广播是滞后于滑动的,比如从右向左滑动,则mLastProgress依次被记录为7654321,正常情况下最后存入的值为最后一个1;
 *      假设最后当该存入1时,因为执行顺序的原因,导致广播接收器的行为将这个1修改为了2,那么此时就会导致1因为丢失无法存入。
 *
 *      这个导致了问题进度条和实际音量不相符的现象:即当进度条滑到0时,没有静音;或者当进度条滑到1时,依然静音。
 *
 *      为了实现最小改动,该问题拟通过增加一个mCurrentProgress变量来进行处理,即将mLastProgress的作用集中,mLastProgress只负责记录最近的音量大小,即AudioManger发送过过来的音量大小,
 *      mCurrentProgress记录SeekBar的当前位置,并将该值存入AudioManger中完成铃声设置。
 *  2、setProgress(int true)方法,该方法true表示使用动画来实现SeekBar的值过渡,该动画会造成onProgressChanged上报的值与自身实际位置不符
 *
 *  3、多个SeekBar同时滑动是因为AudioManager发生错误导致发出了多个不同StreamType类型的广播,引起了其它进度条的更新
 *
 *      通过直接判断广播发送的StreamType与当前实例的mStreamType是否一致来修复该问题。
 * Turns a {@link SeekBar} into a volume control.
 * @hide
 */
public class SeekBarVolumizer implements OnSeekBarChangeListener Handler.Callback {
    pri

评论

共有 条评论