web-dev-qa-db-ja.com

ボリュームの変更に対するブロードキャストアクションはありますか?

ユーザーが呼び出し音の音量やバイブレーションの設定を変更するたびに更新する必要がある小さなウィジェットをプログラミングしています。

キャプチャAndroid.media.VIBRATE_SETTING_CHANGEDバイブレーション設定では問題なく動作しますが、呼び出し音の音量が変更されたときに通知を受け取る方法が見つかりませんでした。これらのキーを使用せずにボリュームを変更するためのオプション。

このために定義されたブロードキャストアクションがあるか、それを作成する方法、またはそれなしで問題を解決する方法があるかを知っていますか?

50
LuTHieR

ブロードキャストアクションはありませんが、設定が変更されたときに通知を受けるためにコンテンツオブザーバーを接続できます。ストリームのボリュームはこれらの設定の一部です。 Android.provider.Settings.System.CONTENT_URIに登録して、すべての設定変更が通知されるようにします。

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

コンテンツオブザーバは次のようになります。

public class SettingsContentObserver extends ContentObserver {

   public SettingsContentObserver(Handler handler) {
      super(handler);
   } 

   @Override
   public boolean deliverSelfNotifications() {
      return super.deliverSelfNotifications(); 
   }

   @Override
   public void onChange(boolean selfChange) {
      super.onChange(selfChange);
      Log.v(LOG_TAG, "Settings change detected");
      updateStuff();
   }
}

そして、ある時点で必ずコンテンツオブザーバの登録を解除してください。

77
Nathan Totura

Nathanのコード は機能しますが、システム設定の変更ごとに2つの通知を提供します。それを回避するには、次を使用します

public class SettingsContentObserver extends ContentObserver {
    int previousVolume;
    Context context;

    public SettingsContentObserver(Context c, Handler handler) {
        super(handler);
        context=c;

        AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        previousVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC);
    }

    @Override
    public boolean deliverSelfNotifications() {
        return super.deliverSelfNotifications();
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);

        AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        int currentVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC);

        int delta=previousVolume-currentVolume;

        if(delta>0)
        {
            Logger.d("Decreased");
            previousVolume=currentVolume;
        }
        else if(delta<0)
        {
            Logger.d("Increased");
            previousVolume=currentVolume;
        }
    }
}

次に、サービスのonCreateで登録します。

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

次に、onDestroyで登録解除します。

getApplicationContext().getContentResolver().unregisterContentObserver(mSettingsContentObserver);
61
Aditya

はい、ボリューム変更のレシーバーを登録できます(これはハッキングの一種ですが、機能します)、私はこの方法で管理できました(ContentObserverを使用しません):マニフェストxmlファイル:

<receiver Android:name="com.example.myproject.receivers.MyReceiver" >
     <intent-filter>
          <action Android:name="Android.media.VOLUME_CHANGED_ACTION" />
     </intent-filter>
</receiver>

BroadcastReceiver:

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("Android.media.VOLUME_CHANGED_ACTION")) {
            Log.d("Music Stream", "has changed");       
        }
    }
}

それが役に立てば幸い!

11
alexm

Nathan'sadi's 、および swooby's code に基づいて、いくつかのマイナーな改良を加えた完全な実例を作成しました。

AudioFragmentクラスを見ると、カスタムContentObserverを使用してボリュームの変更を簡単に聞くことができます。

public class AudioFragment extends Fragment implements OnAudioVolumeChangedListener {

    private AudioVolumeObserver mAudioVolumeObserver;

    @Override
    public void onResume() {
        super.onResume();
        // initialize audio observer
        if (mAudioVolumeObserver == null) {
            mAudioVolumeObserver = new AudioVolumeObserver(getActivity());
        }
        /*
         * register audio observer to identify the volume changes
         * of audio streams for music playback.
         *
         * It is also possible to listen for changes in other audio stream types:
         * STREAM_RING: phone ring, STREAM_ALARM: alarms, STREAM_SYSTEM: system sounds, etc.
         */
        mAudioVolumeObserver.register(AudioManager.STREAM_MUSIC, this);
    }

    @Override
    public void onPause() {
        super.onPause();
        // release audio observer
        if (mAudioVolumeObserver != null) {
            mAudioVolumeObserver.unregister();
        }
    }

    @Override
    public void onAudioVolumeChanged(int currentVolume, int maxVolume) {
        Log.d("Audio", "Volume: " + currentVolume + "/" + maxVolume);
        Log.d("Audio", "Volume: " + (int) ((float) currentVolume / maxVolume) * 100 + "%");
    }
}


public class AudioVolumeContentObserver extends ContentObserver {

    private final OnAudioVolumeChangedListener mListener;
    private final AudioManager mAudioManager;
    private final int mAudioStreamType;
    private int mLastVolume;

    public AudioVolumeContentObserver(
            @NonNull Handler handler,
            @NonNull AudioManager audioManager,
            int audioStreamType,
            @NonNull OnAudioVolumeChangedListener listener) {

        super(handler);
        mAudioManager = audioManager;
        mAudioStreamType = audioStreamType;
        mListener = listener;
        mLastVolume = audioManager.getStreamVolume(mAudioStreamType);
    }

    /**
     * Depending on the handler this method may be executed on the UI thread
     */
    @Override
    public void onChange(boolean selfChange, Uri uri) {
        if (mAudioManager != null && mListener != null) {
            int maxVolume = mAudioManager.getStreamMaxVolume(mAudioStreamType);
            int currentVolume = mAudioManager.getStreamVolume(mAudioStreamType);
            if (currentVolume != mLastVolume) {
                mLastVolume = currentVolume;
                mListener.onAudioVolumeChanged(currentVolume, maxVolume);
            }
        }
    }

