Android 监听系统媒体音量变化

本文介绍了一种在Android系统中监听音量变化的方法,并通过自定义类VolumeChangeObserver实现了音量变化时的回调功能。文章详细展示了如何注册和注销广播接收器,以及如何获取当前媒体音量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


在做 SAPA 适配时由于其直连驱动层不经过 Android 的音量增益控制,所以调节系统媒体音量对音量改变无效。现要调节系统音量时也可以控制播放的音量,那么就需要监听系统音量变化,然后转换成增益给输出数据乘以对应比率从而实现对音量的控制。

一般监听音量多是监听手机物理音量按键的点击事件,但是在音量控制面板拖动音量条改变音量就无法监听。那么我们需要分析无论是按音量键还是拖动音量条,系统都做了什么呢?有什么共性?

参考:Android系统音量变化后会干什么?

从文中可以知道,当音量变化时,系统会发出广播,所以我们只要监听音量改变的广播就可以了,不用关心具体是哪种方式改变的音量。该广播的 action 为AudioManager.VOLUME_CHANGED_ACTION ,但是该常量被隐藏了,所以直接用 "android.media.VOLUME_CHANGED_ACTION" ,在收到广播时可以通过 AudioManager的getStreamVolume(AudioManager.STREAM_MUSIC) 方法获得当前的音量,也可以从广播中携带的数据获取,我对此做了个封装。

封装如下

package com.ushow.sapademo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import java.lang.ref.WeakReference;

/**
 * Author: Alan Wang.
 * Date: 18/5/29 16:39.
 * Mail: alanwang6584@gmail.com
 */

public class VolumeChangeObserver {

    private static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";
    private static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE";

    public interface VolumeChangeListener {
        /**
         * 系统媒体音量变化
         * @param volume
         */
        void onVolumeChanged(int volume);
    }

    private VolumeChangeListener mVolumeChangeListener;
    private VolumeBroadcastReceiver mVolumeBroadcastReceiver;
    private Context mContext;
    private AudioManager mAudioManager;
    private boolean mRegistered = false;

    public VolumeChangeObserver(Context context) {
        mContext = context;
        mAudioManager = (AudioManager) context.getApplicationContext()
                .getSystemService(Context.AUDIO_SERVICE);
    }

    /**
     * 获取当前媒体音量
     * @return
     */
    public int getCurrentMusicVolume() {
        return mAudioManager != null ? mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC) : -1;
    }

    /**
     * 获取系统最大媒体音量
     * @return
     */
    public int getMaxMusicVolume() {
        return mAudioManager != null ? mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) : 15;
    }

    public VolumeChangeListener getVolumeChangeListener() {
        return mVolumeChangeListener;
    }

    public void setVolumeChangeListener(VolumeChangeListener volumeChangeListener) {
        this.mVolumeChangeListener = volumeChangeListener;
    }

    /**
     * 注册音量广播接收器
     * @return
     */
    public void registerReceiver() {
        mVolumeBroadcastReceiver = new VolumeBroadcastReceiver(this);
        IntentFilter filter = new IntentFilter();
        filter.addAction(VOLUME_CHANGED_ACTION);
        mContext.registerReceiver(mVolumeBroadcastReceiver, filter);
        mRegistered = true;
    }

    /**
     * 解注册音量广播监听器,需要与 registerReceiver 成对使用
     */
    public void unregisterReceiver() {
        if (mRegistered) {
            try {
                mContext.unregisterReceiver(mVolumeBroadcastReceiver);
                mVolumeChangeListener = null;
                mRegistered = false;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static class VolumeBroadcastReceiver extends BroadcastReceiver {
        private WeakReference<VolumeChangeObserver> mObserverWeakReference;

        public VolumeBroadcastReceiver(VolumeChangeObserver volumeChangeObserver) {
            mObserverWeakReference = new WeakReference<>(volumeChangeObserver);
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            //媒体音量改变才通知
            if (VOLUME_CHANGED_ACTION.equals(intent.getAction())
                    && (intent.getIntExtra(EXTRA_VOLUME_STREAM_TYPE, -1) == AudioManager.STREAM_MUSIC)) {
                VolumeChangeObserver observer = mObserverWeakReference.get();
                if (observer != null) {
                    VolumeChangeListener listener = observer.getVolumeChangeListener();
                    if (listener != null) {
                        int volume = observer.getCurrentMusicVolume();
                        if (volume >= 0) {
                            listener.onVolumeChanged(volume);
                        }
                    }
                }
            }
        }
    }
}

对外暴露有以下几个方法:

  • VolumeChangeObserver(Context context):构造函数;

  • VolumeChangeListener:音量改变接口,当媒体音量变化时会调用其 onVolumeChanged(int volume) 方法;

  • setVolumeChangeListener(VolumeChangeListener volumeChangeListener):设置音量改变的监听器;

  • getCurrentMusicVolume():获取当前媒体音量;

  • registerReceiver():注册接收器;

  • unregisterReceiver():解注册接收器

调用逻辑如下

package com.ushow.sapademo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

//实现 VolumeChangeListener 接口
public class MainActivity extends AppCompatActivity implements VolumeChangeObserver.VolumeChangeListener {
    private final static String TAG = MainActivity.class.getSimpleName();

    private VolumeChangeObserver mVolumeChangeObserver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //实例化对象并设置监听器
        mVolumeChangeObserver = new VolumeChangeObserver(this);
        mVolumeChangeObserver.setVolumeChangeListener(this);
        int initVolume = mVolumeChangeObserver.getCurrentMusicVolume();
        Log.e(TAG, "initVolume = " + initVolume);
    }

    @Override
    protected void onResume() {
        //注册广播接收器
        mVolumeChangeObserver.registerReceiver();
        super.onResume();
    }

    @Override
    protected void onPause() {
        //解注册广播接收器
        mVolumeChangeObserver.unregisterReceiver();
        super.onPause();
    }

    @Override
    public void onVolumeChanged(int volume) {
        //系统媒体音量改变时的回调
        Log.e(TAG, "onVolumeChanged()--->volume = " + volume);
    }
}

Vivado2023是一款集成开发环境软件,用于设计和验证FPGA(现场可编程门阵列)和可编程逻辑器件。对于使用Vivado2023的用户来说,license是必不可少的。 Vivado2023的license是一种许可证,用于授权用户合法使用该软件。许可证分为多种类型,包括评估许可证、开发许可证和节点许可证等。每种许可证都有不同的使用条件和功能。 评估许可证是免费提供的,让用户可以在一段时间内试用Vivado2023的全部功能。用户可以使用这个许可证来了解软件的性能和特点,对于初学者和小规模项目来说是一个很好的选择。但是,使用评估许可证的用户在使用期限过后需要购买正式的许可证才能继续使用软件。 开发许可证是付费的,可以永久使用Vivado2023的全部功能。这种许可证适用于需要长期使用Vivado2023进行开发的用户,通常是专业的FPGA设计师或工程师。购买开发许可证可以享受Vivado2023的技术支持和更新服务,确保软件始终保持最新的版本和功能。 节点许可证是用于多设备或分布式设计的许可证,可以在多个计算机上安装Vivado2023,并共享使用。节点许可证适用于大规模项目或需要多个处理节点进行设计的用户,可以提高工作效率和资源利用率。 总之,Vivado2023 license是用户在使用Vivado2023时必须考虑的问题。用户可以根据自己的需求选择合适的许可证类型,以便获取最佳的软件使用体验。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值