Skip to content
This repository has been archived by the owner on Aug 27, 2024. It is now read-only.

Commit

Permalink
fine tuning of audiofocus behavior & clean-up
Browse files Browse the repository at this point in the history
  • Loading branch information
y20k committed Jan 10, 2018
1 parent a9ba3fe commit 07a3c73
Show file tree
Hide file tree
Showing 14 changed files with 47 additions and 133 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ Help is very welcome. Be it in the form of code, or artwork, or enhancements to
### Suggested issues to tackle
[#145](https://github.com/y20k/transistor/issues/145) | [#136](https://github.com/y20k/transistor/issues/136) | [#126](https://github.com/y20k/transistor/issues/126) | [#121](https://github.com/y20k/transistor/issues/121) | [#89](https://github.com/y20k/transistor/issues/89)

### Credt for your contributions
### Credit for your contributions
Contributors - like the main translators for a certain language - are listed as co-autors of this project in [AUTHORS.md](https://github.com/y20k/transistor/blob/master/AUTHORS.md). Bonus: If you are on this list, you are automatically eligable for a free German beverage.
To be redeemed in Stuttgart.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ README
Transistor - Radio App for Android
----------------------------------

**Version 3.0.x BETA ("Oh! You Pretty Things")**
**Version 3.0.x ("Oh! You Pretty Things")**

Transistor is a bare bones app for listening to radio programs over the internet. The app stores stations as files on your device's external storage. It currently understands streams encoded in MP3, AAC and Ogg/Opus(*).

Expand Down
6 changes: 3 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ android {

vectorDrawables.useSupportLibrary = true

resConfigs "en", "ca", "de", "el", "es", "eu", "fr", "ja", "kab", "nb-rNO", "pl", "ru", "sl", "sr", "tr", "uk", "v21", "v24", "w820dp", "zh-rCN"
resConfigs "en", "ca", "de", "el", "es", "eu", "fr", "ja", "kab", "nb-rNO", "pl", "ru", "sl", "sr", "tr", "uk", "zh-rCN"

}
buildTypes {
Expand Down Expand Up @@ -42,7 +42,7 @@ dependencies {
implementation project(':exoplayer-library-core')
implementation project(':exoplayer-library-hls')

implementation 'android.arch.lifecycle:extensions:' + archLifecycleVersion;
annotationProcessor 'android.arch.lifecycle:compiler:' + archLifecycleVersion;
implementation 'android.arch.lifecycle:extensions:' + archLifecycleVersion
annotationProcessor 'android.arch.lifecycle:compiler:' + archLifecycleVersion

}
7 changes: 4 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.y20k.transistor">

<uses-permission android:name="android.permission.INTERNET" />
Expand Down Expand Up @@ -104,7 +104,8 @@
<!-- android:exported="true" if used with Android Auto -->
<service
android:name=".PlayerService"
android:exported="true">
android:exported="true"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/org/y20k/transistor/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ private boolean handleStationImageChange(Intent data) {
// update live data
mCollectionViewModel.getStationList().setValue(newStationList);

// reset mTemopStation
// reset mTempStation
mTempStation = null;

return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ public boolean minimizePlayer() {
}


/* Refreshes list of stations - used by pull to refesh */
/* Refreshes list of stations - used by pull to refresh */
private void refreshList() {
// // stop player service using intent
// Intent intent = new Intent(mActivity, PlayerService.class);
Expand Down Expand Up @@ -758,7 +758,7 @@ public void onDismissed(Snackbar transientBottomBar, int event) {
}
});
// stretch Snackbar
(mSleepTimerNotification.getView()).getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;;
(mSleepTimerNotification.getView()).getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
mSleepTimerNotification.show();
}

Expand Down Expand Up @@ -928,7 +928,7 @@ else if (!(newMetaData.equals(oldMetaData))) {
if (mSleepTimerRunning && newStation.getPlaybackState() == PLAYBACK_STATE_STOPPED) {
stopSleepTimer();
}
// update station currently used by player servic
// update station currently used by player service
mPlayerServiceStation = newStation;
}
}
Expand Down
140 changes: 28 additions & 112 deletions app/src/main/java/org/y20k/transistor/PlayerService.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,11 @@ public final class PlayerService extends MediaBrowserServiceCompat implements Tr
private static Station mStation;
private PackageValidator mPackageValidator;
private StationListProvider mStationListProvider;
private AudioManager mAudioManager;
private AudioFocusHelper mAudioFocusHelper;
private AudioAttributesCompat mAudioAttributes;
private AudioFocusRequestCompat mAudioFocusRequest;
private static MediaSessionCompat mSession;
private static MediaControllerCompat mController;
private boolean mStationMetadataReceived;
private boolean mAudioFocusLossTransient;
private boolean mPlayerInitLock;
private HeadphoneUnplugReceiver mHeadphoneUnplugReceiver;
private WifiManager.WifiLock mWifiLock;
Expand All @@ -141,8 +139,6 @@ public void onCreate() {
super.onCreate();

// set up variables
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mAudioFocusLossTransient = false;
mStationMetadataReceived = false;
mPlayerInitLock = false;
mSession = createMediaSession(this);
Expand All @@ -159,15 +155,12 @@ public void onCreate() {
mStationListProvider = new StationListProvider();
mPackageValidator = new PackageValidator(this);

// build audio attributes
mAudioAttributes = new AudioAttributesCompat.Builder()
.setUsage(C.USAGE_MEDIA)
.setContentType(C.CONTENT_TYPE_MUSIC)
.build();

// create audiofocus helper
// create audio focus helper
mAudioFocusHelper = new AudioFocusHelper(this);

// create audio focus request
mAudioFocusRequest = createFocusRequest();

// create media controller
try {
mController = new MediaControllerCompat(getApplicationContext(), mSession.getSessionToken());
Expand All @@ -177,7 +170,7 @@ public void onCreate() {
}

// get instance of mPlayer
createPlayer(mAudioAttributes);
createPlayer();
}


Expand Down Expand Up @@ -458,37 +451,34 @@ public void onStationListReady(boolean success) {

}


@Override
/* Checks if player is playing - method required by AudioFocusAwarePlayer */
public boolean isPlaying() {
LogHelper.e(LOG_TAG, "!!! is playing?" + mPlayer.getPlayWhenReady()); // todo remove
// checks if player is playing (method required by AudioFocusAwarePlayer)
return mPlayer.getPlayWhenReady();
}


@Override
/* Starts playback - method required by AudioFocusAwarePlayer */
public void play() {
// start the stream
// start the stream (method required by AudioFocusAwarePlayer)
mPlayer.setPlayWhenReady(true);
// mController.getTransportControls().play();
}


@Override
/* Pauses / stops playback - method required by AudioFocusAwarePlayer */
public void pause() {
// just stop the stream
// just stop the stream (method required by AudioFocusAwarePlayer)
mPlayer.setPlayWhenReady(false);
// mController.getTransportControls().stop();
}


@Override
/* Stops playback - method required by AudioFocusAwarePlayer */
public void stop() {
// stop the stream
mController.getTransportControls().stop();
// stop the stream (method required by AudioFocusAwarePlayer)
mController.getTransportControls().pause();
}


Expand All @@ -500,54 +490,6 @@ public void setVolume(float volume) {
}



// @Override
// public void onAudioFocusChange(int focusChange) {
// switch (focusChange) {
// // gain of audio focus of unknown duration
// case AudioManager.AUDIOFOCUS_GAIN:
// if (mAudioFocusLossTransient) {
// // AUDIOFOCUS_GAIN after AUDIOFOCUS_LOSS_TRANSIENT -> restart playback
// mController.getTransportControls().play();
// mAudioFocusLossTransient = false;
// } else if (mStation.getPlaybackState() != PLAYBACK_STATE_STOPPED) {
// // AUDIOFOCUS_GAIN after AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> raise volume again
// if (mPlayer == null) {
// initializePlayer();
// mPlayer.setPlayWhenReady(true);
// } else if (mPlayer.getPlayWhenReady()) {
// mPlayer.setPlayWhenReady(true);
// }
// mPlayer.setVolume(1.0f);
// }
// break;
// // loss of audio focus of unknown duration
// case AudioManager.AUDIOFOCUS_LOSS:
// if (mStation.getPlaybackState() != PLAYBACK_STATE_STOPPED && mPlayer.getPlayWhenReady()) {
// mController.getTransportControls().pause();
// }
// break;
// // transient loss of audio focus - e.g. phone call
// case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
// if (mStation.getPlaybackState() != PLAYBACK_STATE_STOPPED && mPlayer != null && mPlayer.getPlayWhenReady()) {
// mAudioFocusLossTransient = true;
// mController.getTransportControls().pause();
// }
// else if (mStation.getPlaybackState() == PLAYBACK_STATE_STOPPED && mPlayer != null && mPlayer.getPlayWhenReady()) {
// mAudioFocusLossTransient = true;
// mPlayer.setPlayWhenReady(false);
// }
// break;
// // temporary external request of audio focus
// case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// if (mPlayer != null && mPlayer.getPlayWhenReady()){
// mPlayer.setVolume(0.1f);
// }
// break;
// }
// }


@Override
public void onDestroy() {
super.onDestroy();
Expand Down Expand Up @@ -626,8 +568,8 @@ private void startPlayback() {
mWakeLock.acquire(); // needs android.permission.WAKE_LOCK
}

// request focus and initialize media mPlayer
if (mStation.getStreamUri() != null && requestFocus(mAudioAttributes)) {
// request audio focus and initialize media mPlayer
if (mStation.getStreamUri() != null && mAudioFocusHelper.requestAudioFocus(mAudioFocusRequest)) {
// initialize player and start playback
initializePlayer();
mPlayer.setPlayWhenReady(true);
Expand Down Expand Up @@ -694,7 +636,7 @@ private void stopPlayback(boolean dismissNotification) {
LogHelper.v(LOG_TAG, "Stopping playback. Station name:" + mStation.getStationName());

// give up audio focus
giveUpAudioFocus();
mAudioFocusHelper.abandonAudioFocus(mAudioFocusRequest);

// update playback state
mSession.setPlaybackState(createSessionPlaybackState());
Expand Down Expand Up @@ -728,7 +670,7 @@ private void stopPlayback(boolean dismissNotification) {


/* Creates an instance of SimpleExoPlayer */
private void createPlayer(AudioAttributesCompat audioAttributes) {
private void createPlayer() {

if (mPlayer != null) {
releasePlayer();
Expand All @@ -742,9 +684,6 @@ private void createPlayer(AudioAttributesCompat audioAttributes) {

// create the player
mPlayer = ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(getApplicationContext()), trackSelector, loadControl);

// set audio attributes
// mPlayer.setAudioAttributes((AudioAttributes)audioAttributes); // todo remove or reenable
}


Expand All @@ -761,12 +700,10 @@ private void preparePLayer(int connectionType) {
// TODO HLS does not work reliable
Toast.makeText(this, this.getString(R.string.toastmessage_stream_may_not_work), Toast.LENGTH_LONG).show();
dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, mUserAgent), bandwidthMeter);
// mediaSource = new HlsMediaSource(mStation.getStreamUri(), dataSourceFactory, null, null);
mediaSource = new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mStation.getStreamUri());
} else {
dataSourceFactory = new CustomDefaultHttpDataSourceFactory(mUserAgent, bandwidthMeter, true, playerCallback);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// mediaSource = new ExtractorMediaSource(mStation.getStreamUri(), dataSourceFactory, extractorsFactory, 32, null, null, null, (1024 * 1024)); // todo attach listener here
mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory).setContinueLoadingCheckIntervalBytes(32).createMediaSource(mStation.getStreamUri());
}
// prepare player with source.
Expand All @@ -790,43 +727,22 @@ private void initializePlayer() {
}


/* Request audio manager focus */
private boolean requestFocus(AudioAttributesCompat audioAttributes) {
AudioFocusRequestCompat focusRequest =
new AudioFocusRequestCompat.Builder(AudioManager.AUDIOFOCUS_GAIN)
.setOnAudioFocusChangeListener(mAudioFocusHelper.getListenerForPlayer(this))
.setAudioAttributes(audioAttributes)
.setFocusGain(AudioManager.AUDIOFOCUS_GAIN)
.setWillPauseWhenDucked(false)
.setAcceptsDelayedFocusGain(true)
.build();
return mAudioFocusHelper.requestAudioFocus(focusRequest);
// LogHelper.e(LOG_TAG, "!!! Request Focus."); // todo remove
// int result = mAudioManager.requestAudioFocus(this,
// AudioManager.STREAM_MUSIC,
// AudioManager.AUDIOFOCUS_GAIN);
// return result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}

/* Creates request for AudioFocus */
private AudioFocusRequestCompat createFocusRequest() {
// build audio attributes
AudioAttributesCompat audioAttributes = new AudioAttributesCompat.Builder()
.setUsage(C.USAGE_MEDIA)
.setContentType(C.CONTENT_TYPE_MUSIC)
.build();

/* Give up audio focus - if not transient */ // todo check if this works !!!
private void giveUpAudioFocus() {
AudioFocusRequestCompat focusRequest =
new AudioFocusRequestCompat.Builder(AudioManager.AUDIOFOCUS_GAIN)
// built and return focus request
return new AudioFocusRequestCompat.Builder(AudioManager.AUDIOFOCUS_GAIN)
.setOnAudioFocusChangeListener(mAudioFocusHelper.getListenerForPlayer(this))
// .setAudioAttributes(audioAttributes)
.setAudioAttributes(audioAttributes)
.setFocusGain(AudioManager.AUDIOFOCUS_GAIN)
.setWillPauseWhenDucked(false)
.setAcceptsDelayedFocusGain(false) // todo check if this flag can be turned on (true)
.build();
mAudioFocusHelper.abandonAudioFocus(focusRequest);

// if (mAudioFocusLossTransient) {
// // do not give up focus when focus loss is just transient
// return false;
// } else {
// // give up audio focus
// int result = mAudioManager.abandonAudioFocus(this);
// return result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
// }
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position)

// CASE ADD NEW
if (holder instanceof AddNewViewHolder) {
// get referece to AddNewViewHolder and listen for taps
// get reference to AddNewViewHolder and listen for taps
AddNewViewHolder addNewViewHolder = (AddNewViewHolder) holder;
addNewViewHolder.getLListItemAddNewLayout().setOnClickListener (new View.OnClickListener () {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public int getStationImageColor() {

// extract color palette from station image
Palette palette = Palette.from(mInputImage).generate();
// get musted and vibrant swatches
// get muted and vibrant swatches
Palette.Swatch vibrantSwatch = palette.getVibrantSwatch();
Palette.Swatch mutedSwatch = palette.getMutedSwatch();

Expand All @@ -125,7 +125,7 @@ public int getStationImageColor() {



/* Creates station image on a circular background with defaukt color */
/* Creates station image on a circular background with default color */
public Bitmap createCircularFramedImage(int size) {
// get default color
int color = ContextCompat.getColor(mContext, R.color.transistor_grey_lighter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
*/
public final class LogHelper {

private final static boolean mTesting = true;
private final static boolean mTesting = false;

public static void d(final String tag, String message) {
// include logging only in debug versions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public interface PlayerCallback {
* This method is called when the player creates a new AudioTrack object
* - before any PCM data are fed into it.
*
* @param value the metadata value
* @param audioTrack the AudioTrack object
*/
public void playerAudioTrackCreated( AudioTrack audioTrack );

Expand Down
Loading

0 comments on commit 07a3c73

Please sign in to comment.