7

寻找一种“最全面和兼容(即所有 Android 版本......)”的方式来收听音量变化,我发现了两种不同的方法来处理这个问题:

  1. 注册媒体按钮事件接收器
  2. onKeyDown + SettingsContentObserver

哪种方法更可取?

为什么?

更新 1:感谢下面的评论,我发现 onKeyDown() 实际上接管了音量键,这可能不是一个完整的解决方案,因为其中一篇文章提到音量可以通过硬件按钮以外的接口更改(不是提到谷歌似乎正在逐渐取消那些“接管”能力)。

OTOH,android.media.VOLUME_CHANGED_ACTION 是一个黑客,甚至没有记录。这可能意味着它将在 Android 5 左右停止工作......

更新 2: registerMediaButtonEventReceiver 根本不起作用!(对于音量硬件按钮,我只是尝试过)。

额外的见解?

4

2 回答 2

2

BroadcastReceiver在未来的 API中为音量流提供 a 会很棒,但今天最好的解决方案可能是ContentObserver为设置注册 a(包括 VOLUME_NOTIFICATION):

mSettingsContentObserver = new SettingsContentObserver( new Handler() ); 
this.getApplicationContext().getContentResolver().registerContentObserver( 
    android.provider.Settings.System.CONTENT_URI, true,
    mSettingsContentObserver );

有关更多信息,请参阅此答案:https ://stackoverflow.com/a/7017516/117382

编辑:用工作代码更正。也许这个解决方案更好:https ://stackoverflow.com/a/17398781/117382

于 2013-03-14T10:06:49.303 回答
0

为了能够收听所有音量流,对我来说最好的方法是使用 ContentObserver。这是我的代码:

public class AudioVolumeObserver
{
    public interface OnAudioStreamVolumeChangedListener
    {
        void onAudioStreamVolumeChanged(ArrayList<Integer> audioStreamType);
    }

    public interface OnAudioModeVolumeChangedListener
    {
        void onAudioModeVolumeChanged(int volumeMode);
    }

    private static class AudioVolumeContentObserver
            extends ContentObserver
    {
        private final AudioManager mAudioManager;

        private final OnAudioStreamVolumeChangedListener mVolumeStreamListener;
        private final OnAudioModeVolumeChangedListener mVolumeModeListener;

        private int[] currentVolumeStreams = new int[6];
        private int[] lastVolumeStreams = new int[6];

        private int currentVolumeMode;
        private int lastVolumeMode;

        ArrayList<Integer> changedVolumeStreams = new ArrayList<>();


        public AudioVolumeContentObserver(
                @NonNull
                        Handler handler,
                @NonNull
                AudioManager audioManager,
                @NonNull
                        OnAudioModeVolumeChangedListener volumeModeListener,
                @NonNull
                OnAudioStreamVolumeChangedListener volumeStreamListener)
        {
            super(handler);

            mAudioManager = audioManager;
            mVolumeModeListener = volumeModeListener;
            mVolumeStreamListener = volumeStreamListener;

            lastVolumeMode = mAudioManager.getRingerMode();

            lastVolumeStreams[0] = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
            lastVolumeStreams[1] = mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM);
            lastVolumeStreams[2] = mAudioManager.getStreamVolume(AudioManager.STREAM_RING);
            lastVolumeStreams[3] = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            lastVolumeStreams[4] = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
            lastVolumeStreams[5] = mAudioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION);

        }

        @Override
        public void onChange(boolean selfChange)
        {
            currentVolumeMode = mAudioManager.getRingerMode();

            currentVolumeStreams[0] = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
            currentVolumeStreams[1] = mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM);
            currentVolumeStreams[2] = mAudioManager.getStreamVolume(AudioManager.STREAM_RING);
            currentVolumeStreams[3] = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            currentVolumeStreams[4] = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
            currentVolumeStreams[5] = mAudioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION);

            if (currentVolumeMode != lastVolumeMode){
                lastVolumeMode = currentVolumeMode;
                mVolumeModeListener.onAudioModeVolumeChanged(currentVolumeMode);

            }

            changedVolumeStreams.clear();

            for (int i=0; i<6; i++)
                if (currentVolumeStreams[i] != lastVolumeStreams[i])
                {
                    lastVolumeStreams[i] = currentVolumeStreams[i];
                    changedVolumeStreams.add(i);
                }


            if (!changedVolumeStreams.isEmpty()){
                mVolumeStreamListener.onAudioStreamVolumeChanged(changedVolumeStreams);
            }

        }
    }

    private final Context mContext;

    private AudioVolumeContentObserver mAudioVolumeContentObserver;

    public AudioVolumeObserver(
            @NonNull
            Context context)
    {
        mContext = context;
    }

    public void start(@NonNull
                      OnAudioModeVolumeChangedListener volumeModeListener,
                      @NonNull
                      OnAudioStreamVolumeChangedListener volumeStreamListener)
    {
        stop();

        Handler handler = new Handler();
        AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);

        mAudioVolumeContentObserver = new AudioVolumeContentObserver(handler, audioManager, volumeModeListener, volumeStreamListener);

        mContext.getContentResolver()
                .registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mAudioVolumeContentObserver);
    }

    public void stop()
    {
        if (mAudioVolumeContentObserver == null)
        {
            return;
        }

        mContext.getContentResolver()
                .unregisterContentObserver(mAudioVolumeContentObserver);
        mAudioVolumeContentObserver = null;
    }
}
于 2016-10-21T11:17:29.300 回答