| /* |
| * Copyright 2017 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 com.example.android.mediasession.service; |
| |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.media.AudioManager; |
| import android.net.wifi.WifiManager; |
| import android.support.annotation.NonNull; |
| import android.support.v4.media.MediaMetadataCompat; |
| import android.support.v4.media.session.PlaybackStateCompat; |
| |
| /** |
| * Abstract player implementation that handles playing music with proper handling of headphones |
| * and audio focus. |
| */ |
| public abstract class PlayerAdapter { |
| |
| private static final float MEDIA_VOLUME_DEFAULT = 1.0f; |
| private static final float MEDIA_VOLUME_DUCK = 0.2f; |
| |
| private static final IntentFilter AUDIO_NOISY_INTENT_FILTER = |
| new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY); |
| |
| private boolean mAudioNoisyReceiverRegistered = false; |
| private final BroadcastReceiver mAudioNoisyReceiver = |
| new BroadcastReceiver() { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) { |
| if (isPlaying()) { |
| pause(); |
| } |
| } |
| } |
| }; |
| |
| private final Context mApplicationContext; |
| private final AudioManager mAudioManager; |
| private final AudioFocusHelper mAudioFocusHelper; |
| |
| private boolean mPlayOnAudioFocus = false; |
| |
| public PlayerAdapter(@NonNull Context context) { |
| mApplicationContext = context.getApplicationContext(); |
| mAudioManager = (AudioManager) mApplicationContext.getSystemService(Context.AUDIO_SERVICE); |
| mAudioFocusHelper = new AudioFocusHelper(); |
| } |
| |
| public abstract void playFromMedia(MediaMetadataCompat metadata); |
| |
| public abstract MediaMetadataCompat getCurrentMedia(); |
| |
| public abstract boolean isPlaying(); |
| |
| public final void play() { |
| if (mAudioFocusHelper.requestAudioFocus()) { |
| registerAudioNoisyReceiver(); |
| onPlay(); |
| } |
| } |
| |
| /** |
| * Called when media is ready to be played and indicates the app has audio focus. |
| */ |
| protected abstract void onPlay(); |
| |
| public final void pause() { |
| if (!mPlayOnAudioFocus) { |
| mAudioFocusHelper.abandonAudioFocus(); |
| } |
| |
| unregisterAudioNoisyReceiver(); |
| onPause(); |
| } |
| |
| /** |
| * Called when media must be paused. |
| */ |
| protected abstract void onPause(); |
| |
| public final void stop() { |
| mAudioFocusHelper.abandonAudioFocus(); |
| unregisterAudioNoisyReceiver(); |
| onStop(); |
| } |
| |
| /** |
| * Called when the media must be stopped. The player should clean up resources at this |
| * point. |
| */ |
| protected abstract void onStop(); |
| |
| public abstract void seekTo(long position); |
| |
| public abstract void setVolume(float volume); |
| |
| private void registerAudioNoisyReceiver() { |
| if (!mAudioNoisyReceiverRegistered) { |
| mApplicationContext.registerReceiver(mAudioNoisyReceiver, AUDIO_NOISY_INTENT_FILTER); |
| mAudioNoisyReceiverRegistered = true; |
| } |
| } |
| |
| private void unregisterAudioNoisyReceiver() { |
| if (mAudioNoisyReceiverRegistered) { |
| mApplicationContext.unregisterReceiver(mAudioNoisyReceiver); |
| mAudioNoisyReceiverRegistered = false; |
| } |
| } |
| |
| /** |
| * Helper class for managing audio focus related tasks. |
| */ |
| private final class AudioFocusHelper |
| implements AudioManager.OnAudioFocusChangeListener { |
| |
| private boolean requestAudioFocus() { |
| final int result = mAudioManager.requestAudioFocus(this, |
| AudioManager.STREAM_MUSIC, |
| AudioManager.AUDIOFOCUS_GAIN); |
| return result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED; |
| } |
| |
| private void abandonAudioFocus() { |
| mAudioManager.abandonAudioFocus(this); |
| } |
| |
| @Override |
| public void onAudioFocusChange(int focusChange) { |
| switch (focusChange) { |
| case AudioManager.AUDIOFOCUS_GAIN: |
| if (mPlayOnAudioFocus && !isPlaying()) { |
| play(); |
| } else if (isPlaying()) { |
| setVolume(MEDIA_VOLUME_DEFAULT); |
| } |
| mPlayOnAudioFocus = false; |
| break; |
| case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: |
| setVolume(MEDIA_VOLUME_DUCK); |
| break; |
| case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: |
| if (isPlaying()) { |
| mPlayOnAudioFocus = true; |
| pause(); |
| } |
| break; |
| case AudioManager.AUDIOFOCUS_LOSS: |
| mAudioManager.abandonAudioFocus(this); |
| mPlayOnAudioFocus = false; |
| stop(); |
| break; |
| } |
| } |
| } |
| } |