TransportPerformer.java revision 8c7c4c0409bd93f66fe39c5a5298a94f832be31e
18c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn/* 28c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Copyright (C) 2013 The Android Open Source Project 38c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * 48c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 58c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * you may not use this file except in compliance with the License. 68c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * You may obtain a copy of the License at 78c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * 88c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 98c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * 108c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Unless required by applicable law or agreed to in writing, software 118c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 128c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * See the License for the specific language governing permissions and 148c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * limitations under the License. 158c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn */ 168c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 178c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackbornpackage android.support.v4.media; 188c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 198c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackbornimport android.os.SystemClock; 208c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackbornimport android.view.KeyEvent; 218c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 228c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn/** 238c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Class through which you receive information about media transport actions. 248c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * These may either come from key events dispatched directly to your UI, or 258c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * events sent over a media button event receiver that this class keeps active 268c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * while your window is in focus. 278c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn */ 288c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackbornpublic abstract class TransportPerformer { 298c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public abstract void onStart(); 308c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 318c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public abstract void onStop(); 328c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 338c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public abstract void onPause(); 348c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 358c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public abstract int onGetDuration(); 368c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 378c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public abstract int onGetCurrentPosition(); 388c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 398c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public abstract void onSeekTo(int pos); 408c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 418c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public abstract boolean onIsPlaying(); 428c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 438c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public int onGetBufferPercentage() { 448c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return 100; 458c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 468c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 478c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn /** 488c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Retrieves the flags for the media transport control buttons that this transport supports. 498c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Result is a combination of the following flags: 508c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PREVIOUS}, 518c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_REWIND}, 528c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY}, 538c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY_PAUSE}, 548c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PAUSE}, 558c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_STOP}, 568c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_FAST_FORWARD}, 578c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_NEXT} 588c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * 598c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * <p>The default implementation returns: 608c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY}, 618c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY_PAUSE}, 628c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PAUSE}, and 638c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_STOP}</p> 648c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn */ 658c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public int onGetTransportControlFlags() { 668c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return TransportMediator.FLAG_KEY_MEDIA_PLAY 678c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn | TransportMediator.FLAG_KEY_MEDIA_PLAY_PAUSE 688c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn | TransportMediator.FLAG_KEY_MEDIA_PAUSE 698c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn | TransportMediator.FLAG_KEY_MEDIA_STOP; 708c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 718c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 728c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn /** 738c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Report that a media button has been pressed. This is like 748c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link android.view.KeyEvent.Callback#onKeyDown(int, android.view.KeyEvent)} but 758c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * will only deliver media keys. The default implementation handles these keys: 768c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * <ul> 778c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * <li>KEYCODE_MEDIA_PLAY: call {@link #onStart}</li> 788c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * <li>KEYCODE_MEDIA_PAUSE: call {@link #onPause}</li> 798c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * <li>KEYCODE_MEDIA_STOP: call {@link #onStop}</li> 808c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * <li>KEYCODE_MEDIA_PLAY_PAUSE and KEYCODE_HEADSETHOOK: call {@link #onPause} 818c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * if {@link #onIsPlaying()} returns true, otherwise call {@link #onStart}</li> 828c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * </ul> 838c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @param keyCode The code of the media key. 848c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @param event The full key event. 858c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @return Indicate whether the key has been consumed. The default 868c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * implementation always returns true. This only matters for keys 878c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * being dispatched here from 888c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#dispatchKeyEvent(android.view.KeyEvent) 898c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * TransportController.dispatchKeyEvent}, and determines whether the key 908c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * continues on to its default key handling (which for media keys means 918c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * being delivered to the current media remote control, which should 928c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * be us). 938c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn */ 948c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public boolean onMediaButtonDown(int keyCode, KeyEvent event) { 958c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn switch (keyCode) { 968c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn case TransportMediator.KEYCODE_MEDIA_PLAY: 978c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onStart(); 988c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return true; 998c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn case TransportMediator.KEYCODE_MEDIA_PAUSE: 1008c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onPause(); 1018c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return true; 1028c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn case KeyEvent.KEYCODE_MEDIA_STOP: 1038c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onStop(); 1048c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return true; 1058c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 1068c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn case KeyEvent.KEYCODE_HEADSETHOOK: 1078c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn if (onIsPlaying()) { 1088c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onPause(); 1098c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } else { 1108c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onStart(); 1118c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 1128c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 1138c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return true; 1148c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 1158c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 1168c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn /** 1178c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Report that a media button has been pressed. This is like 1188c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link KeyEvent.Callback#onKeyUp(int, android.view.KeyEvent)} but 1198c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * will only deliver media keys. The default implementation does nothing. 1208c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @param keyCode The code of the media key. 1218c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @param event The full key event. 1228c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @return Indicate whether the key has been consumed. The default 1238c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * implementation always returns true. This only matters for keys 1248c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * being dispatched here from 1258c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#dispatchKeyEvent(android.view.KeyEvent) 1268c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * TransportController.dispatchKeyEvent}, and determines whether the key 1278c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * continues on to its default key handling (which for media keys means 1288c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * being delivered to the current media remote control, which should 1298c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * be us). 1308c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn */ 1318c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public boolean onMediaButtonUp(int keyCode, KeyEvent event) { 1328c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return true; 1338c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 1348c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 1358c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn // Copy constants from framework since we can't link to them. 1368c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn static final int AUDIOFOCUS_GAIN = 1; 1378c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn static final int AUDIOFOCUS_GAIN_TRANSIENT = 2; 1388c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3; 1398c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN; 1408c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT; 1418c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = 1428c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; 1438c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 1448c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn /** 1458c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Report that audio focus has changed on the app. This only happens if 1468c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * you have indicated you have started playing with 1478c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#startPlaying TransportController.startPlaying}, 1488c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * which takes audio focus for you. 1498c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @param focusChange The type of focus change, as per 1508c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link android.media.AudioManager.OnAudioFocusChangeListener#onAudioFocusChange(int) 1518c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * OnAudioFocusChangeListener.onAudioFocusChange}. The default implementation will 1528c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * deliver a {@link KeyEvent#KEYCODE_MEDIA_STOP} 1538c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * when receiving {@link android.media.AudioManager#AUDIOFOCUS_LOSS}. 1548c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn */ 1558c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public void onAudioFocusChange(int focusChange) { 1568c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn int keyCode = 0; 1578c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn switch (focusChange) { 1588c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn case AUDIOFOCUS_LOSS: 1598c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn // This will cause us to stop playback, which means we drop audio focus 1608c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn // so we will not get any further audio focus gain. 1618c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn keyCode = TransportMediator.KEYCODE_MEDIA_PAUSE; 1628c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn break; 1638c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 1648c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn if (keyCode != 0) { 1658c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn final long now = SystemClock.uptimeMillis(); 1668c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onMediaButtonDown(keyCode, new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0)); 1678c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onMediaButtonUp(keyCode, new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0)); 1688c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 1698c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 1708c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn} 171