7

音量の変化を聞くための「最も包括的で互換性のある(つまり、すべてのAndroidバージョン...)」方法を探していたところ、これを処理する2つの異なる方法が見つかりました。

  1. registerMediaButtonEventReceiver
  2. onKeyDown + SettingsContentObserver

どの方法が好ましいですか?

なぜ?

更新 1:以下のコメントのおかげで、onKeyDown() が実際に音量キーを引き継いでいることがわかりました。これは、ハードウェア ボタン以外のインターフェイスを介して音量を変更できると投稿の 1 つが述べているため、完全な解決策ではない可能性があります ( Google はこれらの「引き継ぐ」機能を徐々に取り除いているように見えることを述べてください)。

OTOH、android.media.VOLUME_CHANGED_ACTIONはハックであり、文書化されていません. これはおそらく、Android 5 かそこらで動作しなくなることを意味します...

更新 2: registerMediaButtonEventReceiver がまったく機能しません! (つまり、ボリュームハードウェアボタンについては、試してみました)。

追加の洞察?

4

2 に答える 2

2

BroadcastReceiver将来、ボリューム ストリーム用の API があれば素晴らしいことですが、現時点ContentObserverでは、設定 (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 に答える