TransportPerformer.java revision 8c7c4c0409bd93f66fe39c5a5298a94f832be31e
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v4.media; 18 19import android.os.SystemClock; 20import android.view.KeyEvent; 21 22/** 23 * Class through which you receive information about media transport actions. 24 * These may either come from key events dispatched directly to your UI, or 25 * events sent over a media button event receiver that this class keeps active 26 * while your window is in focus. 27 */ 28public abstract class TransportPerformer { 29 public abstract void onStart(); 30 31 public abstract void onStop(); 32 33 public abstract void onPause(); 34 35 public abstract int onGetDuration(); 36 37 public abstract int onGetCurrentPosition(); 38 39 public abstract void onSeekTo(int pos); 40 41 public abstract boolean onIsPlaying(); 42 43 public int onGetBufferPercentage() { 44 return 100; 45 } 46 47 /** 48 * Retrieves the flags for the media transport control buttons that this transport supports. 49 * Result is a combination of the following flags: 50 * {@link TransportMediator#FLAG_KEY_MEDIA_PREVIOUS}, 51 * {@link TransportMediator#FLAG_KEY_MEDIA_REWIND}, 52 * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY}, 53 * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY_PAUSE}, 54 * {@link TransportMediator#FLAG_KEY_MEDIA_PAUSE}, 55 * {@link TransportMediator#FLAG_KEY_MEDIA_STOP}, 56 * {@link TransportMediator#FLAG_KEY_MEDIA_FAST_FORWARD}, 57 * {@link TransportMediator#FLAG_KEY_MEDIA_NEXT} 58 * 59 * <p>The default implementation returns: 60 * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY}, 61 * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY_PAUSE}, 62 * {@link TransportMediator#FLAG_KEY_MEDIA_PAUSE}, and 63 * {@link TransportMediator#FLAG_KEY_MEDIA_STOP}</p> 64 */ 65 public int onGetTransportControlFlags() { 66 return TransportMediator.FLAG_KEY_MEDIA_PLAY 67 | TransportMediator.FLAG_KEY_MEDIA_PLAY_PAUSE 68 | TransportMediator.FLAG_KEY_MEDIA_PAUSE 69 | TransportMediator.FLAG_KEY_MEDIA_STOP; 70 } 71 72 /** 73 * Report that a media button has been pressed. This is like 74 * {@link android.view.KeyEvent.Callback#onKeyDown(int, android.view.KeyEvent)} but 75 * will only deliver media keys. The default implementation handles these keys: 76 * <ul> 77 * <li>KEYCODE_MEDIA_PLAY: call {@link #onStart}</li> 78 * <li>KEYCODE_MEDIA_PAUSE: call {@link #onPause}</li> 79 * <li>KEYCODE_MEDIA_STOP: call {@link #onStop}</li> 80 * <li>KEYCODE_MEDIA_PLAY_PAUSE and KEYCODE_HEADSETHOOK: call {@link #onPause} 81 * if {@link #onIsPlaying()} returns true, otherwise call {@link #onStart}</li> 82 * </ul> 83 * @param keyCode The code of the media key. 84 * @param event The full key event. 85 * @return Indicate whether the key has been consumed. The default 86 * implementation always returns true. This only matters for keys 87 * being dispatched here from 88 * {@link TransportMediator#dispatchKeyEvent(android.view.KeyEvent) 89 * TransportController.dispatchKeyEvent}, and determines whether the key 90 * continues on to its default key handling (which for media keys means 91 * being delivered to the current media remote control, which should 92 * be us). 93 */ 94 public boolean onMediaButtonDown(int keyCode, KeyEvent event) { 95 switch (keyCode) { 96 case TransportMediator.KEYCODE_MEDIA_PLAY: 97 onStart(); 98 return true; 99 case TransportMediator.KEYCODE_MEDIA_PAUSE: 100 onPause(); 101 return true; 102 case KeyEvent.KEYCODE_MEDIA_STOP: 103 onStop(); 104 return true; 105 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 106 case KeyEvent.KEYCODE_HEADSETHOOK: 107 if (onIsPlaying()) { 108 onPause(); 109 } else { 110 onStart(); 111 } 112 } 113 return true; 114 } 115 116 /** 117 * Report that a media button has been pressed. This is like 118 * {@link KeyEvent.Callback#onKeyUp(int, android.view.KeyEvent)} but 119 * will only deliver media keys. The default implementation does nothing. 120 * @param keyCode The code of the media key. 121 * @param event The full key event. 122 * @return Indicate whether the key has been consumed. The default 123 * implementation always returns true. This only matters for keys 124 * being dispatched here from 125 * {@link TransportMediator#dispatchKeyEvent(android.view.KeyEvent) 126 * TransportController.dispatchKeyEvent}, and determines whether the key 127 * continues on to its default key handling (which for media keys means 128 * being delivered to the current media remote control, which should 129 * be us). 130 */ 131 public boolean onMediaButtonUp(int keyCode, KeyEvent event) { 132 return true; 133 } 134 135 // Copy constants from framework since we can't link to them. 136 static final int AUDIOFOCUS_GAIN = 1; 137 static final int AUDIOFOCUS_GAIN_TRANSIENT = 2; 138 static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3; 139 static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN; 140 static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT; 141 static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = 142 -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; 143 144 /** 145 * Report that audio focus has changed on the app. This only happens if 146 * you have indicated you have started playing with 147 * {@link TransportMediator#startPlaying TransportController.startPlaying}, 148 * which takes audio focus for you. 149 * @param focusChange The type of focus change, as per 150 * {@link android.media.AudioManager.OnAudioFocusChangeListener#onAudioFocusChange(int) 151 * OnAudioFocusChangeListener.onAudioFocusChange}. The default implementation will 152 * deliver a {@link KeyEvent#KEYCODE_MEDIA_STOP} 153 * when receiving {@link android.media.AudioManager#AUDIOFOCUS_LOSS}. 154 */ 155 public void onAudioFocusChange(int focusChange) { 156 int keyCode = 0; 157 switch (focusChange) { 158 case AUDIOFOCUS_LOSS: 159 // This will cause us to stop playback, which means we drop audio focus 160 // so we will not get any further audio focus gain. 161 keyCode = TransportMediator.KEYCODE_MEDIA_PAUSE; 162 break; 163 } 164 if (keyCode != 0) { 165 final long now = SystemClock.uptimeMillis(); 166 onMediaButtonDown(keyCode, new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0)); 167 onMediaButtonUp(keyCode, new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0)); 168 } 169 } 170} 171