读书频道 > 网站 > 网页设计 > 深入理解Android:卷III
3.2.2通用的音量设置函数setStreamVolume()
15-08-21    下载编辑
收藏    我要投稿   

本文所属图书 > 深入理解Android:卷III

本书在逻辑上分为4个部分Part 01(第1-2章):这是本书的基础部分,首先介绍了Android源码环境的搭建、编译和调试;然后讲解了Android进程间通信与任务调度的工具Binder与MessageQueue 这两项基础工作是深入研究立即去当当网订购
除了可以通过音量键调节音量以外,用户还可以在系统设置中进行调节。Audio-Manager.setStreamVolume()是系统设置界面中调整音量所使用的接口。
 
1. setStreamVolume()分析
 
setStreamVolume()是SDK中提供给应用的API,它的作用是为特定的流类型设置范围内允许的任意音量。我们看一下它的实现:
 
[AudioService.java-->AudioService.setStreamVolume()]
public void setStreamVolume(int streamType, int index, int flags) {
    // 这里先判断一下流类型这个参数的有效性
    ensureValidStreamType(streamType);
    // 获取保存了指定流类型音量信息的VolumeStreamState对象
    // 注意,这里面使用mStreamVolumeAlias对这个数组进行流类型转换
    VolumeStreamState streamState = mStreamStates[mStreamVolumeAlias[streamType]];
    // 获取当前流将使用哪一个音频设备进行播放。它最终会被调用到AudioPolicyService中
    final int device = getDeviceForStream(streamType);
    // 获取流当前的音量
    final int oldIndex = streamState.getIndex(device,
                            (streamState.muteCount() != 0) /* lastAudible */);

    // 将原流类型下的音量值映射到目标流类型下的音量值
    // 因为不同流类型的音量值刻度不一样,所以需要进行转换
    index = rescaleIndex(index * 10, streamType, mStreamVolumeAlias[streamType]);

    //暂时先忽略下面这段if中的代码。它的作用是根据flags的要求修改手机的情景模式
    if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
                (mStreamVolumeAlias[streamType] == getMasterStreamType())) {
        ......
    }
    // 调用setStreamVolumeInt()
    setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false, true);
    // 获取设置的结果
    index = mStreamStates[streamType].getIndex(device,
               (mStreamStates[streamType].muteCount() != 0) /* lastAudible */);
    // 广播通知
    sendVolumeUpdate(streamType, oldIndex, index, flags);
}

 

 
看明白这个函数了吗?抛开被忽略掉的那个if块可以归纳为:这个函数的工作其实很简单,就执行了下面三方面的工作:
 
为调用setStreamVolumeInt()准备参数。
 
调用setStreamVolumeInt()。
 
广播音量发生变化的通知。
 
下面分析的主线将转向setStreamVolumeInt()的内容。
 
2. setStreamVolumeInt()分析
 
看一下setStreamVolumeInt()函数的代码,和前面一样,暂时忽略目前与分析目标无关的部分代码。
 
[AudioService.java-->AudioService.setStreamVolumeInt()]
private void setStreamVolumeInt(int streamType,
                                int index,
                                int device,
                                boolean force,
                                boolean lastAudible) {
    // 获取保存音量信息的VolumeStreamState对象
    VolumeStreamState streamState = mStreamStates[streamType];

    if (streamState.muteCount() != 0) {
        // 这里的内容是为了处理当流被静音后的情况。我们在讨论静音的实现时再考虑这段代码
        ......
    } else {
        // 调用streamState.setIndex()
        if (streamState.setIndex(index, device, lastAudible) || force) {
            // 如果setIndex返回true,或者force参数为true,就在这里向mAudioHandler发送消息
            sendMsg(mAudioHandler,
                    MSG_SET_DEVICE_VOLUME,
                    SENDMSG_QUEUE,
                    device,
                    0,
                    streamState,
                    0);
        }
    }
}

 

此函数有两个工作内容,一个是调用streamState.setIndex(),另一个则是根据setIndex()的返回值和force参数决定是否发送MSG_SET_DEVICE_VOLUME消息。这两项内容在3.2.1节中已经介绍过,在此不再赘述。
 
至此,setStreamVolume()的分析完成。
 
分析完setStreamVolume()的工作流程后,读者是否觉得有些熟悉呢?如果我们用setStreamVolumeInt()的代码替换setStreamVolume()中对setStreamVolumeInt()的调用,再和adjustStreamVolume()函数进行以下比较,就会发现它们的内容出奇得相似。
 
Android在其他地方也有这样的情况。从这一点上来说,已经发展到4.1版本的Android源代码仍然不够精致。读者可以思考一下,有没有办法把这两个函数融合为一个函数呢?
到此,对于音量设置相关的内容就告一段落。接下来我们将讨论和音量相关的另一个重要的内容—静音。
点击复制链接 与好友分享!回本站首页
分享到: 更多
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:1.3 功能
下一篇:1.5 小结
相关文章
图文推荐
JavaScript网页动画设
1.9 响应式
1.8 登陆页式
1.7 主题式
排行
热门
文章
下载
读书

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做最好的IT技术学习网站