您的位置:首页 > 房产 > 家装 > Android动态设置系统音量最大值

Android动态设置系统音量最大值

2024/10/5 14:12:37 来源:https://blog.csdn.net/qq_23069607/article/details/140230522  浏览:    关键词:Android动态设置系统音量最大值

产品需求

  • 通过设定最大音量限制大屏声音输出,设置完后需要立即生效且需要记忆;
  • 以10%为递增状态,设置最大音量后,无论最大音量调节至多少百分比,音量条始终显示为100%(比如最大音量设置为80%,即侧边音量条依然可以显示充满,但是音量只有原来的80%)。

从技术角度上理解为:Framework层需要提供一个动态设置系统音量最大值的开放接口供应用层调用,应用apk通过设置最大音量百分比后系统声音效果需要立即生效,同时原生音量条的最大值范围也要变化。

需要涉及3个地方的修改:

  • 添加Framework层接口方法
  • 应用层apk调用新增的接口
  • SystemUI音量条监听最大值变化

Framework层接口

1、以Android 13为例,如果修改系统默认的STREAM_MUSIC音量值,通常是修改AudioService.java下MAX_STREAM_VOLUME数组对应的值15。但我们需要动态修改这个值且不需要重启服务立即生效。

/** Maximum volume index values for audio streams */
protected static int[] MAX_STREAM_VOLUME = new int[] {5,  // STREAM_VOICE_CALL7,  // STREAM_SYSTEM7,  // STREAM_RING15, // STREAM_MUSIC7,  // STREAM_ALARM7,  // STREAM_NOTIFICATION......
};

2、代码实现
/frameworks/base/media/java/android/media/AudioManager.java
/frameworks/base/media/java/android/media/IAudioService.aidl
/frameworks/base/services/core/java/com/android/server/audio/AudioService.java

IAudioService.aidl主要是声明一个新的系统服务方法,然后通过AudioManager.java来调用服务的具体实现

public void setStreamMaxVolume(int streamType, int maxVolume) {final IAudioService service = getService();try {service.setStreamMaxVolume(streamType, maxVolume);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}

AudioService.java具体实现setStreamMaxVolume方法

//动态变更STREAM_MUSIC最大音量值接口
public void setStreamMaxVolume(int streamType, int maxVolume) {ensureValidStreamType(streamType);if (streamType == AudioSystem.STREAM_MUSIC) {if (maxVolume <= 15 && maxVolume >= 0) {int preMaxVolume = MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];//更新MAX_STREAM_VOLUME数组值同时更新mIndexMaxMAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxVolume;mStreamStates[streamType].updateMaxIndex(maxVolume);//发送一个MAX_VOLUME_CHANGED_ACTION广播用于通知最大音量值变化,该系统广播需要声明在frameworks/base/core/res/AndroidManifest.xml里Intent intent = new Intent("com.ist.media.MAX_VOLUME_CHANGED_ACTION");intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);intent.putExtra("preMaxVolume", preMaxVolume);intent.putExtra("maxVolume", maxVolume);sendBroadcastToAll(intent);}}
}//关键:该方法加在内部class VolumeStreamState中,VolumeStreamState保存了运行时的音量信息,这里有个流音量index的换算关系,更新MAX_STREAM_VOLUME数组的同时也需要更新mIndexMax       
//mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
public void updateMaxIndex(int index) {mIndexMax = index * 10;
}

设置后需要有记忆性,即重启后AudioService服务构造初始化时设置最大音量值

	int maxMusicVolume = SystemProperties.getInt("ro.config.media_vol_steps", -1);if (maxMusicVolume != -1) {MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxMusicVolume;} else {//add by XXX 初始化STREAM_MUSIC最大音量值String ptsStr = mSettings.getGlobalString(mContentResolver, "persist.sys.hht.max_volume_percent");//上层通过该Settings值来保存音量设置的百分比if (TextUtils.isEmpty(ptsStr)) {ptsStr = "10";}int maxPercent = Integer.parseInt(ptsStr);maxMusicVolume = Math.round((float) maxPercent / 10 * 15);MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxMusicVolume;Log.i(TAG, "init maxMusicVolume = " + maxMusicVolume);//end by XXX
}

应用层apk调用

 /*** 设置最大音量百分比* @param percent 0~10,10%递进*/public void setMaxVolumePercent(int percent){Log.i(TAG, "setMaxVolumePercent() percent = "+ percent);//保存最大音量百分比设置Settings.Global.putString(context.getContentResolver(), "persist.sys.hht.max_volume_percent", String.valueOf(percent));//最大音量值设置后需要立即生效if (mAudioManager != null) {int currentMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);//获取系统最大音量值int currentVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);//当前音量值int maxMusicVolume = Math.round((float) percent / 10 * 15);//调用新增的系统接口方法mAudioManager.setStreamMaxVolume(AudioManager.STREAM_MUSIC, maxMusicVolume);Log.i(TAG, "setStreamMaxVolume = " + maxMusicVolume);if (currentVolume > maxMusicVolume) { //若当前音量值大于最大音量值则取较小值mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, maxMusicVolume, 0);}}}

SystemUI音量条监听最大值变化

/frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java

final String action = intent.getAction();
boolean changed = false;
if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);final int level = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);final int oldLevel = intent.getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1);if (D.BUG) Log.d(TAG, "onReceive VOLUME_CHANGED_ACTION stream=" + stream+ " level=" + level + " oldLevel=" + oldLevel);changed = updateStreamLevelW(stream, level);
}
......
//add by XXX 侧边音量条最大值即时更新
else if (action.equals("com.ist.media.MAX_VOLUME_CHANGED_ACTION")) {Log.d(TAG, "onReceive com.ist.media.MAX_VOLUME_CHANGED_ACTION");final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);final int preMaxVolume = intent.getIntExtra("preMaxVolume", -1);final int maxVolume = intent.getIntExtra("maxVolume", -1);Log.i(TAG, "onReceive preMaxVolume = " + preMaxVolume + ", maxVolume = " + maxVolume);if (preMaxVolume != maxVolume) {changed = true;getState();}
}
//end by XXX
if (changed) {mCallbacks.onStateChanged(mState);
}

dumpsys audio调试

通过adb shell dumpsys audio命令查看音频系统的状态信息。
Stream volumes (device: index):查看各类型流的音量值。其中Muted为是否静音,Min为最小值,Max为最大值,Current为各输出设备的当前音量,Devices为当前输出设备。
调试时,我们关注STREAM_MUSIC的Max值有没有按预期的变化即可。

- STREAM_MUSIC:Muted: falseMuted Internally: falseMin: 0Max: 15streamVolume:8Current: 2 (speaker): 8, 400 (hdmi): 8, 80000 (spdif): 8, 100000 (fm_transmitter): 8, 4000000 (usb_headset): 2, 10000000 (echo_canceller): 8, 40000000 (default): 3

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com