Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.andyshon.ucanspeak.ui.catalogTab.catalog.player
- import android.app.*
- import android.content.Context
- import android.content.Intent
- import android.graphics.BitmapFactory
- import android.net.Uri
- import android.os.Binder
- import android.os.Build
- import android.os.Handler
- import android.os.IBinder
- import android.support.v4.app.NotificationCompat
- import com.andyshon.ucanspeak.events.*
- import com.google.android.exoplayer2.*
- import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory
- import com.google.android.exoplayer2.source.ExtractorMediaSource
- import com.google.android.exoplayer2.source.TrackGroupArray
- import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
- import com.google.android.exoplayer2.trackselection.TrackSelectionArray
- import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
- import com.google.android.exoplayer2.util.Util
- import timber.log.Timber
- import java.util.*
- import android.support.v4.content.LocalBroadcastManager
- import android.support.v4.media.session.MediaSessionCompat
- import com.andyshon.ucanspeak.data.entity.LessonFilePhraseEntity
- import com.google.android.exoplayer2.Player
- import com.andyshon.ucanspeak.R
- import com.andyshon.ucanspeak.ui.catalogTab.CatalogTabActivity
- import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
- private const val NOTIFY_ID = 1
- class PlayerService : Service() {
- companion object {
- var isViewAttachedToBottom = false
- var rxEventBus: RxEventBus? = null
- var phrases: ArrayList<LessonFilePhraseEntity> = arrayListOf()
- }
- private lateinit var builder : NotificationCompat.Builder
- private lateinit var notificationManager: NotificationManager
- private var myBinder = MyBinder()
- var exoPlayer: SimpleExoPlayer? = null
- private var mediaSession: MediaSessionCompat? = null
- private var audioDuration = 0L
- var isPlay = false
- private var curPos = 0
- private var playerPosition: Long = 0
- private var lessonName = ""
- private var lessonDescription = ""
- var fileLink = ""
- private var isShowNotification = false
- override fun onBind(intent: Intent): IBinder {
- return myBinder
- }
- internal inner class MyBinder : Binder() {
- val service: PlayerService
- get() = this@PlayerService
- }
- override fun onCreate() {
- val context: Context = this
- val renderersFactory = DefaultRenderersFactory(
- context,
- null,
- DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF
- )
- val trackSelector = DefaultTrackSelector()
- exoPlayer = ExoPlayerFactory.newSimpleInstance(
- renderersFactory,
- trackSelector
- )
- exoPlayer?.addListener(object : Player.EventListener {
- override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
- Timber.e("onPlayerStateChanged $playWhenReady : $playbackState")
- if (playWhenReady && playbackState == Player.STATE_READY) {
- // media actually playing
- audioDuration = exoPlayer?.duration ?: 0
- Timber.e("DURATION = $audioDuration}")
- sendSetSeekBarMaxValue()
- val handler = Handler()
- handler.postDelayed(onEverySecond, 100)
- }
- else {
- Timber.e("Exoplayer listener else state = $playbackState")
- if (playbackState == 4) {
- sendStopPlayer()
- }
- }
- }
- override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) {}
- override fun onSeekProcessed() {}
- override fun onTracksChanged(trackGroups: TrackGroupArray?, trackSelections: TrackSelectionArray?) {}
- override fun onPlayerError(error: ExoPlaybackException?) {}
- override fun onLoadingChanged(isLoading: Boolean) {}
- override fun onPositionDiscontinuity(reason: Int) {}
- override fun onRepeatModeChanged(repeatMode: Int) {}
- override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {}
- override fun onTimelineChanged(timeline: Timeline?, manifest: Any?, reason: Int) {}
- })
- }
- override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
- Timber.e("onStartCommand called intent = $intent")
- isViewAttachedToBottom = true
- if (intent?.hasExtra("lessonName") == true) {
- Timber.e("lessonName")
- Timber.e("has extra lessonName!")
- lessonName = intent.getStringExtra("lessonName")
- lessonDescription = intent.getStringExtra("lessonDescription")
- sendSetLessonName()
- }
- if (intent?.hasExtra("isPlay") == true) {
- Timber.e("isPlay")
- isPlay = intent.getBooleanExtra("isPlay", false)
- exoPlayer?.playWhenReady = /*isPlay*/true
- sendUpdatePlayButton()
- }
- if (intent?.hasExtra("UPDATE_PLAYER_FLOW_BTN_PLAY") == true) {
- Timber.e("UPDATE_PLAYER_FLOW_BTN_PLAY ${exoPlayer?.playWhenReady}")
- sendUpdatePlayButton2()
- }
- if (intent?.hasExtra("STOP_RESUME") == true) {
- Timber.e("STOP_RESUME player ${exoPlayer?.playWhenReady}")
- exoPlayer?.playWhenReady = exoPlayer?.playWhenReady?.not()!!
- sendUpdatePlayButton2()
- updateNotificationBtnPlay(exoPlayer?.playWhenReady ?: false)
- }
- if (intent?.hasExtra("REWIND_NEXT") == true) {
- setCurPos(++curPos)
- rewindForward()
- }
- if (intent?.hasExtra("REWIND_BACK") == true) {
- setCurPos(--curPos)
- rewindBack()
- }
- if (intent?.hasExtra("SEEKBAR_CHANGE") == true) {
- val progress = intent.getIntExtra("SEEKBAR_CHANGE", 0)
- exoPlayer?.seekTo(progress.toLong())
- updateTime()
- }
- if (intent?.hasExtra("PAUSE_PLAYER") == true) {
- isViewAttachedToBottom = false
- exoPlayer?.playWhenReady = false
- closeNotification()
- }
- if (intent?.hasExtra("BLABLA") == true) {
- val b = intent.getBooleanExtra("BLABLA", false)
- Timber.e("BLABLA $b")
- updateNotificationBtnPlay(b)
- exoPlayer?.playWhenReady = b // Handler sending message to a Handler on a dead thread
- }
- if (intent?.hasExtra("CLICK") == true) {
- Timber.e("Click player from notification")
- exoPlayer?.playWhenReady = exoPlayer?.playWhenReady?.not() ?: false
- val intent6 = Intent("intentKey")
- intent6.putExtra("GGGG", exoPlayer?.playWhenReady)
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent6)
- updateNotificationBtnPlay(exoPlayer?.playWhenReady ?: false)
- }
- if (intent?.hasExtra("SET_FILE_LINK") == true) {
- fileLink = intent.getStringExtra("SET_FILE_LINK")
- val userAgent = Util.getUserAgent(this, "Play Audio")
- val mediaSource = ExtractorMediaSource(
- Uri.parse(fileLink), // file audio ada di folder assets
- DefaultDataSourceFactory(this, userAgent),
- DefaultExtractorsFactory(), null, null
- )
- // init media session
- mediaSession = MediaSessionCompat(this, packageName)
- val mediaSessionConnector = MediaSessionConnector(mediaSession)
- mediaSessionConnector.setPlayer(exoPlayer, null)
- mediaSession!!.isActive = true
- Timber.e("sessionToken 2 = ${mediaSession?.sessionToken}")
- exoPlayer?.prepare(mediaSource)
- exoPlayer?.playWhenReady = true
- notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
- createNotification(this, isPlay)
- }
- if (intent?.hasExtra("CREATE_NOTIFICATION") == true) {
- if (isShowNotification) {
- }
- else {
- createNotification(this, /*isPlay*/false)
- }
- }
- return START_NOT_STICKY
- }
- private fun createNotification(context: Context, isStartPlay: Boolean) {
- val id = "Default_channel_id" // default_channel_id
- val title = "UCanSpeak" // Default Channel
- val acceptPlay = Intent(this, PlayerNotificationReceiver::class.java)
- acceptPlay.action = "Player_play"
- val pendingIntentBtnPlay = PendingIntent.getBroadcast(this, 0, acceptPlay,
- PendingIntent.FLAG_UPDATE_CURRENT)
- val acceptBack = Intent(this, PlayerNotificationReceiver::class.java)
- acceptBack.action = "Player_back"
- val pendingIntentBtnBack = PendingIntent.getBroadcast(this, 0, acceptBack,
- PendingIntent.FLAG_UPDATE_CURRENT)
- val acceptForward = Intent(this, PlayerNotificationReceiver::class.java)
- acceptForward.action = "Player_forward"
- val pendingIntentBtnForward = PendingIntent.getBroadcast(this, 0, acceptForward,
- PendingIntent.FLAG_UPDATE_CURRENT)
- val intent = Intent(context, CatalogTabActivity::class.java)
- val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
- val myLogo = BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher)
- val myLogo2 = BitmapFactory.decodeResource(resources, R.drawable.ic_logo_big_notification)
- builder = NotificationCompat.Builder(context, id)
- builder.addAction(R.drawable.ic_player_hide_previous_btn, "Rewind back", pendingIntentBtnBack)
- if (isStartPlay)
- builder.addAction(R.drawable.exo_icon_pause, "Play/Resume", pendingIntentBtnPlay)
- else
- builder.addAction(R.drawable.exo_icon_play, "Play/Resume", pendingIntentBtnPlay)
- builder.addAction(R.drawable.ic_player_hide_next_btn, "Rewind forward", pendingIntentBtnForward)
- .setStyle(android.support.v4.media.app.NotificationCompat.MediaStyle().setShowActionsInCompactView(0,1,2).setMediaSession(mediaSession?.sessionToken))
- .setSmallIcon(R.mipmap.ic_launcher)
- .setShowWhen(false)
- .setOngoing(true)
- .setSound(null)
- // .setSound(Uri.parse("android.resource://"+YOUR_APP_PACKAGE_NAME+"/"+R.raw.silence)) //TODO: just set silent sound
- .setContentTitle(lessonName)
- .setContentText(lessonDescription)
- .setContentIntent(pendingIntent)
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- val importance = NotificationManager.IMPORTANCE_DEFAULT
- var mChannel = notificationManager.getNotificationChannel(id)
- if (mChannel == null) {
- mChannel = NotificationChannel(id, title, importance)
- notificationManager.createNotificationChannel(mChannel)
- }
- builder
- .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
- .setLargeIcon(myLogo)
- .priority = Notification.PRIORITY_MAX
- }
- else {
- builder
- .setLargeIcon(myLogo2)
- .setTicker(lessonName)
- // .priority = Notification.PRIORITY_HIGH
- }
- val notification = builder.build()
- notificationManager.notify(NOTIFY_ID, notification)
- isShowNotification = true
- }
- private fun closeNotification() {
- notificationManager.cancel(NOTIFY_ID)
- isShowNotification = false
- }
- private fun rewindBack() {
- Timber.e("REWIND_BACK Curpos = $curPos")
- if (curPos > 0) {
- if (curPos == 0) {
- sendBtnBackInvisible()
- } else {
- sendBtnBackVisible()
- }
- val previousPhrase = phrases[curPos - 1]
- Timber.e("playerBtnBack call curPost = $curPos previousPhrase pos ${previousPhrase.position}")
- exoPlayer?.seekTo(previousPhrase.position.toLong() * 1000)
- sendUpdateSeekBar(exoPlayer?.currentPosition?.toInt()!!)
- updateTime()
- }
- else {
- sendBtnBackInvisible()
- }
- }
- private fun rewindForward() {
- Timber.e("REWIND_NEXT Curpos = $curPos")
- if (curPos < phrases.size - 1) {
- if (curPos == phrases.size - 2) {
- sendBtnForwardInvisible()
- } else {
- sendBtnForwardVisible()
- }
- val nextPhrase = phrases[curPos + 1]
- exoPlayer?.seekTo(nextPhrase.position.toLong() * 1000)
- sendUpdateSeekBar(exoPlayer?.currentPosition?.toInt()!!)
- updateTime()
- }
- else {
- sendBtnForwardInvisible()
- }
- }
- fun updateNotificationBtnPlay(isPlay: Boolean) {
- //TODO: first update play button on flow player layout
- sendUpdatePlayButton2()
- val acceptPlay = Intent(this, PlayerNotificationReceiver::class.java)
- acceptPlay.action = "Player_play"
- val pendingIntentBtnPlay = PendingIntent.getBroadcast(this, 0, acceptPlay,
- PendingIntent.FLAG_UPDATE_CURRENT)
- val acceptBack = Intent(this, PlayerNotificationReceiver::class.java)
- acceptBack.action = "Player_back"
- val pendingIntentBtnBack = PendingIntent.getBroadcast(this, 0, acceptBack,
- PendingIntent.FLAG_UPDATE_CURRENT)
- val acceptForward = Intent(this, PlayerNotificationReceiver::class.java)
- acceptForward.action = "Player_forward"
- val pendingIntentBtnForward = PendingIntent.getBroadcast(this, 0, acceptForward,
- PendingIntent.FLAG_UPDATE_CURRENT)
- builder.mActions.clear()
- if (isPlay) {
- builder.addAction(R.drawable.ic_player_hide_previous_btn, "Rewind back", pendingIntentBtnBack)
- builder.addAction(R.drawable.exo_icon_pause, "Play/Resume", pendingIntentBtnPlay)
- builder.addAction(R.drawable.ic_player_hide_next_btn, "Rewind forward", pendingIntentBtnForward)
- }
- else {
- builder.addAction(R.drawable.ic_player_hide_previous_btn, "Rewind back", pendingIntentBtnBack)
- builder.addAction(R.drawable.exo_icon_play, "Play/Resume", pendingIntentBtnPlay)
- builder.addAction(R.drawable.ic_player_hide_next_btn, "Rewind forward", pendingIntentBtnForward)
- }
- notificationManager.notify(NOTIFY_ID, builder.build())
- }
- private fun updateNotificationBtnRewindBack(isVisible: Boolean) {
- if (isVisible) { }
- else { }
- }
- private fun updateNotificationBtnRewindForward(isVisible: Boolean) {
- if (isVisible) { }
- else { }
- }
- fun setCurPos(pos: Int) {
- curPos = pos
- }
- private fun sendStopPlayer() {
- val intent = Intent("intentKey")
- intent.putExtra("STOP_PLAYER", true)
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- }
- private fun sendBtnBackVisible() {
- val intent = Intent("intentKey")
- intent.putExtra("BTN_BACK_VISIBLE", true)
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- }
- private fun sendBtnBackInvisible() {
- val intent = Intent("intentKey")
- intent.putExtra("BTN_BACK_INVISIBLE", true)
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- }
- private fun sendBtnForwardVisible() {
- val intent = Intent("intentKey")
- intent.putExtra("BTN_FORWARD_VISIBLE", true)
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- }
- private fun sendBtnForwardInvisible() {
- val intent = Intent("intentKey")
- intent.putExtra("BTN_FORWARD_INVISIBLE", true)
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- }
- private fun sendSetSeekBarMaxValue() {
- val intent = Intent("intentKey")
- intent.putExtra("SEEKBAR_MAX_VALUE", audioDuration)
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- }
- private fun sendUpdatePlayButton2() {
- val intent = Intent("intentKey")
- intent.putExtra("STOP_RESUME", exoPlayer?.playWhenReady)
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- }
- private fun sendUpdatePlayButton() {
- val intent = Intent("intentKey")
- intent.putExtra("yes", true)
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- }
- private fun sendSetLessonName() {
- val intent = Intent("intentKey")
- intent.putExtra("lessonName", lessonName)
- intent.putExtra("lessonDescription", lessonDescription)
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- }
- private fun sendUpdateSeekBar(msg: Int) {
- val intent = Intent("intentKey")
- intent.putExtra("key", msg)
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- }
- val onEverySecond = object : Runnable {
- override fun run() {
- if (exoPlayer != null) {
- if (phrases.isNotEmpty()) {
- try {
- sendSetSeekBarMaxValue()
- sendUpdateSeekBar(exoPlayer?.currentPosition?.toInt()!!)
- val seconds = exoPlayer?.currentPosition?.toInt()!! / 1000
- if (seconds >= phrases[1].position) {
- sendBtnBackVisible()
- } else {
- sendBtnBackInvisible()
- }
- if (seconds >= phrases[phrases.size - 1].position) {
- sendBtnForwardInvisible()
- } else {
- sendBtnForwardVisible()
- }
- updateTime()
- sendUpdateTimeText()
- Timber.e("CUR POS EXO = ${exoPlayer?.currentPosition} : duration = $audioDuration")
- if (exoPlayer?.currentPosition ?: 0 >= audioDuration || exoPlayer?.playWhenReady == false) {
- Timber.e("Stop self")
- // stopSelf()
- }
- else {
- sendUpdatePhrase()
- Handler().postDelayed(this, 100)
- }
- } catch (e: IllegalStateException) {
- Timber.e("CATCH onEverySecond run")
- }
- }
- }
- else { }
- }
- }
- private fun updateTime() {
- playerPosition = exoPlayer?.currentPosition!! / 1000
- }
- private fun sendUpdatePhrase() {
- val intent = Intent("intentKey")
- intent.putExtra("updatePhrase", true)
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- }
- private fun sendUpdateTimeText() {
- val intent = Intent("intentKey")
- intent.putExtra("current", exoPlayer?.currentPosition)
- intent.putExtra("audioDuration", audioDuration)
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- }
- override fun onDestroy() {
- isViewAttachedToBottom = false
- exoPlayer?.release()
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement