音量变化是否有播放动作?

我正在编程一个小部件,每当用户更改铃声音量或振动设置时都需要更新。

捕获android.media.VIBRATE_SETTING_CHANGED对于振动设置工作得很好,但是我还没有find任何方式在振铃音量发生变化时得到通知,尽pipe当用户按下音量增大/减小的物理键时我可以尝试捕获,还有许多其他的选项可以在不使用这些键的情况下改变音量。

你知道是否有任何广播行动或任何方式来创build一个或没有它的解决问题?

没有广播动作,但我确实发现你可以连接一个内容观察者,当设置改变时得到通知,stream的音量就是其中一些设置。 注册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(); } } 

一定要注销内容观察者。

内森的代码工作,但给每个更改系统设置两个通知。 为避免这种情况,请使用以下内容

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

是的,你可以注册一个音量变化的接收器(这是一种黑客,但工程),我设法这样做(不涉及ContentObserver):在清单xml文件中:

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

广播接收器:

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

希望它有帮助!

内森和阿迪的代码是有效的,但是可以清理和自我包含:

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

基于纳森的 adi和swooby的代码,我创build了一个完整的工作示例,并进行了一些小改进。

outlookAudioFragment类,我们可以看到使用我们的自定义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); } 

希望它对于某人仍然有用! 🙂

嗨,我试过上面的代码,它不适合我。 但是当我试图添加这一行

 getActivity().setVolumeControlStream(AudioManager.STREAM_MUSIC); 

并放

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

它现在有效。 我关心的是如何隐藏音量对话框onchange。 看到这个图像 。

如果其唯一的振铃模式更改,您可以使用Brodcast接收器“ android.media.RINGER_MODE_CHANGED ”作为动作。 这将很容易实施

Interesting Posts