From 98daf24d11e90bc02fb5c1bd9219dd2d12de2cc1 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 10 Jul 2019 09:29:18 -0300 Subject: [PATCH 1/4] just inverted the text --- app/src/main/res/layout/fragment_auth.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/fragment_auth.xml b/app/src/main/res/layout/fragment_auth.xml index 5104349..50de267 100644 --- a/app/src/main/res/layout/fragment_auth.xml +++ b/app/src/main/res/layout/fragment_auth.xml @@ -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" From 5b27763dbf2271cd3500dbe69f5d6b773407bbdf Mon Sep 17 00:00:00 2001 From: Mostafa Gazar Date: Wed, 17 Jul 2019 04:37:40 +1200 Subject: [PATCH 2/4] Fix CONTRIBUTING.md link in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 916a74d..feb82af 100644 --- a/README.md +++ b/README.md @@ -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. From 57209e697ce286088864b1eb30003d0285160b40 Mon Sep 17 00:00:00 2001 From: Mostafa Gazar Date: Wed, 17 Jul 2019 04:39:09 +1200 Subject: [PATCH 3/4] Add a stop button to the playback notification and make it dismissible when paused --- .../episodedetail/EpisodeDetailFragment.kt | 1 + .../sedaily/feature/player/AudioService.kt | 154 ++++++++++-------- .../feature/player/BasePlayerActivity.kt | 28 +++- .../sedaily/feature/player/PlayerStatus.kt | 1 + 4 files changed, 112 insertions(+), 72 deletions(-) diff --git a/app/src/main/java/com/koalatea/sedaily/feature/episodedetail/EpisodeDetailFragment.kt b/app/src/main/java/com/koalatea/sedaily/feature/episodedetail/EpisodeDetailFragment.kt index 00838c7..88a031a 100644 --- a/app/src/main/java/com/koalatea/sedaily/feature/episodedetail/EpisodeDetailFragment.kt +++ b/app/src/main/java/com/koalatea/sedaily/feature/episodedetail/EpisodeDetailFragment.kt @@ -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() } } diff --git a/app/src/main/java/com/koalatea/sedaily/feature/player/AudioService.kt b/app/src/main/java/com/koalatea/sedaily/feature/player/AudioService.kt index 6e7016a..614df93 100644 --- a/app/src/main/java/com/koalatea/sedaily/feature/player/AudioService.kt +++ b/app/src/main/java/com/koalatea/sedaily/feature/player/AudioService.kt @@ -88,6 +88,7 @@ class AudioService : LifecycleService() { var episodeId: String? = null private set + private var episodeTitle: String? = null private lateinit var exoPlayer: SimpleExoPlayer @@ -117,67 +118,10 @@ 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, @@ -185,7 +129,7 @@ class AudioService : LifecycleService() { 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 @@ -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) @@ -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) @@ -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 { @@ -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)) } @@ -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?) { diff --git a/app/src/main/java/com/koalatea/sedaily/feature/player/BasePlayerActivity.kt b/app/src/main/java/com/koalatea/sedaily/feature/player/BasePlayerActivity.kt index cb92010..bd470bc 100644 --- a/app/src/main/java/com/koalatea/sedaily/feature/player/BasePlayerActivity.kt +++ b/app/src/main/java/com/koalatea/sedaily/feature/player/BasePlayerActivity.kt @@ -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. @@ -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() @@ -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() @@ -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() { diff --git a/app/src/main/java/com/koalatea/sedaily/feature/player/PlayerStatus.kt b/app/src/main/java/com/koalatea/sedaily/feature/player/PlayerStatus.kt index b9f09d9..4d28c96 100644 --- a/app/src/main/java/com/koalatea/sedaily/feature/player/PlayerStatus.kt +++ b/app/src/main/java/com/koalatea/sedaily/feature/player/PlayerStatus.kt @@ -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) } \ No newline at end of file From 92daffd610d90dde77bd6b5ff7952daae7cc6ab5 Mon Sep 17 00:00:00 2001 From: Mostafa Gazar Date: Wed, 17 Jul 2019 05:19:53 +1200 Subject: [PATCH 4/4] Bump app version --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7f9f093..b003293 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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" }