先上一张个人项目研发settings应用的一个功能,效果图如下:
个人根据项目相关代码跟踪到framework层时(framework层关键代码如下:)
@Override
public int adjustVolumeLevel(int volumeType, int level) {
if (null == mAudioManager) {
return -1;
}
boolean bMcuMute = false;
if (null == mSettingService) {
mSettingService = SettingService.getInstance();
}
if (null != mSettingService) {
try {
bMcuMute = mSettingService.isMcuMute();
} catch (RemoteException e) {
e.printStackTrace();
}
}
switch (volumeType) {
case VOLUME_TYPE_MUSIC:
case VOLUME_TYPE_NVGIS:
if (level >= 0 && masterMax() >= level) {
if (bMcuMute && 0 != level) {
setSystemMute(false);
}
mAudioManager.setStreamVolume(AudioManager.STREAM_GIS, level, 0);
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, level, 0);
saveAudioTypeVolumeLevel(AudioManager.STREAM_GIS, level);
saveAudioTypeVolumeLevel(AudioManager.STREAM_MUSIC, level);
}
break;
case VOLUME_TYPE_BTHFP:
if (level >= 0 && bthfpMax() >= level) {
mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, level, 0);
saveAudioTypeVolumeLevel(AudioManager.STREAM_BLUETOOTH_SCO, level);
}
break;
case VOLUME_TYPE_BKCAR:
if (level >= 0 && backcarMax() >= level) {
mAudioManager.setStreamVolume(AudioManager.STREAM_BACKCAR, level, 0);
saveAudioTypeVolumeLevel(AudioManager.STREAM_BACKCAR, level);
}
break;
case VOLUME_TYPE_xRING:
if (level >= 0 && ringMax() >= level) {
mAudioManager.setStreamVolume(AudioManager.STREAM_RING, level, 0);
saveAudioTypeVolumeLevel(AudioManager.STREAM_RING, level);
}
break;
default:
break;
}
return 0;
}
发现Android实际上已经针对不同音源的不同音量设置提供了接口,其源码路径为<个人使用的是Android4.2.2平台代码>:path:\android4.2.2\frameworks\base\media\java\android\media\AudioService.java,部分关键代码如下:
/** @see AudioManager#setStreamVolume(int, int, int) */
public void setStreamVolume(int streamType, int index, int flags) {
ensureValidStreamType(streamType);
VolumeStreamState streamState = mStreamStates[mStreamVolumeAlias[streamType]];
final int device = getDeviceForStream(streamType);
int oldIndex;
boolean force = false;
flags &= ~AudioManager.FLAG_FIXED_VOLUME;
if ((mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
((device & mFixedVolumeDevices) != 0)) {
flags |= AudioManager.FLAG_FIXED_VOLUME;
index = mStreamStates[streamType].getMaxIndex();
oldIndex = index;
} else {
// get last audible index if stream is muted, current index otherwise
oldIndex = streamState.getIndex(device,
(streamState.muteCount() != 0) /* lastAudible */);
index = rescaleIndex(index * 10, streamType, mStreamVolumeAlias[streamType]);
if (!checkSafeMediaVolume(mStreamVolumeAlias[streamType], index, device)) {
return;
}
if (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
force = true;
}
// setting volume on master stream type also controls silent mode
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
(mStreamVolumeAlias[streamType] == getMasterStreamType())) {
int newRingerMode;
if (index == 0) {
newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
: AudioManager.RINGER_MODE_SILENT;
setStreamVolumeInt(mStreamVolumeAlias[streamType],
index,
device,
force,
true);
} else {
newRingerMode = AudioManager.RINGER_MODE_NORMAL;
setRingerMode(newRingerMode);
}
//setRingerMode(newRingerMode); 移动到else中,正对Ring = 0避免全部静音
}
setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false, true);
// get last audible index if stream is muted, current index otherwise
index = mStreamStates[streamType].getIndex(device,
(mStreamStates[streamType].muteCount() != 0) /* lastAudible */);
}
sendVolumeUpdate(streamType, oldIndex, index, flags);
}
这边实际上是AudioManager调用了AudioService的相关方法,而AudioService又调用了本地jni库的方法。
上层使用方式:
我们直接通过context取get一个AudioManager管理者,然后通过设置不同音频通道即可,代码如下:
mAudioManager.setStreamVolume(AudioManager.STREAM_GIS, level, 0);
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, level, 0);
mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, level, 0);
mAudioManager.setStreamVolume(AudioManager.STREAM_BACKCAR, level, 0);
mAudioManager.setStreamVolume(AudioManager.STREAM_RING, level, 0);