开发者

any way to detect volume key presses or volume changes with android service?

Some Android apps generate a notification when the device's volume changes and some lock t开发者_开发技巧he volume. For the life of me, I cannot find out how that's done. Please, can someone help me by providing an example?


Actually there is one way you can do in service by using Content Observer. It works like a broadcast receiver, listen to the event of changing content such as volume, contacts, call log...

Using the following code in your service

public class VolumeService extends Service{ 
AudioManager mAudioManager;
Handler mHandler;

private ContentObserver mVolumeObserver = new ContentObserver(mHandler) {
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        if (mAudioManager != null) {

            final int volume = mAudioManager.getStreamVolume(AudioManager.STREAM_RING);
            System.out.println("Volume thay đổi: " +volume);

            Intent photoIntent = new Intent(VolumeService.this,TakePhotoActivity.class);
            photoIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(photoIntent);
        }
    }
};





@Override
public void onCreate() {
    super.onCreate();

    System.out.println("Volume Service started");

    mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);

    Uri uri = Settings.System.getUriFor(Settings.System.VOLUME_SETTINGS[AudioManager.STREAM_RING]);
    getContentResolver().registerContentObserver(uri, true, mVolumeObserver);

    System.out.println("Đã đăng ký Volume listener");
}



@Override
public void onDestroy() {
    super.onDestroy();      
    System.out.println("Volume service destroied");

    getContentResolver().unregisterContentObserver(mVolumeObserver);
}



@Override
public IBinder onBind(Intent arg0) {

    return null;
}

}

Don't forget to declare it in the Android Manifest.xml

<service android:name=".service.VolumeService" >


There is no Broadcast Action to detect volume changes, but you could maybe every second or two check what the volume is with getStreamVolume and if you need to lock it at a specific volume, every second or two use: setStreamVolume

Check http://developer.android.com/reference/android/media/AudioManager.htm for more info.

You could use the AlarmManager class or a handler to check the volume every second or so.

If it's an activity, you can override onKeyDown to detect key presses. See http://developer.android.com/reference/android/view/View.html


This is one way to do it, you could just fix to a set volume instead of changing. My goal was to adjust system volume Service.

Also, avoid doing this only when needed.

public class VolumeKeyController {

    private MediaSessionCompat mMediaSession;
    private final Context mContext;

    public VolumeKeyController(Context context) {
        mContext = context;
    }

    private void createMediaSession() {
        mMediaSession = new MediaSessionCompat(mContext, KeyUtil.log);

        mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
                MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
        mMediaSession.setPlaybackState(new Builder()
                .setState(PlaybackStateCompat.STATE_PLAYING, 0, 0)
                .build());
        mMediaSession.setPlaybackToRemote(getVolumeProvider());
        mMediaSession.setActive(true);
    }

    private VolumeProviderCompat getVolumeProvider() {
        final AudioManager audio = mContext.getSystemService(Context.AUDIO_SERVICE);

        int STREAM_TYPE = AudioManager.STREAM_MUSIC;
        int currentVolume = audio.getStreamVolume(STREAM_TYPE);
        int maxVolume = audio.getStreamMaxVolume(STREAM_TYPE);
        final int VOLUME_UP = 1;
        final int VOLUME_DOWN = -1;

        return new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_RELATIVE, maxVolume, currentVolume) {
            @Override
            public void onAdjustVolume(int direction) {
                // Up = 1, Down = -1, Release = 0
                // Replace with your action, if you don't want to adjust system volume
                if (direction == VOLUME_UP) {
                    audio.adjustStreamVolume(STREAM_TYPE,
                            AudioManager.ADJUST_RAISE, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
                }
                else if (direction == VOLUME_DOWN) {
                    audio.adjustStreamVolume(STREAM_TYPE,
                            AudioManager.ADJUST_LOWER, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
                }
                setCurrentVolume(audio.getStreamVolume(STREAM_TYPE));
            }
        };
    }

    // Call when control needed, add a call to constructor if needed immediately
    public void setActive(boolean active) {
        if (mMediaSession != null) {
            mMediaSession.setActive(active);
            return;
        }
        createMediaSession();
    }

    // Call from Service's onDestroy method
    public void destroy() {
        if (mMediaSession != null) {
            mMediaSession.release();
        }
    }
}


You can capture volume/hardware key events by using accessibility service.

How to capture key events inside a service?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