From afcf7036ee3f1f3da6dcec99211ce8faf57261c7 Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Wed, 6 Oct 2021 16:11:33 +0300 Subject: [PATCH 1/7] Bump checkout library version --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 91cb331da6..e8c29c0385 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -67,7 +67,7 @@ ext.versions = [ googleauth : '18.1.0', firebaseBoM : '28.4.1', - checkout : '1.2.1', + checkout : '1.2.3', facebook : '8.1.0', vk : '2.2.3', From 279283fa4fb47504953b66c91dfe09644e18a3e8 Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Mon, 11 Oct 2021 15:57:17 +0300 Subject: [PATCH 2/7] Migrate ExoPlayer to new version --- .../ui/custom_exo/AppCompatSeekTimeBar.kt | 8 +- .../ui/activity/VideoPlayerActivity.kt | 61 ++++----- .../VideoPlayerMediaDescriptionAdapter.kt | 10 +- .../service/VideoPlayerForegroundService.kt | 117 +++++++++++------- ...l_view.xml => exo_player_control_view.xml} | 0 .../res/layout/exo_simple_player_view.xml | 2 +- dependencies.gradle | 2 +- 7 files changed, 111 insertions(+), 89 deletions(-) rename app/src/main/res/layout/{exo_playback_control_view.xml => exo_player_control_view.xml} (100%) diff --git a/app/src/main/java/org/stepic/droid/ui/custom_exo/AppCompatSeekTimeBar.kt b/app/src/main/java/org/stepic/droid/ui/custom_exo/AppCompatSeekTimeBar.kt index ccd5c4a1c7..316e1b1bd0 100644 --- a/app/src/main/java/org/stepic/droid/ui/custom_exo/AppCompatSeekTimeBar.kt +++ b/app/src/main/java/org/stepic/droid/ui/custom_exo/AppCompatSeekTimeBar.kt @@ -21,12 +21,12 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 setOnSeekBarChangeListener(this) } - override fun addListener(listener: TimeBar.OnScrubListener?) { - listener?.let(listeners::add) + override fun addListener(listener: TimeBar.OnScrubListener) { + listener.let(listeners::add) } - override fun removeListener(listener: TimeBar.OnScrubListener?) { - listener?.let(listeners::remove) + override fun removeListener(listener: TimeBar.OnScrubListener) { + listener.let(listeners::remove) } override fun setKeyTimeIncrement(time: Long) { diff --git a/app/src/main/java/org/stepik/android/view/video_player/ui/activity/VideoPlayerActivity.kt b/app/src/main/java/org/stepik/android/view/video_player/ui/activity/VideoPlayerActivity.kt index 4c0531f783..c5136077ef 100644 --- a/app/src/main/java/org/stepik/android/view/video_player/ui/activity/VideoPlayerActivity.kt +++ b/app/src/main/java/org/stepik/android/view/video_player/ui/activity/VideoPlayerActivity.kt @@ -34,14 +34,12 @@ import androidx.appcompat.widget.PopupMenu import androidx.core.view.GestureDetectorCompat import androidx.core.view.isVisible import androidx.lifecycle.ViewModelProvider -import com.google.android.exoplayer2.DefaultControlDispatcher -import com.google.android.exoplayer2.ExoPlaybackException -import com.google.android.exoplayer2.ExoPlayer +import com.google.android.exoplayer2.PlaybackException import com.google.android.exoplayer2.Player import com.google.android.exoplayer2.upstream.HttpDataSource import com.google.android.exoplayer2.util.Util import kotlinx.android.synthetic.main.activity_video_player.* -import kotlinx.android.synthetic.main.exo_playback_control_view.* +import kotlinx.android.synthetic.main.exo_player_control_view.* import org.stepic.droid.R import org.stepic.droid.analytic.AmplitudeAnalytic import org.stepic.droid.analytic.Analytic @@ -65,7 +63,6 @@ import org.stepik.android.view.video_player.model.VideoPlayerData import org.stepik.android.view.video_player.model.VideoPlayerMediaData import org.stepik.android.view.video_player.ui.service.VideoPlayerForegroundService import javax.inject.Inject -import kotlin.math.abs class VideoPlayerActivity : AppCompatActivity(), VideoPlayerView, VideoQualityDialogInPlayer.Callback { companion object { @@ -152,11 +149,9 @@ class VideoPlayerActivity : AppCompatActivity(), VideoPlayerView, VideoQualityDi } private val exoPlayerListener = - object : Player.EventListener { - override fun onPlayerError(error: ExoPlaybackException?) { - error ?: return - - if (error.type == ExoPlaybackException.TYPE_SOURCE && error.cause is HttpDataSource.HttpDataSourceException) { + object : Player.Listener { + override fun onPlayerError(error: PlaybackException) { + if (error.cause is HttpDataSource.HttpDataSourceException) { Toast .makeText(this@VideoPlayerActivity, R.string.no_connection, Toast.LENGTH_LONG) .show() @@ -204,11 +199,9 @@ class VideoPlayerActivity : AppCompatActivity(), VideoPlayerView, VideoQualityDi } CONTROL_TYPE_PAUSE -> exoPlayer?.playWhenReady = false CONTROL_TYPE_REWIND -> exoPlayer?.let { - analytic.report(VideoPlayerControlClickedEvent(VideoPlayerControlClickedEvent.ACTION_REWIND)) it.seekTo(it.currentPosition - JUMP_TIME_MILLIS) } CONTROL_TYPE_FORWARD -> exoPlayer?.let { - analytic.report(VideoPlayerControlClickedEvent(VideoPlayerControlClickedEvent.ACTION_FORWARD)) it.seekTo(it.currentPosition + JUMP_TIME_MILLIS) } } @@ -216,22 +209,22 @@ class VideoPlayerActivity : AppCompatActivity(), VideoPlayerView, VideoQualityDi } } - private val controlDispatcher = object : DefaultControlDispatcher() { - override fun dispatchSeekTo(player: Player?, windowIndex: Int, positionMs: Long): Boolean { - val current = player?.currentPosition ?: 0L - val difference = current - positionMs - val action = - if (difference > 0L) { - VideoPlayerControlClickedEvent.ACTION_SEEK_BACK - } else { - VideoPlayerControlClickedEvent.ACTION_SEEK_FORWARD - } - if (abs(difference) != JUMP_TIME_MILLIS.toLong()) { - analytic.report(VideoPlayerControlClickedEvent(action)) - } - return super.dispatchSeekTo(player, windowIndex, positionMs) - } - } +// private val controlDispatcher = object : DefaultControlDispatcher() { +// override fun dispatchSeekTo(player: Player?, windowIndex: Int, positionMs: Long): Boolean { +// val current = player?.currentPosition ?: 0L +// val difference = current - positionMs +// val action = +// if (difference > 0L) { +// VideoPlayerControlClickedEvent.ACTION_SEEK_BACK +// } else { +// VideoPlayerControlClickedEvent.ACTION_SEEK_FORWARD +// } +// if (abs(difference) != JUMP_TIME_MILLIS.toLong()) { +// analytic.report(VideoPlayerControlClickedEvent(action)) +// } +// return super.dispatchSeekTo(player, windowIndex, positionMs) +// } +// } private lateinit var gestureDetector: GestureDetectorCompat @@ -247,7 +240,7 @@ class VideoPlayerActivity : AppCompatActivity(), VideoPlayerView, VideoQualityDi } } - private var exoPlayer: ExoPlayer? = null + private var exoPlayer: Player? = null set(value) { field?.removeListener(exoPlayerListener) field = value @@ -307,10 +300,11 @@ class VideoPlayerActivity : AppCompatActivity(), VideoPlayerView, VideoQualityDi qualityView.isVisible = false - playerView.setControlDispatcher(controlDispatcher) +// playerView.setControlDispatcher(controlDispatcher) +// playerView.setControlDispatcher() playerView.controllerShowTimeoutMs = TIMEOUT_BEFORE_HIDE - playerView.setFastForwardIncrementMs(JUMP_TIME_MILLIS) - playerView.setRewindIncrementMs(JUMP_TIME_MILLIS) +// playerView.setFastForwardIncrementMs(JUMP_TIME_MILLIS) +// playerView.setRewindIncrementMs(JUMP_TIME_MILLIS) exo_pip_icon_container.isVisible = isSupportPIP() exo_pip_icon_container.setOnClickListener { @@ -343,12 +337,10 @@ class VideoPlayerActivity : AppCompatActivity(), VideoPlayerView, VideoQualityDi } rewind.setOnClickListener { - analytic.report(VideoPlayerControlClickedEvent(VideoPlayerControlClickedEvent.ACTION_REWIND)) exoPlayer?.let { player -> player.seekTo(player.currentPosition - JUMP_TIME_MILLIS) } } forward.setOnClickListener { - analytic.report(VideoPlayerControlClickedEvent(VideoPlayerControlClickedEvent.ACTION_FORWARD)) exoPlayer?.let { player -> player.seekTo(player.currentPosition + JUMP_TIME_MILLIS) } } @@ -662,6 +654,7 @@ class VideoPlayerActivity : AppCompatActivity(), VideoPlayerView, VideoQualityDi } private fun logIsPlayingEvent(isPlaying: Boolean) { + val event = if (isPlaying) { VideoPlayerControlClickedEvent(VideoPlayerControlClickedEvent.ACTION_PLAY) } else { diff --git a/app/src/main/java/org/stepik/android/view/video_player/ui/adapter/VideoPlayerMediaDescriptionAdapter.kt b/app/src/main/java/org/stepik/android/view/video_player/ui/adapter/VideoPlayerMediaDescriptionAdapter.kt index f33e548abb..7179f6a138 100644 --- a/app/src/main/java/org/stepik/android/view/video_player/ui/adapter/VideoPlayerMediaDescriptionAdapter.kt +++ b/app/src/main/java/org/stepik/android/view/video_player/ui/adapter/VideoPlayerMediaDescriptionAdapter.kt @@ -22,20 +22,20 @@ class VideoPlayerMediaDescriptionAdapter( private fun createIntent(videoPlayerMediaData: VideoPlayerMediaData): Intent = VideoPlayerActivity.createIntent(context, videoPlayerMediaData) - override fun createCurrentContentIntent(player: Player?): PendingIntent? = + override fun createCurrentContentIntent(player: Player): PendingIntent? = videoPlayerMediaData ?.let(::createIntent) ?.let { intent -> PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) } - override fun getCurrentContentText(player: Player?): String? = + override fun getCurrentContentText(player: Player): String? = videoPlayerMediaData?.description - override fun getCurrentContentTitle(player: Player?): String = + override fun getCurrentContentTitle(player: Player): String = videoPlayerMediaData?.title ?: "" - override fun getCurrentLargeIcon(player: Player?, callback: PlayerNotificationManager.BitmapCallback?): Bitmap? { + override fun getCurrentLargeIcon(player: Player, callback: PlayerNotificationManager.BitmapCallback): Bitmap? { Glide.with(context) .asBitmap() .load(videoPlayerMediaData?.thumbnail) @@ -44,7 +44,7 @@ class VideoPlayerMediaDescriptionAdapter( override fun onLoadCleared(placeholder: Drawable?) {} override fun onResourceReady(resource: Bitmap, transition: Transition?) { - callback?.onBitmap(resource) + callback.onBitmap(resource) } }) return null diff --git a/app/src/main/java/org/stepik/android/view/video_player/ui/service/VideoPlayerForegroundService.kt b/app/src/main/java/org/stepik/android/view/video_player/ui/service/VideoPlayerForegroundService.kt index f9d6267a42..8392a90c3a 100644 --- a/app/src/main/java/org/stepik/android/view/video_player/ui/service/VideoPlayerForegroundService.kt +++ b/app/src/main/java/org/stepik/android/view/video_player/ui/service/VideoPlayerForegroundService.kt @@ -12,14 +12,13 @@ import android.os.Binder import android.os.IBinder import android.support.v4.media.session.MediaSessionCompat import androidx.media.session.MediaButtonReceiver +import com.google.android.exoplayer2.PlaybackParameters +import com.google.android.exoplayer2.MediaItem +import com.google.android.exoplayer2.SimpleExoPlayer import com.google.android.exoplayer2.C import com.google.android.exoplayer2.DefaultLoadControl -import com.google.android.exoplayer2.DefaultRenderersFactory -import com.google.android.exoplayer2.ExoPlayer -import com.google.android.exoplayer2.ExoPlayerFactory -import com.google.android.exoplayer2.PlaybackParameters +import com.google.android.exoplayer2.ForwardingPlayer import com.google.android.exoplayer2.Player -import com.google.android.exoplayer2.SimpleExoPlayer import com.google.android.exoplayer2.audio.AudioAttributes import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector import com.google.android.exoplayer2.source.MediaSource @@ -28,7 +27,6 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector import com.google.android.exoplayer2.ui.PlayerNotificationManager import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory -import com.google.android.exoplayer2.DefaultControlDispatcher import com.google.android.exoplayer2.util.Util import org.stepic.droid.R import org.stepic.droid.analytic.Analytic @@ -64,7 +62,7 @@ class VideoPlayerForegroundService : Service() { @Inject internal lateinit var analytic: Analytic - private var player: SimpleExoPlayer? = null + private var player: ForwardingPlayer? = null private lateinit var playerNotificationManager: PlayerNotificationManager private lateinit var mediaSession: MediaSessionCompat @@ -100,7 +98,7 @@ class VideoPlayerForegroundService : Service() { createPlayer() } - override fun onBind(intent: Intent?): IBinder? = + override fun onBind(intent: Intent?): IBinder = VideoPlayerBinder(player) override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { @@ -119,45 +117,53 @@ class VideoPlayerForegroundService : Service() { val loadControl = DefaultLoadControl.Builder() .setBackBuffer(BACK_BUFFER_DURATION_MS, true) - .createDefaultLoadControl() + .build() - player = ExoPlayerFactory - .newSimpleInstance(this, DefaultRenderersFactory(this), DefaultTrackSelector(), loadControl) + val simplePlayer = SimpleExoPlayer.Builder(this) + .setLoadControl(loadControl) + .setTrackSelector(DefaultTrackSelector(this)) + .setSeekBackIncrementMs(JUMP_TIME_MILLIS) + .setSeekForwardIncrementMs(JUMP_TIME_MILLIS) + .build() .apply { playWhenReady = true setAudioAttributes(audioAttributes, true) } - val notificationListener = - object : PlayerNotificationManager.NotificationListener { - override fun onNotificationCancelled(notificationId: Int) { - stopSelf() - } + player = object : ForwardingPlayer(simplePlayer) { + /** + * Interacting with seekbar in notification or fullscreen + */ + override fun seekTo(windowIndex: Int, positionMs: Long) { + val currentPosition = player?.currentPosition ?: 0L + val difference = currentPosition - positionMs + val action = + if (difference > 0L) { + VideoPlayerControlClickedEvent.ACTION_SEEK_BACK + } else { + VideoPlayerControlClickedEvent.ACTION_SEEK_FORWARD + } + analytic.report(VideoPlayerControlClickedEvent(action)) + super.seekTo(windowIndex, positionMs) + } - override fun onNotificationStarted(notificationId: Int, notification: Notification?) { - startForeground(notificationId, notification) - } + /** + * Rewind/forward buttons in notification + */ + override fun seekBack() { + analytic.report(VideoPlayerControlClickedEvent((VideoPlayerControlClickedEvent.ACTION_REWIND))) + super.seekBack() } - playerNotificationManager = PlayerNotificationManager - .createWithNotificationChannel( - this, - PLAYER_CHANNEL_ID, - R.string.video_player_control_notification_channel_name, - R.string.video_player_control_notification_channel_description, - PLAYER_NOTIFICATION_ID, - videoPlayerMediaDescriptionAdapter, - notificationListener - ) + override fun seekForward() { + analytic.report(VideoPlayerControlClickedEvent((VideoPlayerControlClickedEvent.ACTION_FORWARD))) + super.seekForward() + } - playerNotificationManager.setSmallIcon(R.drawable.ic_player_notification) - playerNotificationManager.setUseStopAction(false) - playerNotificationManager.setPlayer(player) - playerNotificationManager.setRewindIncrementMs(JUMP_TIME_MILLIS) - playerNotificationManager.setFastForwardIncrementMs(JUMP_TIME_MILLIS) - playerNotificationManager.setUseNavigationActions(false) - playerNotificationManager.setControlDispatcher(object : DefaultControlDispatcher() { - override fun dispatchSeekTo(player: Player?, windowIndex: Int, positionMs: Long): Boolean { + /** + * Rewind/forward when pressing PIP or fullscreen buttons + */ + override fun seekTo(positionMs: Long) { val currentPosition = player?.currentPosition ?: 0L val difference = currentPosition - positionMs val action = @@ -167,9 +173,31 @@ class VideoPlayerForegroundService : Service() { VideoPlayerControlClickedEvent.ACTION_FORWARD } analytic.report(VideoPlayerControlClickedEvent(action)) - return super.dispatchSeekTo(player, windowIndex, positionMs) + super.seekTo(positionMs) } - }) + } + + val notificationListener = + object : PlayerNotificationManager.NotificationListener { + override fun onNotificationCancelled(notificationId: Int, dismissedByUser: Boolean) { + stopSelf() + } + + override fun onNotificationPosted(notificationId: Int, notification: Notification, ongoing: Boolean) { + startForeground(notificationId, notification) + } + } + + playerNotificationManager = PlayerNotificationManager.Builder(this, PLAYER_NOTIFICATION_ID, PLAYER_CHANNEL_ID) + .setChannelNameResourceId(R.string.video_player_control_notification_channel_name) + .setChannelDescriptionResourceId(R.string.video_player_control_notification_channel_description) + .setMediaDescriptionAdapter(videoPlayerMediaDescriptionAdapter) + .setNotificationListener(notificationListener) + .build() + + playerNotificationManager.setSmallIcon(R.drawable.ic_player_notification) + playerNotificationManager.setPlayer(player) + playerNotificationManager.setUsePreviousAction(false) mediaSession = MediaSessionCompat(this, MEDIA_SESSION_TAG, ComponentName(this, MediaButtonReceiver::class.java), null) mediaSession.isActive = true @@ -186,6 +214,7 @@ class VideoPlayerForegroundService : Service() { private fun setPlayerData(videoPlayerData: VideoPlayerData?) { val player = this.player + ?.wrappedPlayer as? SimpleExoPlayer ?: return val position = @@ -202,7 +231,8 @@ class VideoPlayerForegroundService : Service() { if (videoPlayerData != null) { if (this.videoPlayerData?.videoUrl != videoPlayerData.videoUrl || player.playbackState == Player.STATE_IDLE) { val mediaSource = getMediaSource(videoPlayerData) - player.prepare(mediaSource) + player.prepare() + player.setMediaSource(mediaSource) } player.playbackParameters = PlaybackParameters(videoPlayerData.videoPlaybackRate.rateFloat, 1f) @@ -222,7 +252,7 @@ class VideoPlayerForegroundService : Service() { return ProgressiveMediaSource .Factory(dataSourceFactory) - .createMediaSource(Uri.parse(videoPlayerData.videoUrl)) + .createMediaSource(MediaItem.fromUri(Uri.parse(videoPlayerData.videoUrl))) } private fun releasePlayer() { @@ -233,7 +263,6 @@ class VideoPlayerForegroundService : Service() { mediaSessionConnector.setPlayer(null) playerNotificationManager.setPlayer(null) - playerNotificationManager.setControlDispatcher(null) player?.release() player = null } @@ -244,8 +273,8 @@ class VideoPlayerForegroundService : Service() { super.onDestroy() } - class VideoPlayerBinder(private val player: ExoPlayer?) : Binder() { - fun getPlayer(): ExoPlayer? = + class VideoPlayerBinder(private val player: Player?) : Binder() { + fun getPlayer(): Player? = player } } \ No newline at end of file diff --git a/app/src/main/res/layout/exo_playback_control_view.xml b/app/src/main/res/layout/exo_player_control_view.xml similarity index 100% rename from app/src/main/res/layout/exo_playback_control_view.xml rename to app/src/main/res/layout/exo_player_control_view.xml diff --git a/app/src/main/res/layout/exo_simple_player_view.xml b/app/src/main/res/layout/exo_simple_player_view.xml index c7691cbaa8..3e5835e53d 100644 --- a/app/src/main/res/layout/exo_simple_player_view.xml +++ b/app/src/main/res/layout/exo_simple_player_view.xml @@ -42,7 +42,7 @@ - diff --git a/dependencies.gradle b/dependencies.gradle index a86be9c150..405f8bb698 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -20,7 +20,7 @@ ext.versions = [ rxKotlin : '2.3.0', rxRelay : '2.1.1', - exoPlayer : '2.10.5', + exoPlayer : '2.15.1', appCompat : '1.1.0', ktx : '1.3.0', From f56be40fe07e7233241b7d3dd1b4e02348dc0b63 Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Mon, 11 Oct 2021 18:28:42 +0300 Subject: [PATCH 3/7] Fix notification image flicker --- .../ui/adapter/VideoPlayerMediaDescriptionAdapter.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/stepik/android/view/video_player/ui/adapter/VideoPlayerMediaDescriptionAdapter.kt b/app/src/main/java/org/stepik/android/view/video_player/ui/adapter/VideoPlayerMediaDescriptionAdapter.kt index 7179f6a138..596959f212 100644 --- a/app/src/main/java/org/stepik/android/view/video_player/ui/adapter/VideoPlayerMediaDescriptionAdapter.kt +++ b/app/src/main/java/org/stepik/android/view/video_player/ui/adapter/VideoPlayerMediaDescriptionAdapter.kt @@ -5,6 +5,7 @@ import android.content.Context import android.content.Intent import android.graphics.Bitmap import android.graphics.drawable.Drawable +import androidx.core.content.ContextCompat import com.bumptech.glide.Glide import com.bumptech.glide.request.target.CustomTarget import com.bumptech.glide.request.transition.Transition @@ -13,6 +14,7 @@ import com.google.android.exoplayer2.ui.PlayerNotificationManager import org.stepic.droid.R import org.stepik.android.view.video_player.model.VideoPlayerMediaData import org.stepik.android.view.video_player.ui.activity.VideoPlayerActivity +import ru.nobird.android.view.base.ui.extension.toBitmap class VideoPlayerMediaDescriptionAdapter( private val context: Context @@ -47,6 +49,6 @@ class VideoPlayerMediaDescriptionAdapter( callback.onBitmap(resource) } }) - return null + return ContextCompat.getDrawable(context, R.drawable.general_placeholder)?.toBitmap() } } \ No newline at end of file From 0c2f52c540e2bab8152826f437b8626fa95a9352 Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Mon, 11 Oct 2021 18:51:09 +0300 Subject: [PATCH 4/7] Clean up --- .../ui/activity/VideoPlayerActivity.kt | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/app/src/main/java/org/stepik/android/view/video_player/ui/activity/VideoPlayerActivity.kt b/app/src/main/java/org/stepik/android/view/video_player/ui/activity/VideoPlayerActivity.kt index c5136077ef..be1b212a2c 100644 --- a/app/src/main/java/org/stepik/android/view/video_player/ui/activity/VideoPlayerActivity.kt +++ b/app/src/main/java/org/stepik/android/view/video_player/ui/activity/VideoPlayerActivity.kt @@ -209,23 +209,6 @@ class VideoPlayerActivity : AppCompatActivity(), VideoPlayerView, VideoQualityDi } } -// private val controlDispatcher = object : DefaultControlDispatcher() { -// override fun dispatchSeekTo(player: Player?, windowIndex: Int, positionMs: Long): Boolean { -// val current = player?.currentPosition ?: 0L -// val difference = current - positionMs -// val action = -// if (difference > 0L) { -// VideoPlayerControlClickedEvent.ACTION_SEEK_BACK -// } else { -// VideoPlayerControlClickedEvent.ACTION_SEEK_FORWARD -// } -// if (abs(difference) != JUMP_TIME_MILLIS.toLong()) { -// analytic.report(VideoPlayerControlClickedEvent(action)) -// } -// return super.dispatchSeekTo(player, windowIndex, positionMs) -// } -// } - private lateinit var gestureDetector: GestureDetectorCompat private val onSimpleGestureListener = object : GestureDetector.SimpleOnGestureListener() { @@ -299,12 +282,7 @@ class VideoPlayerActivity : AppCompatActivity(), VideoPlayerView, VideoQualityDi } qualityView.isVisible = false - -// playerView.setControlDispatcher(controlDispatcher) -// playerView.setControlDispatcher() playerView.controllerShowTimeoutMs = TIMEOUT_BEFORE_HIDE -// playerView.setFastForwardIncrementMs(JUMP_TIME_MILLIS) -// playerView.setRewindIncrementMs(JUMP_TIME_MILLIS) exo_pip_icon_container.isVisible = isSupportPIP() exo_pip_icon_container.setOnClickListener { @@ -654,7 +632,6 @@ class VideoPlayerActivity : AppCompatActivity(), VideoPlayerView, VideoQualityDi } private fun logIsPlayingEvent(isPlaying: Boolean) { - val event = if (isPlaying) { VideoPlayerControlClickedEvent(VideoPlayerControlClickedEvent.ACTION_PLAY) } else { From bc97e1697f36dd1560e88e9a8fe01cfa48f456c7 Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Tue, 12 Oct 2021 13:04:56 +0300 Subject: [PATCH 5/7] Fix PR comments --- .../org/stepic/droid/ui/custom_exo/AppCompatSeekTimeBar.kt | 4 ++-- .../ui/adapter/VideoPlayerMediaDescriptionAdapter.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/ui/custom_exo/AppCompatSeekTimeBar.kt b/app/src/main/java/org/stepic/droid/ui/custom_exo/AppCompatSeekTimeBar.kt index 316e1b1bd0..557e778de3 100644 --- a/app/src/main/java/org/stepic/droid/ui/custom_exo/AppCompatSeekTimeBar.kt +++ b/app/src/main/java/org/stepic/droid/ui/custom_exo/AppCompatSeekTimeBar.kt @@ -22,11 +22,11 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 } override fun addListener(listener: TimeBar.OnScrubListener) { - listener.let(listeners::add) + listeners += listener } override fun removeListener(listener: TimeBar.OnScrubListener) { - listener.let(listeners::remove) + listeners -= listener } override fun setKeyTimeIncrement(time: Long) { diff --git a/app/src/main/java/org/stepik/android/view/video_player/ui/adapter/VideoPlayerMediaDescriptionAdapter.kt b/app/src/main/java/org/stepik/android/view/video_player/ui/adapter/VideoPlayerMediaDescriptionAdapter.kt index 596959f212..59ad2ef138 100644 --- a/app/src/main/java/org/stepik/android/view/video_player/ui/adapter/VideoPlayerMediaDescriptionAdapter.kt +++ b/app/src/main/java/org/stepik/android/view/video_player/ui/adapter/VideoPlayerMediaDescriptionAdapter.kt @@ -5,7 +5,7 @@ import android.content.Context import android.content.Intent import android.graphics.Bitmap import android.graphics.drawable.Drawable -import androidx.core.content.ContextCompat +import androidx.appcompat.content.res.AppCompatResources import com.bumptech.glide.Glide import com.bumptech.glide.request.target.CustomTarget import com.bumptech.glide.request.transition.Transition @@ -49,6 +49,6 @@ class VideoPlayerMediaDescriptionAdapter( callback.onBitmap(resource) } }) - return ContextCompat.getDrawable(context, R.drawable.general_placeholder)?.toBitmap() + return AppCompatResources.getDrawable(context, R.drawable.general_placeholder)?.toBitmap() } } \ No newline at end of file From 7e5ba5a5d9d5f2001e025176c547d6ef3681d7a6 Mon Sep 17 00:00:00 2001 From: Stepik Bot Date: Wed, 13 Oct 2021 03:02:54 +0000 Subject: [PATCH 6/7] "inc version to 2226" --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 3b4658913d..b1cdd560a1 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,6 +1,6 @@ ext.versions = [ - code : 2225, - name : '1.193', + code : 2226, + name : '1.194', minSdk : 21, targetSdk : 30, From 0757ea9c1be2e96ca61bcbc5642d1164812d9d6f Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Wed, 13 Oct 2021 17:26:23 +0300 Subject: [PATCH 7/7] Add properties to Firebase; Log buy event for IAP --- .../java/org/stepic/droid/analytic/AnalyticImpl.kt | 10 ++++++++++ .../view/course/ui/delegates/CourseHeaderDelegate.kt | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/app/src/main/java/org/stepic/droid/analytic/AnalyticImpl.kt b/app/src/main/java/org/stepic/droid/analytic/AnalyticImpl.kt index 8367693894..cd7720c412 100644 --- a/app/src/main/java/org/stepic/droid/analytic/AnalyticImpl.kt +++ b/app/src/main/java/org/stepic/droid/analytic/AnalyticImpl.kt @@ -68,6 +68,10 @@ constructor( apply(Attribute.customBoolean(AmplitudeAnalytic.Properties.IS_NIGHT_MODE_ENABLED).withValue(context.isNightModeEnabled())) apply(Attribute.customBoolean(AmplitudeAnalytic.Properties.IS_AR_SUPPORTED).withValue(context.isARSupported())) } + + firebaseAnalytics.setUserProperty(AmplitudeAnalytic.Properties.PUSH_PERMISSION, if (isNotificationsEnabled) "granted" else "not_granted") + firebaseAnalytics.setUserProperty(AmplitudeAnalytic.Properties.IS_NIGHT_MODE_ENABLED, context.isNightModeEnabled().toString()) + firebaseAnalytics.setUserProperty(AmplitudeAnalytic.Properties.IS_AR_SUPPORTED, context.isARSupported().toString()) } // Amplitude properties @@ -85,32 +89,38 @@ constructor( override fun setCoursesCount(coursesCount: Int) { amplitude.identify(Identify().set(AmplitudeAnalytic.Properties.COURSES_COUNT, coursesCount)) updateYandexUserProfile { apply(Attribute.customNumber(AmplitudeAnalytic.Properties.COURSES_COUNT).withValue(coursesCount.toDouble())) } + firebaseAnalytics.setUserProperty(AmplitudeAnalytic.Properties.COURSES_COUNT, coursesCount.toString()) } override fun setSubmissionsCount(submissionsCount: Long, delta: Long) { amplitude.identify(Identify().set(AmplitudeAnalytic.Properties.SUBMISSIONS_COUNT, submissionsCount + delta)) updateYandexUserProfile { apply(Attribute.customCounter(AmplitudeAnalytic.Properties.SUBMISSIONS_COUNT).withDelta(delta.toDouble())) } + firebaseAnalytics.setUserProperty(AmplitudeAnalytic.Properties.SUBMISSIONS_COUNT, (submissionsCount + delta).toString()) } override fun setScreenOrientation(orientation: Int) { val orientationName = if (orientation == Configuration.ORIENTATION_PORTRAIT) "portrait" else "landscape" amplitude.identify(Identify().set(AmplitudeAnalytic.Properties.SCREEN_ORIENTATION, orientationName)) updateYandexUserProfile { apply(Attribute.customString(AmplitudeAnalytic.Properties.SCREEN_ORIENTATION).withValue(orientationName)) } + firebaseAnalytics.setUserProperty(AmplitudeAnalytic.Properties.SCREEN_ORIENTATION, orientationName) } override fun setStreaksNotificationsEnabled(isEnabled: Boolean) { amplitude.identify(Identify().set(AmplitudeAnalytic.Properties.STREAKS_NOTIFICATIONS_ENABLED, if (isEnabled) "enabled" else "disabled")) updateYandexUserProfile { apply(Attribute.customBoolean(AmplitudeAnalytic.Properties.STREAKS_NOTIFICATIONS_ENABLED).withValue(isEnabled)) } + firebaseAnalytics.setUserProperty(AmplitudeAnalytic.Properties.STREAKS_NOTIFICATIONS_ENABLED.substring(0, 24), if (isEnabled) "enabled" else "disabled") } override fun setTeachingCoursesCount(coursesCount: Int) { amplitude.identify(Identify().set(AmplitudeAnalytic.Properties.TEACHING_COURSES_COUNT, coursesCount)) updateYandexUserProfile { apply(Attribute.customNumber(AmplitudeAnalytic.Properties.TEACHING_COURSES_COUNT).withValue(coursesCount.toDouble())) } + firebaseAnalytics.setUserProperty(AmplitudeAnalytic.Properties.TEACHING_COURSES_COUNT, coursesCount.toString()) } override fun setGoogleServicesAvailable(isAvailable: Boolean) { amplitude.identify(Identify().set(AmplitudeAnalytic.Properties.IS_GOOGLE_SERVICES_AVAILABLE, isAvailable.toString())) updateYandexUserProfile { apply(Attribute.customBoolean(AmplitudeAnalytic.Properties.IS_GOOGLE_SERVICES_AVAILABLE).withValue(isAvailable)) } + firebaseAnalytics.setUserProperty(AmplitudeAnalytic.Properties.IS_GOOGLE_SERVICES_AVAILABLE.substring(0, 24), isAvailable.toString()) } override fun report(analyticEvent: AnalyticEvent) { diff --git a/app/src/main/java/org/stepik/android/view/course/ui/delegates/CourseHeaderDelegate.kt b/app/src/main/java/org/stepik/android/view/course/ui/delegates/CourseHeaderDelegate.kt index f0c5c0826a..ef85058591 100644 --- a/app/src/main/java/org/stepik/android/view/course/ui/delegates/CourseHeaderDelegate.kt +++ b/app/src/main/java/org/stepik/android/view/course/ui/delegates/CourseHeaderDelegate.kt @@ -142,6 +142,10 @@ constructor( courseBuyInWebActionDiscounted.setOnClickListener { buyInWebAction() } courseBuyInAppAction.setOnClickListener { + courseHeaderData?.let { headerData -> + analytic.report(BuyCoursePressedEvent(headerData.course, BuyCoursePressedEvent.COURSE_SCREEN, headerData.stats.isWishlisted)) + analytic.report(BuyCoursePressedAnalyticBatchEvent(headerData.courseId)) + } coursePresenter.purchaseCourse() }