4

I encountered a problem when I wanted to implement volume change detection. As the change detection has to be detected in the background via Service, I can not intercept volume key presses.

I've tried ContentObserver to listen for volume settings change, but it didn't worked. But I've dig a bit more, and found that my ContentObserver detects volume change when I register it like this:

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

I've tried to change the first parameter - the URI of setting to listen, if I understand correctly. But I achieved nothing. So, how can this be done? I don't want to update my UI(I'm setting Seekbar to certain positin) on every settings change.

So, how do I register content observer to listen for media volume change?

Here's the code of ContentObserver:

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

3 Answers3

3

Change your onChange meathod to the following

@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;
    }
}
Aditya
  • 5,509
  • 4
  • 31
  • 51
  • Thanks. but this is not exactly that I want. Sure, it will prevent updating my UI, but still it's called when any setting changed. The question is how to register ContentObserver for some specific settings. – Alexander Woodblock Jul 02 '13 at 10:30
  • 1
    That cannot be done as there is no obserevr available for it. What you are currently doing is, observing all the descendants in the hierarchy of System. Settings. Read http://developer.android.com/reference/android/content/ContentResolver.html#registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver) – Aditya Jul 02 '13 at 10:48
  • How can I use content observer to detect holding down volume button? – Ruchir Baronia Feb 07 '16 at 16:30
0

You can monitor for changes to a specific stream by using a more specific URI than Settings.System.CONTENT_URI. The method Settings.System.getUriFor() will return the URI for a specific stream.

For example:

Uri uri = Settings.System.getUriFor(Settings.System.VOLUME_SETTINGS[AudioManager.STREAM_RING]);
appContext.getContentResolver().registerContentObserver(uri, true, myObserver);
Andy Dennie
  • 6,012
  • 2
  • 32
  • 51
0

Andy Dennie:

I have just tested approach suggested by you:

Uri uri = Settings.System .getUriFor(Settings.System.VOLUME_SETTINGS[AudioManager.STREAM_MUSIC]); appContext.getContentResolver().registerContentObserver(uri, true, myObserver);

and if I register for this URI, volume changes on STREAM_MUSIC aren't detected. But If I use

android.provider.Settings.System.CONTENT_URI

it works perfectly.

Michał Ziobro
  • 10,759
  • 11
  • 88
  • 143