Advertisement
andyshon

PlayerService

Feb 7th, 2019
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 12.35 KB | None | 0 0
  1. package com.andyshon.ucanspeak.ui.catalogTab.catalog.player
  2.  
  3. import android.app.*
  4. import android.content.Intent
  5. import android.net.Uri
  6. import android.os.Binder
  7. import android.os.Handler
  8. import android.os.IBinder
  9. import com.andyshon.ucanspeak.events.*
  10. import com.google.android.exoplayer2.*
  11. import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory
  12. import com.google.android.exoplayer2.source.ExtractorMediaSource
  13. import com.google.android.exoplayer2.source.TrackGroupArray
  14. import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
  15. import com.google.android.exoplayer2.trackselection.TrackSelectionArray
  16. import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
  17. import com.google.android.exoplayer2.util.Util
  18. import timber.log.Timber
  19. import java.util.*
  20. import android.support.v4.content.LocalBroadcastManager
  21. import com.andyshon.ucanspeak.data.entity.LessonFilePhraseEntity
  22. import com.andyshon.ucanspeak.data.preference.Preference.PlayerService.PLAYER_SERVICE_CLOSE_NOTIFICATION
  23. import com.andyshon.ucanspeak.data.preference.Preference.PlayerService.PLAYER_SERVICE_CREATE_NOTIFICATION
  24. import com.andyshon.ucanspeak.data.preference.Preference.PlayerService.PLAYER_SERVICE_PLAY_PAUSE
  25. import com.andyshon.ucanspeak.data.preference.Preference.PlayerService.PLAYER_SERVICE_PLAY_PAUSE_FROM_FLOW_PLAYER
  26. import com.andyshon.ucanspeak.data.preference.Preference.PlayerService.PLAYER_SERVICE_REWIND_BACK
  27. import com.andyshon.ucanspeak.data.preference.Preference.PlayerService.PLAYER_SERVICE_REWIND_BACK_INVISIBLE
  28. import com.andyshon.ucanspeak.data.preference.Preference.PlayerService.PLAYER_SERVICE_REWIND_BACK_VISIBLE
  29. import com.andyshon.ucanspeak.data.preference.Preference.PlayerService.PLAYER_SERVICE_REWIND_NEXT
  30. import com.andyshon.ucanspeak.data.preference.Preference.PlayerService.PLAYER_SERVICE_REWIND_NEXT_INVISIBLE
  31. import com.andyshon.ucanspeak.data.preference.Preference.PlayerService.PLAYER_SERVICE_REWIND_NEXT_VISIBLE
  32. import com.andyshon.ucanspeak.data.preference.Preference.PlayerService.PLAYER_SERVICE_REWIND_SEEKBAR
  33. import com.andyshon.ucanspeak.data.preference.Preference.PlayerService.PLAYER_SERVICE_SET_NEW_AUDIO_FILE
  34. import com.andyshon.ucanspeak.data.preference.Preference.PlayerService.PLAYER_SERVICE_STOP
  35. import com.google.android.exoplayer2.DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF
  36. import com.google.android.exoplayer2.Player
  37.  
  38. class PlayerService : Service() {
  39.  
  40.     companion object {
  41.  
  42.         var isViewAttachedToBottom = false
  43.  
  44.         var rxEventBus: RxEventBus? = null
  45.         var phrases: ArrayList<LessonFilePhraseEntity> = arrayListOf()
  46.     }
  47.  
  48.     var exoPlayer: SimpleExoPlayer? = null
  49.  
  50.     private var myBinder = MyBinder()
  51.     private lateinit var playerNotificationManager: PlayerNotificationManager
  52.  
  53.     private var audioDuration = 0L
  54.     private var curPos = 0
  55.  
  56.     private var lessonName = ""
  57.     private var lessonDescription = ""
  58.     var fileLink = ""
  59.  
  60.  
  61.     override fun onCreate() {
  62.  
  63.         val renderersFactory = DefaultRenderersFactory(this, null, EXTENSION_RENDERER_MODE_OFF)
  64.         val trackSelector = DefaultTrackSelector()
  65.         exoPlayer = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector)
  66.  
  67.         exoPlayer?.addListener(object : Player.EventListener {
  68.             override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
  69.                 if (playWhenReady && playbackState == Player.STATE_READY) {
  70.                     // media actually playing
  71.  
  72.                     audioDuration = exoPlayer?.duration ?: 0
  73.                     sendSetSeekBarMaxValue()
  74.  
  75.                     Handler().postDelayed(onEverySecond, 100)
  76.                 }
  77.                 else {
  78.                     if (playbackState == 4) {
  79.                         sendStopPlayer()
  80.                     }
  81.                 }
  82.             }
  83.  
  84.             override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) {}
  85.             override fun onSeekProcessed() {}
  86.             override fun onTracksChanged(trackGroups: TrackGroupArray?, trackSelections: TrackSelectionArray?) {}
  87.             override fun onPlayerError(error: ExoPlaybackException?) {}
  88.             override fun onLoadingChanged(isLoading: Boolean) {}
  89.             override fun onPositionDiscontinuity(reason: Int) {}
  90.             override fun onRepeatModeChanged(repeatMode: Int) {}
  91.             override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {}
  92.             override fun onTimelineChanged(timeline: Timeline?, manifest: Any?, reason: Int) {}
  93.         })
  94.     }
  95.  
  96.     override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
  97.  
  98.         isViewAttachedToBottom = true
  99.  
  100.         if (intent?.hasExtra(PLAYER_SERVICE_CREATE_NOTIFICATION) == true) {
  101.             if (playerNotificationManager.isShowNotification.not()) {
  102.                 playerNotificationManager.createNotification(this, false, lessonName, lessonDescription)
  103.             }
  104.         }
  105.  
  106.         if (intent?.hasExtra(PLAYER_SERVICE_PLAY_PAUSE_FROM_FLOW_PLAYER) == true) {
  107.             sendUpdatePlayButton(exoPlayer?.playWhenReady!!)
  108.         }
  109.  
  110.         if (intent?.hasExtra(PLAYER_SERVICE_PLAY_PAUSE_FROM_FLOW_PLAYER) == true) {
  111.             exoPlayer?.playWhenReady = exoPlayer?.playWhenReady?.not()!!
  112.             sendUpdatePlayButton(exoPlayer?.playWhenReady!!)
  113.             updateNotificationBtnPlay(exoPlayer?.playWhenReady ?: false)
  114.         }
  115.  
  116.         if (intent?.hasExtra(PLAYER_SERVICE_REWIND_NEXT) == true) {
  117.             rewindForward()
  118.         }
  119.  
  120.         if (intent?.hasExtra(PLAYER_SERVICE_REWIND_BACK) == true) {
  121.             rewindBack()
  122.         }
  123.  
  124.         if (intent?.hasExtra(PLAYER_SERVICE_REWIND_SEEKBAR) == true) {
  125.             val progress = intent.getIntExtra(PLAYER_SERVICE_REWIND_SEEKBAR, 0)
  126.             exoPlayer?.seekTo(progress.toLong())
  127.         }
  128.  
  129.         if (intent?.hasExtra(PLAYER_SERVICE_CLOSE_NOTIFICATION) == true) {
  130.             closeNotification()
  131.         }
  132.  
  133.         if (intent?.hasExtra(PLAYER_SERVICE_PLAY_PAUSE) == true) {
  134.             exoPlayer?.playWhenReady = exoPlayer?.playWhenReady?.not() ?: false
  135.  
  136.             sendUpdatePlayButton(exoPlayer?.playWhenReady ?: false)
  137.             updateNotificationBtnPlay(exoPlayer?.playWhenReady ?: false)
  138.         }
  139.  
  140.         if (intent?.hasExtra(PLAYER_SERVICE_SET_NEW_AUDIO_FILE) == true) {
  141.             fileLink = intent.getStringExtra(PLAYER_SERVICE_SET_NEW_AUDIO_FILE)
  142.  
  143.             lessonName = intent.getStringExtra("lessonName")
  144.             lessonDescription = intent.getStringExtra("lessonDescription")
  145.  
  146.             sendUpdatePlayButton(true)
  147.             sendSetLessonName()
  148.  
  149.             val userAgent = Util.getUserAgent(this, "Play Audio")
  150.             val mediaSource = ExtractorMediaSource(
  151.                 Uri.parse(fileLink),
  152.                 DefaultDataSourceFactory(this, userAgent),
  153.                 DefaultExtractorsFactory(), null, null
  154.             )
  155.  
  156.             exoPlayer?.prepare(mediaSource)
  157.             exoPlayer?.playWhenReady = true
  158.  
  159.  
  160.             playerNotificationManager = PlayerNotificationManager(this, exoPlayer!!)
  161.             playerNotificationManager.createNotification(this,true, lessonName, lessonDescription)
  162.         }
  163.  
  164.         return START_NOT_STICKY
  165.     }
  166.  
  167.  
  168.     private fun closeNotification() {
  169.         isViewAttachedToBottom = false
  170.         exoPlayer?.playWhenReady = false
  171.         playerNotificationManager.closeNotification()
  172.     }
  173.  
  174.  
  175.     private fun rewindBack() {
  176.         setCurPos(--curPos)
  177.         if (curPos > 0) {
  178.             if (curPos == 0) {
  179.                 sendBtnBackInvisible()
  180.             } else {
  181.                 sendBtnBackVisible()
  182.             }
  183.  
  184.             val previousPhrase = phrases[curPos - 1]
  185.             exoPlayer?.seekTo(previousPhrase.position.toLong() * 1000)
  186.             sendUpdateSeekBar(exoPlayer?.currentPosition?.toInt()!!)
  187.         }
  188.         else {
  189.             sendBtnBackInvisible()
  190.         }
  191.     }
  192.  
  193.  
  194.     private fun rewindForward() {
  195.         setCurPos(++curPos)
  196.         if (curPos < phrases.size - 1) {
  197.  
  198.             if (curPos == phrases.size - 2) {
  199.                 sendBtnForwardInvisible()
  200.             } else {
  201.                 sendBtnForwardVisible()
  202.             }
  203.  
  204.             val nextPhrase = phrases[curPos + 1]
  205.             exoPlayer?.seekTo(nextPhrase.position.toLong() * 1000)
  206.             sendUpdateSeekBar(exoPlayer?.currentPosition?.toInt()!!)
  207.         }
  208.         else {
  209.             sendBtnForwardInvisible()
  210.         }
  211.     }
  212.  
  213.  
  214.     fun updateNotificationBtnPlay(play: Boolean) {
  215.  
  216.         playerNotificationManager.updateNotificationBtnPlay(play)
  217.         sendUpdatePlayButton(exoPlayer?.playWhenReady!!)
  218.     }
  219.  
  220.     val onEverySecond = object : Runnable {
  221.         override fun run() {
  222.             if (exoPlayer != null) {
  223.                 if (phrases.isNotEmpty()) {
  224.                     try {
  225.                         sendSetSeekBarMaxValue()
  226.  
  227.                         sendUpdateSeekBar(exoPlayer?.currentPosition?.toInt()!!)
  228.  
  229.                         val seconds = exoPlayer?.currentPosition?.toInt()!! / 1000
  230.  
  231.                         if (seconds >= phrases[1].position) sendBtnBackVisible()
  232.                         else sendBtnBackInvisible()
  233.  
  234.                         if (seconds >= phrases[phrases.size - 1].position) sendBtnForwardInvisible()
  235.                         else sendBtnForwardVisible()
  236.  
  237.                         sendUpdateTimeText()
  238.  
  239.                         if (exoPlayer?.currentPosition ?: 0 >= audioDuration || exoPlayer?.playWhenReady == false) {
  240.                             Timber.e("Stop self")
  241.                         }
  242.                         else {
  243.                             sendUpdatePhrase()
  244.                             Handler().postDelayed(this, 100)
  245.                         }
  246.                     } catch (e: IllegalStateException) { }
  247.                 }
  248.             }
  249.             else { }
  250.         }
  251.     }
  252.  
  253.     fun setCurPos(pos: Int) {
  254.         curPos = pos
  255.     }
  256.  
  257.  
  258.  
  259.  
  260.     // --- SEND INTENTS TO ACTIVITY ---
  261.  
  262.  
  263.     private fun sendIntent(params: MutableMap<String, Any>) {
  264.         val intent = Intent("intentKey")
  265.         params.forEach { (key, value) ->
  266.             run {
  267.                 when (value) {
  268.                     is Int -> intent.putExtra(key, value)
  269.                     is Long ->intent.putExtra(key, value)
  270.                     is Boolean -> intent.putExtra(key, value)
  271.                     is String -> intent.putExtra(key, value)
  272.                     else -> { }
  273.                 }
  274.             }
  275.         }
  276.         LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
  277.     }
  278.  
  279.     private fun sendStopPlayer() {
  280.         sendIntent(mutableMapOf(Pair(PLAYER_SERVICE_STOP, true)))
  281.     }
  282.  
  283.     private fun sendBtnBackVisible() {
  284.         sendIntent(mutableMapOf(Pair(PLAYER_SERVICE_REWIND_BACK_VISIBLE, true)))
  285.     }
  286.  
  287.     private fun sendBtnBackInvisible() {
  288.         sendIntent(mutableMapOf(Pair(PLAYER_SERVICE_REWIND_BACK_INVISIBLE, true)))
  289.     }
  290.  
  291.     private fun sendBtnForwardVisible() {
  292.         sendIntent(mutableMapOf(Pair(PLAYER_SERVICE_REWIND_NEXT_VISIBLE, true)))
  293.     }
  294.  
  295.     private fun sendBtnForwardInvisible() {
  296.         sendIntent(mutableMapOf(Pair(PLAYER_SERVICE_REWIND_NEXT_INVISIBLE, true)))
  297.     }
  298.  
  299.     private fun sendSetSeekBarMaxValue() {
  300.         sendIntent(mutableMapOf(Pair("SEEKBAR_MAX_VALUE", audioDuration)))
  301.     }
  302.  
  303.     private fun sendUpdatePlayButton(play: Boolean) {
  304.         sendIntent(mutableMapOf(Pair(PLAYER_SERVICE_PLAY_PAUSE, play)))
  305.     }
  306.  
  307.     private fun sendSetLessonName() {
  308.         sendIntent(mutableMapOf(Pair("lessonName", lessonName), Pair("lessonDescription", lessonDescription)))
  309.     }
  310.  
  311.     private fun sendUpdateSeekBar(msg: Int) {
  312.         sendIntent(mutableMapOf(Pair("key", msg)))
  313.     }
  314.  
  315.     private fun sendUpdatePhrase() {
  316.         sendIntent(mutableMapOf(Pair("updatePhrase", true)))
  317.     }
  318.  
  319.     private fun sendUpdateTimeText() {
  320.         sendIntent(mutableMapOf(Pair("current", exoPlayer?.currentPosition ?: 0), Pair("audioDuration", audioDuration)))
  321.     }
  322.  
  323.  
  324.     // --- SEND INTENTS TO ACTIVITY ---
  325.  
  326.  
  327.     override fun onDestroy() {
  328.         isViewAttachedToBottom = false
  329.         exoPlayer?.release()
  330.     }
  331.  
  332.  
  333.     override fun onBind(intent: Intent): IBinder {
  334.         return myBinder
  335.     }
  336.  
  337.  
  338.     internal inner class MyBinder : Binder() {
  339.         val service: PlayerService
  340.             get() = this@PlayerService
  341.     }
  342. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement