Skip to content

Commit

Permalink
Merge pull request #22 from SoftwareEngineeringDaily/develop
Browse files Browse the repository at this point in the history
Release v1.0.1
  • Loading branch information
MostafaGazar authored Jul 16, 2019
2 parents dff5d24 + 4e10998 commit ade6c5a
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 77 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,4 @@ Interested in seeing a particular feature implemented in this app? Please open a

Contributing
------------
Checkout [CONTRIBUTING.md](https://github.com/SoftwareEngineeringDaily/software-engineering-daily-android/CONTRIBUTING.md) for details.
Checkout [CONTRIBUTING.md](https://github.com/SoftwareEngineeringDaily/software-engineering-daily-android/blob/master/CONTRIBUTING.md) for details.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ android {
applicationId "com.koalatea.sedaily"
minSdkVersion 21
targetSdkVersion 29
versionCode 16
versionName "1.0.0"
versionCode 17
versionName "1.0.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ class EpisodeDetailFragment : BaseFragment() {
is PlayerStatus.Playing -> showStopViews()
is PlayerStatus.Paused -> showPlayViews()
is PlayerStatus.Ended -> showPlayViews()
is PlayerStatus.Cancelled -> showPlayViews()
is PlayerStatus.Error -> acknowledgeGenericError()
}
}
Expand Down
154 changes: 88 additions & 66 deletions app/src/main/java/com/koalatea/sedaily/feature/player/AudioService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class AudioService : LifecycleService() {

var episodeId: String? = null
private set
private var episodeTitle: String? = null

private lateinit var exoPlayer: SimpleExoPlayer

Expand Down Expand Up @@ -117,75 +118,18 @@ class AudioService : LifecycleService() {
.build()
exoPlayer.setAudioAttributes(audioAttributes, true)

// Monitor ExoPlayer events.
exoPlayer.addListener(PlayerEventListener())
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
handleIntent(intent)

return super.onStartCommand(intent, flags, startId)
}

override fun onDestroy() {
cancelPlaybackMonitor()

mediaSession?.release()
mediaSessionConnector?.setPlayer(null)
playerNotificationManager?.setPlayer(null)

exoPlayer.release()

super.onDestroy()
}

@MainThread
fun play(uri: Uri, startPosition: Long, playbackSpeed: Float? = null) {
val userAgent = Util.getUserAgent(applicationContext, BuildConfig.APPLICATION_ID)
val mediaSource = ExtractorMediaSource(
uri,
DefaultDataSourceFactory(applicationContext, userAgent),
DefaultExtractorsFactory(),
null,
null)

val haveStartPosition = startPosition != C.POSITION_UNSET.toLong()
if (haveStartPosition) {
exoPlayer.seekTo(startPosition)
}

playbackSpeed?.let { changePlaybackSpeed(playbackSpeed) }

exoPlayer.prepare(mediaSource, !haveStartPosition, false)
exoPlayer.playWhenReady = true
}

@MainThread
fun resume() {
exoPlayer.playWhenReady = true
}

@MainThread
fun pause() {
exoPlayer.playWhenReady = false
}

@MainThread
fun changePlaybackSpeed(playbackSpeed: Float) {
exoPlayer.playbackParameters = PlaybackParameters(playbackSpeed)
}

@MainThread
private fun handleIntent(intent: Intent?) {
episodeId = intent?.getStringExtra(ARG_EPISODE_ID)

// Setup notification and media session.
playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
applicationContext,
PLAYBACK_CHANNEL_ID,
R.string.playback_channel_name,
PLAYBACK_NOTIFICATION_ID,
object : PlayerNotificationManager.MediaDescriptionAdapter {
override fun getCurrentContentTitle(player: Player): String {
return intent?.getStringExtra(ARG_TITLE) ?: getString(R.string.loading_dots)
return episodeTitle ?: getString(R.string.loading_dots)
}

@Nullable
Expand All @@ -211,13 +155,28 @@ class AudioService : LifecycleService() {
}

override fun onNotificationCancelled(notificationId: Int) {
_playerStatusLiveData.value = PlayerStatus.Cancelled(episodeId)

stopSelf()
}

override fun onNotificationPosted(notificationId: Int, notification: Notification?, ongoing: Boolean) {
if (ongoing) {
// Make sure the service will not get destroyed while playing media.
startForeground(notificationId, notification)
} else {
// Make notification cancellable.
stopForeground(false)
}
}
}
).apply {
// omit skip previous and next actions
// Omit skip previous and next actions.
setUseNavigationActions(false)

// Add stop action.
setUseStopAction(true)

val incrementMs = resources.getInteger(R.integer.increment_ms).toLong()
setFastForwardIncrementMs(incrementMs)
setRewindIncrementMs(incrementMs)
Expand All @@ -240,7 +199,7 @@ class AudioService : LifecycleService() {
putParcelable(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, bitmap)
}

val title = intent?.getStringExtra(ARG_TITLE) ?: getString(R.string.loading_dots)
val title = episodeTitle ?: getString(R.string.loading_dots)

return MediaDescriptionCompat.Builder()
.setIconBitmap(bitmap)
Expand All @@ -252,6 +211,30 @@ class AudioService : LifecycleService() {

setPlayer(exoPlayer)
}
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
handleIntent(intent)

return super.onStartCommand(intent, flags, startId)
}

override fun onDestroy() {
cancelPlaybackMonitor()

mediaSession?.release()
mediaSessionConnector?.setPlayer(null)
playerNotificationManager?.setPlayer(null)

exoPlayer.release()

super.onDestroy()
}

@MainThread
private fun handleIntent(intent: Intent?) {
episodeId = intent?.getStringExtra(ARG_EPISODE_ID)
episodeTitle = intent?.getStringExtra(ARG_TITLE)

// Play
intent?.let {
Expand All @@ -264,6 +247,42 @@ class AudioService : LifecycleService() {
}
}

@MainThread
fun play(uri: Uri, startPosition: Long, playbackSpeed: Float? = null) {
val userAgent = Util.getUserAgent(applicationContext, BuildConfig.APPLICATION_ID)
val mediaSource = ExtractorMediaSource(
uri,
DefaultDataSourceFactory(applicationContext, userAgent),
DefaultExtractorsFactory(),
null,
null)

val haveStartPosition = startPosition != C.POSITION_UNSET.toLong()
if (haveStartPosition) {
exoPlayer.seekTo(startPosition)
}

playbackSpeed?.let { changePlaybackSpeed(playbackSpeed) }

exoPlayer.prepare(mediaSource, !haveStartPosition, false)
exoPlayer.playWhenReady = true
}

@MainThread
fun resume() {
exoPlayer.playWhenReady = true
}

@MainThread
fun pause() {
exoPlayer.playWhenReady = false
}

@MainThread
fun changePlaybackSpeed(playbackSpeed: Float) {
exoPlayer.playbackParameters = PlaybackParameters(playbackSpeed)
}

@MainThread
private fun saveLastListeningPosition() = lifecycleScope.launch {
episodeId?.let { appDatabase.listenedDao().insert(Listened(it, exoPlayer.contentPosition, exoPlayer.duration)) }
Expand Down Expand Up @@ -321,18 +340,21 @@ class AudioService : LifecycleService() {
if (playbackState == Player.STATE_READY) {
if (exoPlayer.playWhenReady) {
episodeId?.let { _playerStatusLiveData.value = PlayerStatus.Playing(it) }

monitorPlaybackProgress()
} else {// Paused
episodeId?.let { _playerStatusLiveData.value = PlayerStatus.Paused(it) }

cancelPlaybackMonitor()
}
} else if (playbackState == Player.STATE_ENDED) {
episodeId?.let { _playerStatusLiveData.value = PlayerStatus.Ended(it) }
} else {
episodeId?.let { _playerStatusLiveData.value = PlayerStatus.Other(it) }
}

// Only monitor playback to record progress when playing.
if (playbackState == Player.STATE_READY && exoPlayer.playWhenReady) {
monitorPlaybackProgress()
} else {
cancelPlaybackMonitor()
}
}

override fun onPlayerError(e: ExoPlaybackException?) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ abstract class BasePlayerActivity : AppCompatActivity(), PlayerCallback, Playbac
_playerStatusLiveData.value = it

playerOverlayPlayMaterialButton.isSelected = it is PlayerStatus.Playing

if (it is PlayerStatus.Cancelled) {
dismissPlayerOverlay()

stopAudioService()
}
})

// Show player after config change.
Expand Down Expand Up @@ -93,11 +99,6 @@ abstract class BasePlayerActivity : AppCompatActivity(), PlayerCallback, Playbac

setupPlayerBottomSheet()

// Show the player, if the audio service is already running.
if (applicationContext.isServiceRunning(AudioService::class.java.name)) {
bindToAudioService()
}

playerOverlayPlayMaterialButton.setOnClickListener {
if (playerOverlayPlayMaterialButton.isSelected) {
audioService?.pause()
Expand Down Expand Up @@ -139,6 +140,17 @@ abstract class BasePlayerActivity : AppCompatActivity(), PlayerCallback, Playbac
playerView.showController()
}

override fun onStart() {
super.onStart()

// Show the player, if the audio service is already running.
if (applicationContext.isServiceRunning(AudioService::class.java.name)) {
bindToAudioService()
} else {
dismissPlayerOverlay()
}
}

override fun onStop() {
unbindAudioService()

Expand All @@ -160,8 +172,12 @@ abstract class BasePlayerActivity : AppCompatActivity(), PlayerCallback, Playbac
override fun stop() {
dismissPlayerOverlay()

audioService?.episodeId?.let { episodeId ->
_playerStatusLiveData.value = PlayerStatus.Paused(episodeId)
} ?: run {
_playerStatusLiveData.value = PlayerStatus.Other()
}
stopAudioService()
_playerStatusLiveData.value = PlayerStatus.Other()
}

private fun bindToAudioService() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ sealed class PlayerStatus(open val episodeId: String?) {
data class Other(override val episodeId: String? = null) : PlayerStatus(episodeId)
data class Playing(override val episodeId: String) : PlayerStatus(episodeId)
data class Paused(override val episodeId: String) : PlayerStatus(episodeId)
data class Cancelled(override val episodeId: String? = null) : PlayerStatus(episodeId)
data class Ended(override val episodeId: String) : PlayerStatus(episodeId)
data class Error(override val episodeId: String, val exception: Exception?) : PlayerStatus(episodeId)
}
4 changes: 2 additions & 2 deletions app/src/main/res/layout/fragment_auth.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
android:layout_marginTop="16dp"
android:layout_marginEnd="@dimen/first_keyline"
android:layout_marginBottom="@dimen/first_keyline"
android:textOff="@string/back_to_login_in"
android:textOn="@string/back_to_create_account"
android:textOff="@string/back_to_create_account"
android:textOn="@string/back_to_login_in"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
Expand Down

0 comments on commit ade6c5a

Please sign in to comment.