Android音量控制

0. Thanks To

Android音量控制调节
android 音量控制setVolumeControlStream
android 音量调节以及媒体音量界面

1. 音量调节

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

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

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

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

    //获取系统的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方法
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.直接自定义调节的幅度(步进值),直接调节音量大小。
public void setStreamVolume (int streamType, int index, int flags)
            参数说明:
                第一个,第三个和上面的一样

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

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

2. 音量按键的监听

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

    @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);
    }

两个方法选其一就好。

3. UI修改:

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

4. 封装音量控制:

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

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  : //www.greatytc.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。

5. Demo

这个Demo示例了怎么使用这个封装,和示例了怎么修改音量调UI。
ChestnutPlus/ModuleMedia
代码在:Moudle-Media-src-java下
通过MainActivity调用VideoActivity,记得修改视频的URL。

 /**
     * 监听音量实体按键
     * @param keyCode
     * @param event
     * @return
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        int a;
        switch (keyCode) {
            case KeyEvent.KEYCODE_VOLUME_DOWN:
                xToastMusic.setVoice(audioMngHelper.subVoice100()).show();
                return true;
            case KeyEvent.KEYCODE_VOLUME_UP:
                xToastMusic.setVoice(audioMngHelper.addVoice100()).show();
                return true;
            case KeyEvent.KEYCODE_VOLUME_MUTE:
                break;
        }
        return super.onKeyDown(keyCode, event);
    }

点个赞咯~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容