最近一直在解安卓audio部分的bug,其中最多的就是音量设置方面的问题,在这里把自己学习到的一些东西记录一下,以供参考。
安卓java部分的音量设置首先调用到AudioManager.java中
在这里有两种方法可以设置音量setStreamVolume和adjustStreamVolume
setStreamVolume:传入index直接设置音量值
adjustStreamVolume:传入direction,根据direction和获取到的步长设置音量。
由于我们用到的是setStreamVolume方法,所以通过setStreamVolume向下看,其实如果再去看adjustStreamVolume其实也是殊途同归。
1.setStreamVolume(AudioManager.java)
public void setStreamVolume(int streamType, int index, int flags) {
final IAudioService service = getService();
try {
service.setStreamVolume(streamType, index, flags, getContext().getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在此处调用了AudioService的setStreamVolume方法。此处传入的streamType和index分别为设置的流类型和音量值。
关于streamType:安卓在声音方面定义了多种流的类型以控制不同的声音(比如区分音乐和铃声以及系统提示音等)
/** Used to identify the volume of audio streams for phone calls */
public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL;
/** Used to identify the volume of audio streams for system sounds */
public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM;
/** Used to identify the volume of audio streams for the phone ring */
public static final int STREAM_RING = AudioSystem.STREAM_RING;
/** Used to identify the volume of audio streams for music playback */
public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC;
/** Used to identify the volume of audio streams for alarms */
public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM;
/** Used to identify the volume of audio streams for notifications */
public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION;
/** @hide Used to identify the volume of audio streams for phone calls when connected
* to bluetooth */
public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO;
/** @hide Used to identify the volume of audio streams for enforced system sounds
* in certain countries (e.g camera in Japan) */
public static final int STREAM_SYSTEM_ENFORCED = AudioSystem.STREAM_SYSTEM_ENFORCED;
/** Used to identify the volume of audio streams for DTMF Tones */
public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF;
/** @hide Used to identify the volume of audio streams exclusively transmitted through the
* speaker (TTS) of the device */
public static final int STREAM_TTS = AudioSystem.STREAM_TTS;
/** Used to identify the volume of audio streams for accessibility prompts */
public static final int STREAM_ACCESSIBILITY = AudioSystem.STREAM_ACCESSIBILITY;
我们在AudioManager.java中可以看到源码对各种流类型进行了解释,并且调用AudioSystem中的变量进行了赋值。
/** Used to identify the default audio stream volume */
public static final int STREAM_DEFAULT = -1;
/** Used to identify the volume of audio streams for phone calls */
public static final int STREAM_VOICE_CALL = 0;
/** Used to identify the volume of audio streams for system sounds */
public static final int STREAM_SYSTEM = 1;
/** Used to identify the volume of audio streams for the phone ring and message alerts */
public static final int STREAM_RING = 2;
/** Used to identify the volume of audio streams for music playback */
public static final int STREAM_MUSIC = 3;
/** Used to identify the volume of audio streams for alarms */
public static final int STREAM_ALARM = 4;
/** Used to identify the volume of audio streams for notifications */
public static final int STREAM_NOTIFICATION = 5;
/** Used to identify the volume of audio streams for phone calls when connected on bluetooth */
public static final int STREAM_BLUETOOTH_SCO = 6;
/** Used to identify the volume of audio streams for enforced system sounds in certain
* countries (e.g camera in Japan) */
public static final int STREAM_SYSTEM_ENFORCED = 7;
/** Used to identify the volume of audio streams for DTMF tones */
public static final int STREAM_DTMF = 8;
/** Used to identify the volume of audio streams exclusively transmitted through the
* speaker (TTS) of the device */
public static final int STREAM_TTS = 9;
/** Used to identify the volume of audio streams for accessibility prompts */
public static final int STREAM_ACCESSIBILITY = 10;
/**
2.AudioService.java
/** @see AudioManager#setStreamVolume(int, int, int) */
public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
//验证流类型是否合法
if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Log.w(TAG, "Trying to call setStreamVolume() for a11y without"
+ " CHANGE_ACCESSIBILITY_VOLUME callingPackage=" + callingPackage);
return;
}
setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
Binder.getCallingUid());
}
此处再调用AudioService中的setStreamVolume的重载函数,该函数多传入了一个Binder.getCallingUid(),此处用到了binder的方法获取调用端的UID来判断调用者的身份,有兴趣的可以去了解binder相关的内容,此处影响不大不多做解释。
private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
String caller, int uid) {
<