Android 监听系统媒体音量变化


在做 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: [email protected]
 */

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

猜你喜欢

转载自blog.csdn.net/u011520181/article/details/80529414