blob: 83c810ee1e53675f5e07f77e0d9e4fabbc630ede [file] [log] [blame]
/*
* 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;
}
}
}
}