Android中系统音量用代码控制

音量调节

我们知道,在平常调节音量的时候,是有一定的调节数值,也就是,每按一次音量 +/-,音量的增加/减小幅度,这个我们称为:系统的音量步进值。而音量还有一定的范围,系统的是:0 到 Max,Max 不确定,这个称为:系统的音量范围。

在Android中,是有几种类型的音量可以调节:

  • STREAM_ALARM 警报
  • STREAM_MUSIC 音乐回放即媒体音量
  • STREAM_RING 铃声
  • STREAM_SYSTEM 系统
  • STREAM_VOICE_CALL 通话

Android 中的所有音量都是通过:AudioManager 去管理的,也是通过它去调节:

1
2
3
4
5
6
//获取系统的Audio管理者
AudioManager mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);  
//最大音量
int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
//当前音量
int currentVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

而日常的项目中,有两种的调节方式:

1. 渐进式,即像手动按音量键一样,一步一步增加或减少

通过 AudioManager 的 adjustStreamVolume 方法:

1
public void adjustStreamVolume (int  streamType, int direction, int flags)

参数说明:

int streamType 需要调整的音量类型(以下常量定义于AudioManager类中)

  • STREAM_ALARM 警报
  • STREAM_MUSIC 音乐回放即媒体音量
  • STREAM_NOTIFICATION 窗口顶部状态栏Notification,
  • STREAM_RING 铃声
  • STREAM_SYSTEM 系统
  • STREAM_VOICE_CALL 通话
  • STREAM_DTMF 双音多频,不是很明白什么东西

int direction 调整的方向,加或者减(以下常量定义于AudioManager类中)

  • ADJUST_LOWER 降低音量
  • ADJUST_RAISE 升高音量
  • ADJUST_SAME 保持不变,这个主要用于向用户展示当前的音量

int flags 附加的一些参数

参数的说明参考API文档:http://www.android-doc.com/reference/android/media/AudioManager.html

  • FLAG_PLAY_SOUND 调整音量时播放声音
  • FLAG_SHOW_UI 调整时显示音量条,就是按音量键出现的那个
  • 0表示什么也没有

2. 直接自定义调节的幅度(步进值),直接调节音量大小

1
public void setStreamVolume (int streamType, int index, int flags)

参数说明:

第一个,第三个和上面的一样

第二个参数:int index: 把音量调整到index值。

这里,可以根据获取的最大音量去自己设置调整的幅度。

音量按键的监听

