|
25 | 25 | import android.graphics.Color;
|
26 | 26 | import android.graphics.drawable.BitmapDrawable;
|
27 | 27 | import android.graphics.drawable.Drawable;
|
| 28 | +import android.media.AudioManager; |
28 | 29 | import android.net.Uri;
|
29 | 30 | import android.os.Bundle;
|
30 | 31 | import android.os.RemoteException;
|
|
49 | 50 | import android.util.SparseArray;
|
50 | 51 | import android.view.View;
|
51 | 52 | import android.view.ViewGroup;
|
| 53 | +import android.widget.AdapterView; |
52 | 54 | import android.widget.EditText;
|
53 | 55 | import android.widget.ImageButton;
|
54 | 56 | import android.widget.ImageView;
|
55 | 57 | import android.widget.Spinner;
|
56 | 58 | import android.widget.TextView;
|
57 | 59 | import android.widget.Toast;
|
| 60 | +import android.widget.ToggleButton; |
58 | 61 |
|
59 | 62 | import java.util.ArrayList;
|
60 | 63 | import java.util.Collections;
|
@@ -112,6 +115,7 @@ public class MediaAppControllerActivity extends AppCompatActivity {
|
112 | 115 | private MediaAppDetails mMediaAppDetails;
|
113 | 116 | private MediaControllerCompat mController;
|
114 | 117 | private MediaBrowserCompat mBrowser;
|
| 118 | + private AudioFocusHelper mAudioFocusHelper; |
115 | 119 |
|
116 | 120 | private View mRootView;
|
117 | 121 | private Spinner mInputTypeView;
|
@@ -332,6 +336,10 @@ private void setupButtons() {
|
332 | 336 | findViewById(R.id.action_prepare).setOnClickListener(preparePlayHandler);
|
333 | 337 | findViewById(R.id.action_play).setOnClickListener(preparePlayHandler);
|
334 | 338 |
|
| 339 | + mAudioFocusHelper = new AudioFocusHelper(this, |
| 340 | + (ToggleButton) findViewById(R.id.audio_focus_button), |
| 341 | + (Spinner) findViewById(R.id.audio_focus_type)); |
| 342 | + |
335 | 343 | mActionButtonMap.clear();
|
336 | 344 | final List<Action> mediaActions = Action.createActions(this);
|
337 | 345 | for (final Action action : mediaActions) {
|
@@ -638,6 +646,85 @@ private int getTint(@PlaybackStateCompat.Actions long actions,
|
638 | 646 | }
|
639 | 647 | }
|
640 | 648 |
|
| 649 | + /** |
| 650 | + * Helper class to manage audio focus requests and the UI surrounding this feature. |
| 651 | + */ |
| 652 | + private static class AudioFocusHelper |
| 653 | + implements View.OnClickListener, |
| 654 | + AudioManager.OnAudioFocusChangeListener, |
| 655 | + AdapterView.OnItemSelectedListener { |
| 656 | + |
| 657 | + /** |
| 658 | + * This list MUST match the order of the string-array |
| 659 | + * {@see R.array.audio_focus_types}. |
| 660 | + */ |
| 661 | + private static final int[] FOCUS_TYPES = { |
| 662 | + AudioManager.AUDIOFOCUS_GAIN, |
| 663 | + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, |
| 664 | + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK |
| 665 | + }; |
| 666 | + |
| 667 | + private final AudioManager mAudioManager; |
| 668 | + private final ToggleButton mToggleButton; |
| 669 | + private final Spinner mFocusTypeSpinner; |
| 670 | + |
| 671 | + private AudioFocusHelper(@NonNull Context context, |
| 672 | + @NonNull ToggleButton focusToggleButton, |
| 673 | + @NonNull Spinner focusTypeSpinner) { |
| 674 | + |
| 675 | + mAudioManager = (AudioManager) context.getSystemService(AUDIO_SERVICE); |
| 676 | + mToggleButton = focusToggleButton; |
| 677 | + mFocusTypeSpinner = focusTypeSpinner; |
| 678 | + |
| 679 | + mToggleButton.setOnClickListener(this); |
| 680 | + mFocusTypeSpinner.setOnItemSelectedListener(this); |
| 681 | + } |
| 682 | + |
| 683 | + @Override |
| 684 | + public void onClick(View v) { |
| 685 | + if (mToggleButton.isChecked()) { |
| 686 | + requestAudioFocus(getSelectedFocusType()); |
| 687 | + } else { |
| 688 | + mAudioManager.abandonAudioFocus(this); |
| 689 | + } |
| 690 | + } |
| 691 | + |
| 692 | + @Override |
| 693 | + public void onAudioFocusChange(int focusChange) { |
| 694 | + switch (focusChange) { |
| 695 | + case AudioManager.AUDIOFOCUS_GAIN: |
| 696 | + case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT: |
| 697 | + case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK: |
| 698 | + mToggleButton.setChecked(true); |
| 699 | + break; |
| 700 | + default: |
| 701 | + mToggleButton.setChecked(false); |
| 702 | + } |
| 703 | + } |
| 704 | + |
| 705 | + private int getSelectedFocusType() { |
| 706 | + return FOCUS_TYPES[mFocusTypeSpinner.getSelectedItemPosition()]; |
| 707 | + } |
| 708 | + |
| 709 | + private void requestAudioFocus(final int hint) { |
| 710 | + mAudioManager.requestAudioFocus(this, AudioManager.STREAM_VOICE_CALL, hint); |
| 711 | + } |
| 712 | + |
| 713 | + @Override |
| 714 | + public void onItemSelected(AdapterView> parent, View view, int position, long id) { |
| 715 | + // If we're holding audio focus and the type should change, automatically |
| 716 | + // request the new type of focus. |
| 717 | + if (mToggleButton.isChecked()) { |
| 718 | + requestAudioFocus(getSelectedFocusType()); |
| 719 | + } |
| 720 | + } |
| 721 | + |
| 722 | + @Override |
| 723 | + public void onNothingSelected(AdapterView> parent) { |
| 724 | + // Nothing to do. |
| 725 | + } |
| 726 | + } |
| 727 | + |
641 | 728 | private static class KeyComparator implements Comparator<String> {
|
642 | 729 | private final Set<String> mCapKeys = new HashSet<>();
|
643 | 730 |
|
|
0 commit comments