    @Override
    public boolean deliverSelfNotifications() {
        return super.deliverSelfNotifications();
    }
}


public class AudioVolumeObserver {

    private final Context mContext;
    private final AudioManager mAudioManager;
    private AudioVolumeContentObserver mAudioVolumeContentObserver;

    public AudioVolumeObserver(@NonNull Context context) {
        mContext = context;
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    }

    public void register(int audioStreamType, 
                         @NonNull OnAudioVolumeChangedListener listener) {

        Handler handler = new Handler();
        // with this handler AudioVolumeContentObserver#onChange() 
        //   will be executed in the main thread
        // To execute in another thread you can use a Looper
        // +info: https://stackoverflow.com/a/35261443/904907

        mAudioVolumeContentObserver = new AudioVolumeContentObserver(
                handler,
                mAudioManager,
                audioStreamType,
                listener);

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

    public void unregister() {
        if (mAudioVolumeContentObserver != null) {
            mContext.getContentResolver().unregisterContentObserver(mAudioVolumeContentObserver);
            mAudioVolumeContentObserver = null;
        }
    }
}


public interface OnAudioVolumeChangedListener {

    void onAudioVolumeChanged(int currentVolume, int maxVolume);
}

それがまだ誰かに役立つことを願っています! :)

8
Ryan Amaral

Nathanとadiのコードは機能しますが、クリーンアップして自己完結させることができます。

public class AudioStreamVolumeObserver
{
    public interface OnAudioStreamVolumeChangedListener
    {
        void onAudioStreamVolumeChanged(int audioStreamType, int volume);
    }

    private static class AudioStreamVolumeContentObserver
            extends ContentObserver
    {
        private final AudioManager                       mAudioManager;
        private final int                                mAudioStreamType;
        private final OnAudioStreamVolumeChangedListener mListener;

        private int mLastVolume;

        public AudioStreamVolumeContentObserver(
                @NonNull
                Handler handler,
                @NonNull
                AudioManager audioManager, int audioStreamType,
                @NonNull
                OnAudioStreamVolumeChangedListener listener)
        {
            super(handler);

            mAudioManager = audioManager;
            mAudioStreamType = audioStreamType;
            mListener = listener;

            mLastVolume = mAudioManager.getStreamVolume(mAudioStreamType);
        }

        @Override
        public void onChange(boolean selfChange)
        {
            int currentVolume = mAudioManager.getStreamVolume(mAudioStreamType);

            if (currentVolume != mLastVolume)
            {
                mLastVolume = currentVolume;

                mListener.onAudioStreamVolumeChanged(mAudioStreamType, currentVolume);
            }
        }
    }

    private final Context mContext;

    private AudioStreamVolumeContentObserver mAudioStreamVolumeContentObserver;

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

    public void start(int audioStreamType,
                      @NonNull
                      OnAudioStreamVolumeChangedListener listener)
    {
        stop();

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

        mAudioStreamVolumeContentObserver = new AudioStreamVolumeContentObserver(handler, audioManager, audioStreamType, listener);

        mContext.getContentResolver()
                .registerContentObserver(System.CONTENT_URI, true, mAudioStreamVolumeContentObserver);
    }

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

        mContext.getContentResolver()
                .unregisterContentObserver(mAudioStreamVolumeContentObserver);
        mAudioStreamVolumeContentObserver = null;
    }
}
7
swooby

こんにちは、上記のコードを試してみましたが、うまくいきませんでした。しかし、私はこの行を追加しようとしたとき

getActivity().setVolumeControlStream(AudioManager.STREAM_MUSIC);

そして、置きます

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

今は動作します。私の懸念は、変更時に音量ダイアログを非表示にする方法です。こちらをご覧ください image

2
donmj

その唯一の呼び出し音モードが変更された場合、アクションとして「Android.media.RINGER_MODE_CHANGED」を指定してブロードキャストレシーバーを使用できます。簡単に実装できます

2
user2503849
  private const val EXTRA_VOLUME_STREAM_TYPE = "Android.media.EXTRA_VOLUME_STREAM_TYPE"
  private const val VOLUME_CHANGED_ACTION = "Android.media.VOLUME_CHANGED_ACTION"

    val filter = IntentFilter(VOLUME_CHANGED_ACTION)
    filter.addAction(RINGER_MODE_CHANGED_ACTION)

      val receiver = object : BroadcastReceiver() {
            override fun onReceive(context1: Context, intent: Intent) {

                val stream = intent.getIntExtra(EXTRA_VOLUME_STREAM_TYPE, UNKNOWN)
                val mode = intent.getIntExtra(EXTRA_RINGER_MODE, UNKNOWN)
                val volumeLevel = audioManager.getStreamVolume(stream)
            }
        }
1
Ken Zira

すべての場合に100%の作業方法

  public class SettingsContentObserver extends ContentObserver {

        SettingsContentObserver(Handler handler) {
            super(handler);
        }

        @Override
        public boolean deliverSelfNotifications() {
            return super.deliverSelfNotifications();
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            volumeDialogContract.updateMediaVolume(getMediaVolume());


    }

    int getMediaVolume() {
        return audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
    }



    void unRegisterVolumeChangeListener() {
        volumeDialogContract.getAppContext().getApplicationContext().getContentResolver().
                unregisterContentObserver(settingsContentObserver);
    }

    void registerVolumeChangeListener() {
        settingsContentObserver = new VolumeDialogPresenter.SettingsContentObserver(new Handler());
        volumeDialogContract.getAppContext().getApplicationContext().getContentResolver().registerContentObserver(
                Android.provider.Settings.System.CONTENT_URI, true,
                settingsContentObserver);
    }
0
Vinayak