直接上代码,需要在 Activity 中,重写其按键的回调:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    int action = event.getAction();
    if (action ==KeyEvent.ACTION_DOWN) {
        tv.setText("+++++++++ACTION_DOWN++++++"+ count++);
        return true;
    }
    if (action== KeyEvent.ACTION_UP) {
        tv.setText("+++++ACTION_UP++++++++++");
        return true;
    }
    return super.dispatchKeyEvent(event);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    switch (keyCode) {
    case KeyEvent.KEYCODE_VOLUME_DOWN:
        tv.setText("-----------------"+count);
        count--;
        return true;
    case KeyEvent.KEYCODE_VOLUME_UP:
        tv.setText("++++++++++++++++"+ count);
        count++;
        return true;
    case KeyEvent.KEYCODE_VOLUME_MUTE:
        tv.setText("MUTE");
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

两个方法选其一就好。

UI修改

我们可以直接在监听里面做,让系统音量 UI 不弹出,设置好调整音量的两个方法的 FLAG 就好,然后自己去控制音量。这里我们可以用自定义的 Toast 布局去弄,或者是基于 Dialog 的组合控件去曾现这个音量条。

封装音量控制

代码里面定义了常用的 DIY 音量调节范围:0-100,默认音量步进值为 2。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package com.chestnut.Common.Helper;

import android.content.Context;
import android.media.AudioManager;
import android.support.annotation.IntDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * <pre>
 *     author: Chestnut
 *     blog  : http://www.jianshu.com/u/a0206b5f4526
 *     time  : 2017/6/17 16:11
 *     desc  :  集成音量控制
 *     thanks To:   http://blog.csdn.net/hufeng882412/article/details/7310131
 *     dependent on:
 *     update log:
 * </pre>
 */

public class AudioMngHelper {

    private final String TAG = "AudioMngHelper";
    private final boolean OpenLog = true;

    private AudioManager audioManager;
    private int NOW_AUDIO_TYPE = TYPE_MUSIC;
    private int NOW_FLAG = FLAG_NOTHING;
    private int VOICE_STEP_100 = 2; //0-100的步进。

    /**
     * 封装:STREAM_类型
     */
    public final static int TYPE_MUSIC = AudioManager.STREAM_MUSIC;
    public final static int TYPE_ALARM = AudioManager.STREAM_ALARM;
    public final static int TYPE_RING = AudioManager.STREAM_RING;
    @IntDef({TYPE_MUSIC, TYPE_ALARM, TYPE_RING})
    @Retention(RetentionPolicy.SOURCE)
    public @interface TYPE {}

    /**
     * 封装:FLAG
     */
    public final static int FLAG_SHOW_UI = AudioManager.FLAG_SHOW_UI;
    public final static int FLAG_PLAY_SOUND = AudioManager.FLAG_PLAY_SOUND;
    public final static int FLAG_NOTHING = 0;
    @IntDef({FLAG_SHOW_UI, FLAG_PLAY_SOUND, FLAG_NOTHING})
    @Retention(RetentionPolicy.SOURCE)
    public @interface FLAG {}

    /**
     * 初始化,获取音量管理者
     * @param context   上下文
     */
    public AudioMngHelper(Context context) {
        audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    }

    public int getSystemMaxVolume() {
        return audioManager.getStreamMaxVolume(NOW_AUDIO_TYPE);
    }

    public int getSystemCurrentVolume() {
        return audioManager.getStreamVolume(NOW_AUDIO_TYPE);
    }

    /**
     * 以0-100为范围,获取当前的音量值
     * @return  获取当前的音量值
     */
    public int get100CurrentVolume() {
        return 100*getSystemCurrentVolume()/getSystemMaxVolume();
    }

    /**
     * 修改步进值
     * @param step  step
     * @return  this
     */
    public AudioMngHelper setVoiceStep100(int step) {
        VOICE_STEP_100 = step;
        return this;
    }

    /**
     * 改变当前的模式,对全局API生效
     * @param type
     * @return
     */
    public AudioMngHelper setAudioType(@TYPE int type) {
        NOW_AUDIO_TYPE = type;
        return this;
    }

    /**
     * 改变当前FLAG,对全局API生效
     * @param flag
     * @return
     */
    public AudioMngHelper setFlag(@FLAG int flag) {
        NOW_FLAG = flag;
        return this;
    }

    public AudioMngHelper addVoiceSystem() {
        audioManager.adjustStreamVolume(NOW_AUDIO_TYPE,AudioManager.ADJUST_RAISE,NOW_FLAG);
        return this;
    }

    public AudioMngHelper subVoiceSystem() {
        audioManager.adjustStreamVolume(NOW_AUDIO_TYPE,AudioManager.ADJUST_LOWER,NOW_FLAG);
        return this;
    }

    /**
     * 调整音量,自定义
     * @param num   0-100
     * @return  改完后的音量值
     */
    public int setVoice100(int num) {
        int a = (int) Math.ceil((num)*getSystemMaxVolume()*0.01);
        a = a<=0 ? 0 : a;
        a = a>=100 ? 100 : a;
        audioManager.setStreamVolume(NOW_AUDIO_TYPE,a,0);
        return get100CurrentVolume();
    }

    /**
     * 步进加,步进值可修改
     *  0——100
     * @return  改完后的音量值
     */
    public int addVoice100() {
        int a = (int) Math.ceil((VOICE_STEP_100 + get100CurrentVolume())*getSystemMaxVolume()*0.01);
        a = a<=0 ? 0 : a;
        a = a>=100 ? 100 : a;
        audioManager.setStreamVolume(NOW_AUDIO_TYPE,a,NOW_FLAG);
        return get100CurrentVolume();
    }

    /**
     * 步进减,步进值可修改
     *  0——100
     * @return  改完后的音量值
     */
    public int subVoice100() {
        int a = (int) Math.floor((get100CurrentVolume() - VOICE_STEP_100)*getSystemMaxVolume()*0.01);
        a = a<=0 ? 0 : a;
        a = a>=100 ? 100 : a;
        audioManager.setStreamVolume(NOW_AUDIO_TYPE,a,NOW_FLAG);
        return get100CurrentVolume();
    }
}

部分API的说明:

  • 可以设置对哪种类型的音量去调控,通过:AudioMngHelper.setAudioType,通过注解的方式限制了用户的设置类型,在类的开头可以看到,默认值是媒体类型。
  • 可以对 Flag 进行全局的设置,通过:AudioMngHelper.setFlag,设置显示UI或者听到调节音效或者啥都没。
  • get100CurrentVolume(): 以 0-100 为范围,获取当前的音量值
  • getSystemMaxVolume(): 获取系统音量范围的最大值
  • getSystemCurrentVolume(): 获取系统音量范围的当前值
  • addVoiceSystem(): 以系统步进值和范围为基础,音量+
  • subVoiceSystem(): 同上,音量-
  • addVoice100(): 以 0-100 范围和自定义的步进值为基础,音量+
  • subVoice100(): 同上,音量-
  • setVoiceStep100(): 设置 DIY 步进值,默认是 2。