Audio系列之通用的音量设置函数setStreamVolume()
来源:互联网 发布:java校验身份证号正则 编辑:程序博客网 时间:2024/06/06 09:01
系统设置界面中就是使用AudioManager.setStreamVolume(),
说下比较难理解的flag参数在AudioManager在handlerKeyDown()中设置了两个flags,分别是FLAG_SHOW_UI和FLAG_VIBRATE.从字面上可知,前者告诉AudioService需要弹出一个音量控制面板,后者可能,只是可能是设置在为0时震动一下.而设置了FLAG_PLAY_SOUND是松开音量键时有个提示音.
源码:
/** * Sets the volume index for a particular stream. * <p>This method has no effect if the device implements a fixed volume policy * as indicated by {@link #isVolumeFixed()}. * <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless * the app has been granted Do Not Disturb Access. * See {@link NotificationManager#isNotificationPolicyAccessGranted()}. * @param streamType The stream whose volume index should be set. * @param index The volume index to set. See * {@link #getStreamMaxVolume(int)} for the largest valid value. * @param flags One or more flags. * @see #getStreamMaxVolume(int) * @see #getStreamVolume(int) * @see #isVolumeFixed() */ public void setStreamVolume(int streamType, int index, int flags) { IAudioService service = getService(); try { service.setStreamVolume(streamType, index, flags, getContext().getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }只是简单的调用了AudioService的setStreamVolume()方法,下面是AudioService#setStreamVolume()源码:
private void setStreamVolume(int streamType, int index, int flags, String callingPackage, String caller, int uid) { if (mUseFixedVolume) { return; } ensureValidStreamType(streamType);//下面两句是进行流类型转换,后面会详细介绍。mStreamVolumeAlias保存了源类型//和目标类型的映射关系。mStreamStates是保存了各种流的对应的VolumeStreamState//VolumeStreamState保存与一个流类型所有音量相关的信息,每种流分配了一个VolumeStreamState对象 int streamTypeAlias = mStreamVolumeAlias[streamType]; VolumeStreamState streamState = mStreamStates[streamTypeAlias];//获取当前流使用哪一个音频设备进行播放,最终会被调用到AudioPolicyService中 final int device = getDeviceForStream(streamType); int oldIndex; // skip a2dp absolute volume control request when the device // is not an a2dp device if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) { return; } // If we are being called by the system (e.g. hardware keys) check for current user // so we handle user restrictions correctly. if (uid == android.os.Process.SYSTEM_UID) { uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid)); } if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage) != AppOpsManager.MODE_ALLOWED) { return; } if (isAndroidNPlus(callingPackage) && wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags)) && !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) { throw new SecurityException("Not allowed to change Do Not Disturb state"); } if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) { return; } synchronized (mSafeMediaVolumeState) { // reset any pending volume command mPendingVolumeCommand = null;//获取当前流的音量oldIndex = streamState.getIndex(device);//由于流类型转换需要转换设置的音量值 index = rescaleIndex(index * 10, streamType, streamTypeAlias); if (streamTypeAlias == AudioSystem.STREAM_MUSIC && (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { synchronized (mA2dpAvrcpLock) {
//和蓝牙耳机协议有关
if (mA2dp != null && mAvrcpAbsVolSupported) { mA2dp.setAvrcpAbsoluteVolume(index / 10); } } } if (streamTypeAlias == AudioSystem.STREAM_MUSIC) { setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags); } flags &= ~AudioManager.FLAG_FIXED_VOLUME; if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) && ((device & mFixedVolumeDevices) != 0)) { flags |= AudioManager.FLAG_FIXED_VOLUME; // volume is either 0 or max allowed for fixed volume devices if (index != 0) { if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && (device & mSafeMediaVolumeDevices) != 0) { index = mSafeMediaVolumeIndex; } else { index = streamState.getMaxIndex(); } } } if (!checkSafeMediaVolume(streamTypeAlias, index, device)) { mVolumeController.postDisplaySafeVolumeWarning(flags); mPendingVolumeCommand = new StreamVolumeCommand( streamType, index, flags, device); } else { onSetStreamVolume(streamType, index, flags, device, caller);
//获取设置的结果
index = mStreamStates[streamType].getIndex(device); } }
//广播通知
sendVolumeUpdate(streamType, oldIndex, index, flags); }
当VolumeStreamState#muteCount() != 0则是静音。应该是调用VolumeStreamState#setIndext()设置音量值的,但是API24的AudioService的setStreamVolume()代码中找不到这句。
int streamTypeAlias = mStreamVolumeAlias[streamType];
VolumeStreamState streamState = mStreamStates[streamTypeAlias];
以上两句涉及到满足所谓的“将铃声音量作为通知音量”这种需求,如,实现“以铃声音量用作音乐音量”代码如下:
mStreamVolumeAlias[AudioSystem.STREAM_MUSIC] = AudioSystem.STREAM_RING;
这样,当传入AudioSystem.STREAM_MUSIC参数时,实际操作的回事AudioSystem.STREAM_RING这个流对应的VolumeStreamState。
0 0
- Audio系列之通用的音量设置函数setStreamVolume()
- Audio系列之音量键
- iTween基础之Audio(音量和音调的变化)
- iTween基础之Audio(音量和音调的变化)
- android audio 音量设置分析
- Android Audio音量设置流程
- android audio 音量设置分析
- [RK3288][Android6.0] Audio的音量设置流程小结
- Core Audio APIs 技术笔记一(扬声器音量设置)
- Android Audio System线性音量和对数音量的转换
- Android Audio System线性音量和对数音量的转换
- Android Audio System线性音量和对数音量的转换
- Android Audio System线性音量和对数音量的转换
- Android Audio System线性音量和对数音量的转换
- Android Audio System线性音量和对数音量的转换
- Core Audio APIs 技术笔记二(麦克风音量和增强设置)
- Core Audio APIs 技术笔记二(麦克风音量和增强设置)
- Audio系列之AudioFocus
- 【Mrpc】Demo2 基于Zookeeper的服务器感知及负载均衡
- 位运算应用
- 关于成为一名嵌入式程序员的日常总结(8)
- 位运算例题3
- java性能优化技巧
- Audio系列之通用的音量设置函数setStreamVolume()
- Java多线程-工具篇-BlockingQueue
- HDU - 1007 分治(最接近点对模板)
- Android 中string-array的用法
- 宏,循环语句,位运算
- mac 'Access denied for user 'root'@'localhost' (using password: NO)'
- Material Design(1)
- 1.1.1初识VisualBasic
- 位运算练习(1、将整数中的几位取出来,取反输出二进制2、将整数中间某一位置位 )