/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.support.v4.media;
import android.os.SystemClock;
import android.view.KeyEvent;
/**
* Class through which you receive information about media transport actions.
* These may either come from key events dispatched directly to your UI, or
* events sent over a media button event receiver that this class keeps active
* while your window is in focus.
*/
public abstract class TransportPerformer {
public abstract void onStart();
public abstract void onStop();
public abstract void onPause();
public abstract int onGetDuration();
public abstract int onGetCurrentPosition();
public abstract void onSeekTo(int pos);
public abstract boolean onIsPlaying();
public int onGetBufferPercentage() {
return 100;
}
/**
* Retrieves the flags for the media transport control buttons that this transport supports.
* Result is a combination of the following flags:
* {@link TransportMediator#FLAG_KEY_MEDIA_PREVIOUS},
* {@link TransportMediator#FLAG_KEY_MEDIA_REWIND},
* {@link TransportMediator#FLAG_KEY_MEDIA_PLAY},
* {@link TransportMediator#FLAG_KEY_MEDIA_PLAY_PAUSE},
* {@link TransportMediator#FLAG_KEY_MEDIA_PAUSE},
* {@link TransportMediator#FLAG_KEY_MEDIA_STOP},
* {@link TransportMediator#FLAG_KEY_MEDIA_FAST_FORWARD},
* {@link TransportMediator#FLAG_KEY_MEDIA_NEXT}
*
*
The default implementation returns:
* {@link TransportMediator#FLAG_KEY_MEDIA_PLAY},
* {@link TransportMediator#FLAG_KEY_MEDIA_PLAY_PAUSE},
* {@link TransportMediator#FLAG_KEY_MEDIA_PAUSE}, and
* {@link TransportMediator#FLAG_KEY_MEDIA_STOP}
*/
public int onGetTransportControlFlags() {
return TransportMediator.FLAG_KEY_MEDIA_PLAY
| TransportMediator.FLAG_KEY_MEDIA_PLAY_PAUSE
| TransportMediator.FLAG_KEY_MEDIA_PAUSE
| TransportMediator.FLAG_KEY_MEDIA_STOP;
}
/**
* Report that a media button has been pressed. This is like
* {@link android.view.KeyEvent.Callback#onKeyDown(int, android.view.KeyEvent)} but
* will only deliver media keys. The default implementation handles these keys:
*
* - KEYCODE_MEDIA_PLAY: call {@link #onStart}
* - KEYCODE_MEDIA_PAUSE: call {@link #onPause}
* - KEYCODE_MEDIA_STOP: call {@link #onStop}
* - KEYCODE_MEDIA_PLAY_PAUSE and KEYCODE_HEADSETHOOK: call {@link #onPause}
* if {@link #onIsPlaying()} returns true, otherwise call {@link #onStart}
*
* @param keyCode The code of the media key.
* @param event The full key event.
* @return Indicate whether the key has been consumed. The default
* implementation always returns true. This only matters for keys
* being dispatched here from
* {@link TransportMediator#dispatchKeyEvent(android.view.KeyEvent)
* TransportController.dispatchKeyEvent}, and determines whether the key
* continues on to its default key handling (which for media keys means
* being delivered to the current media remote control, which should
* be us).
*/
public boolean onMediaButtonDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case TransportMediator.KEYCODE_MEDIA_PLAY:
onStart();
return true;
case TransportMediator.KEYCODE_MEDIA_PAUSE:
onPause();
return true;
case KeyEvent.KEYCODE_MEDIA_STOP:
onStop();
return true;
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
case KeyEvent.KEYCODE_HEADSETHOOK:
if (onIsPlaying()) {
onPause();
} else {
onStart();
}
}
return true;
}
/**
* Report that a media button has been pressed. This is like
* {@link KeyEvent.Callback#onKeyUp(int, android.view.KeyEvent)} but
* will only deliver media keys. The default implementation does nothing.
* @param keyCode The code of the media key.
* @param event The full key event.
* @return Indicate whether the key has been consumed. The default
* implementation always returns true. This only matters for keys
* being dispatched here from
* {@link TransportMediator#dispatchKeyEvent(android.view.KeyEvent)
* TransportController.dispatchKeyEvent}, and determines whether the key
* continues on to its default key handling (which for media keys means
* being delivered to the current media remote control, which should
* be us).
*/
public boolean onMediaButtonUp(int keyCode, KeyEvent event) {
return true;
}
// Copy constants from framework since we can't link to them.
static final int AUDIOFOCUS_GAIN = 1;
static final int AUDIOFOCUS_GAIN_TRANSIENT = 2;
static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3;
static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN;
static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT;
static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK =
-1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;
/**
* Report that audio focus has changed on the app. This only happens if
* you have indicated you have started playing with
* {@link TransportMediator#startPlaying TransportController.startPlaying},
* which takes audio focus for you.
* @param focusChange The type of focus change, as per
* {@link android.media.AudioManager.OnAudioFocusChangeListener#onAudioFocusChange(int)
* OnAudioFocusChangeListener.onAudioFocusChange}. The default implementation will
* deliver a {@link KeyEvent#KEYCODE_MEDIA_STOP}
* when receiving {@link android.media.AudioManager#AUDIOFOCUS_LOSS}.
*/
public void onAudioFocusChange(int focusChange) {
int keyCode = 0;
switch (focusChange) {
case AUDIOFOCUS_LOSS:
// This will cause us to stop playback, which means we drop audio focus
// so we will not get any further audio focus gain.
keyCode = TransportMediator.KEYCODE_MEDIA_PAUSE;
break;
}
if (keyCode != 0) {
final long now = SystemClock.uptimeMillis();
onMediaButtonDown(keyCode, new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0));
onMediaButtonUp(keyCode, new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0));
}
}
}