Advertisement
jessedirisu

Untitled

Jul 8th, 2021 (edited)
318
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 12.26 KB | None | 0 0
  1. package com.example.lighthouse.services
  2.  
  3. import android.app.Notification
  4. import android.app.PendingIntent
  5. import android.content.Context
  6. import android.content.Intent
  7. import android.graphics.Bitmap
  8. import android.graphics.BitmapFactory
  9. import android.net.Uri
  10. import android.os.Bundle
  11. import android.support.v4.media.MediaDescriptionCompat
  12. import android.support.v4.media.MediaMetadataCompat
  13. import android.support.v4.media.session.MediaSessionCompat
  14. import android.util.Log
  15. import android.widget.Toast
  16. import androidx.annotation.Nullable
  17. import androidx.annotation.UiThread
  18.  
  19. import com.example.lighthouse.Application
  20. import com.example.lighthouse.MainActivity
  21. import com.example.lighthouse.R
  22. import com.google.android.exoplayer2.*
  23.  
  24. import com.google.android.exoplayer2.audio.AudioAttributes
  25. import com.google.android.exoplayer2.source.ProgressiveMediaSource
  26. import com.google.android.exoplayer2.source.MediaSource
  27. import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
  28. import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
  29. import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
  30. import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator
  31. import com.google.android.exoplayer2.ui.PlayerNotificationManager
  32. import io.flutter.plugin.common.MethodChannel
  33. import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
  34. import kotlinx.coroutines.GlobalScope
  35. import kotlinx.coroutines.launch
  36. import java.net.URL
  37.  
  38. class LighthouseStreamService(val ctx: Context, val channel: MethodChannel) {
  39.     private var mediaSession: MediaSessionCompat? = null
  40.     private var playerNotificationManager: PlayerNotificationManager? = null
  41.     private var mediaSessionConnector: MediaSessionConnector? = null
  42.     private var player: SimpleExoPlayer? = null
  43.     private var volumeBeforeMuted = 0F
  44.     private var muted = false
  45.     private var bitmap: Bitmap? = null
  46.  
  47.     private fun preparePlayer(url: String) {
  48.         val uri = Uri.parse(url)
  49.         val mediaSource = buildMediaSource(ctx, uri)
  50.         player!!.setAudioAttributes(attributes(), true)
  51.         player!!.prepare(mediaSource, true, true)
  52.         player!!.playWhenReady = true
  53.         player!!.addListener(PlayerEventListener())
  54.     }
  55.  
  56.     private fun initMediaSession(title: String, description: String, image: String) {
  57.         Log.e("e", "he")
  58.         try {
  59.             playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
  60.                     ctx,
  61.                     Application.NOTIF_CHANNEL,
  62.                     R.string.playback_channel,
  63.                     R.string.channel_desc,
  64.                     1,
  65.                     object : PlayerNotificationManager.MediaDescriptionAdapter {
  66.                         override fun getCurrentContentTitle(player: Player): String {
  67.                             return title
  68.                         }
  69.  
  70.                         @Nullable
  71.                         override fun createCurrentContentIntent(player: Player): PendingIntent? = PendingIntent.getActivity(
  72.                                 ctx,
  73.                                 0,
  74.                                 Intent(ctx, MainActivity::class.java),
  75.                                 PendingIntent.FLAG_UPDATE_CURRENT)
  76.  
  77.                         @Nullable
  78.                         override fun getCurrentContentText(player: Player): String? {
  79.                             return description
  80.                         }
  81.  
  82.                         @Nullable
  83.                         override fun getCurrentLargeIcon(player: Player, callback: PlayerNotificationManager.BitmapCallback): Bitmap? {
  84.                             if (bitmap != null) {
  85.                                 return bitmap
  86.                             }
  87.                             GlobalScope.launch {
  88.                                 bitmap = bitMapFromUri(image)
  89.                                 callback.onBitmap(bitmap)
  90.                             }
  91.                             return  null
  92.                         }
  93.                     },
  94.                     object : PlayerNotificationManager.NotificationListener {
  95.                         override fun onNotificationStarted(notificationId: Int, notification: Notification?) {
  96. //                            startForeground(notificationId, notification)
  97.                         }
  98.  
  99.                         override fun onNotificationCancelled(notificationId: Int) {
  100.                             pause()
  101.                         }
  102.  
  103.                         override fun onNotificationPosted(notificationId: Int, notification: Notification?, ongoing: Boolean) {
  104.                             if (ongoing) {
  105.                                 print("foreground")
  106.                             } else {
  107.                                 print("background")
  108.                             }
  109.                         }
  110.                     }
  111.             )
  112.  
  113.             playerNotificationManager!!.setUseNavigationActionsInCompactView(false)
  114.             playerNotificationManager!!.setUseNavigationActions(false)
  115.             playerNotificationManager!!.setSmallIcon(R.mipmap.launcher_icon)
  116.             playerNotificationManager!!.setUseStopAction(false)
  117.             playerNotificationManager!!.setPlayer(player!!)
  118.             mediaSession = MediaSessionCompat(ctx, "lighthouse_media_channel").apply {
  119.                 isActive = true
  120.             }
  121.             playerNotificationManager?.setMediaSessionToken(mediaSession?.sessionToken)
  122.             mediaSessionConnector = MediaSessionConnector(mediaSession).apply {
  123.                 setQueueNavigator(object : TimelineQueueNavigator(mediaSession) {
  124.                     override fun getMediaDescription(player: Player, windowIndex: Int): MediaDescriptionCompat {
  125.                         val extras = Bundle().apply {
  126.                             putParcelable(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, BitmapFactory.decodeResource(ctx.resources, R.mipmap.launcher_icon))
  127.                         }
  128.                         return MediaDescriptionCompat.Builder()
  129.                                 .setTitle(title)
  130.                                 .setDescription(description)
  131.                                 .setIconUri(Uri.parse(image))
  132.                                 .setExtras(extras)
  133.                                 .build()
  134.                     }
  135.                 })
  136.                 setPlayer(player)
  137.             }
  138.         } catch (e: Throwable) {
  139.             Log.e("e", e.message)
  140.         }
  141.     }
  142.  
  143.     private fun initializePlayer(url: String, title: String, description: String, image: String): Long  {
  144.         if (player != null) {
  145.             player?.release()
  146.             player = null
  147.         }
  148.         player = ExoPlayerFactory.newSimpleInstance(
  149.                 ctx,
  150.                 DefaultRenderersFactory(ctx),
  151.                 DefaultTrackSelector(), DefaultLoadControl())
  152.         preparePlayer(url);
  153.         initMediaSession(title, description, image)
  154.         return (player?.duration ?: 0).toLong()
  155.     }
  156.  
  157.     private fun buildMediaSource(ctx: Context, uri: Uri): MediaSource {
  158.         return ProgressiveMediaSource.Factory(DefaultDataSourceFactory(ctx, "com.thelighthouseapp.app")).createMediaSource(uri)
  159.     }
  160.  
  161.     private fun attributes(): AudioAttributes? {
  162.             return AudioAttributes.Builder()
  163.                     .setUsage(C.USAGE_MEDIA)
  164.                     .setContentType(C.CONTENT_TYPE_MUSIC)
  165.                     .build()
  166.     }
  167.  
  168. //    private fun createNotification(title: String, description: String, image: String) {
  169. //        notification = Notification.Builder(ctx, Application.NOTIF_CHANNEL)
  170. //                .setSmallIcon(R.mipmap.launcher_icon)
  171. //                .setLargeIcon(bitMapFromUri(image))
  172. //                .setContentTitle(title)
  173. //                .setContentText(description)
  174. //                .setStyle(Notification.MediaStyle())
  175. //                .build()
  176. //        notificationManager.notify(1, notification);
  177. //    }
  178.  
  179. //    private inner class ImageTask(): AsyncTask<String, Bitmap, Bitmap> {
  180. //        override fun onPreExecute() {
  181. //            super.onPreExecute()
  182. //        }
  183. //
  184. //        override fun doInBackground(vararg params: String?): Bitmap {
  185. //            val image = bitMapFromUri(params[0] ?: "")
  186. //            return image
  187. //        }
  188. //
  189. //        override fun onPostExecute(result: Bitmap?) {
  190. //            playerNotificationManager!!
  191. //
  192. //        }
  193. //    }
  194.     private fun bitMapFromUri(uri: String): Bitmap? {
  195.         return try {
  196.             val url = URL(uri)
  197.             val connection = url.openConnection()
  198.             connection.doInput = true;
  199.             connection.connect()
  200.             BitmapFactory.decodeStream(connection.getInputStream())
  201.         } catch (e: Throwable) {
  202.             e.printStackTrace()
  203.             null
  204.         }
  205.     }
  206.  
  207.     fun play(url: String, isSameUrl: Boolean, title: String, description: String, image: String): Long {
  208.         return if (player == null || !isSameUrl) {
  209.             bitmap = null
  210.             if (player != null) {
  211.                 player!!.stop()
  212.                 preparePlayer(url)
  213.                 releaseMediaSession()
  214.                 initMediaSession(title, description, image)
  215.                 player!!.playWhenReady  = true
  216.                 return (player?.duration ?: 0).toLong()
  217.             } else {
  218.                 initializePlayer(url, title, description, image)
  219.             }
  220.         } else {
  221.             player!!.playWhenReady = true
  222.             (player?.duration ?: 0).toLong()
  223.         }
  224.     }
  225.  
  226.     fun currentPos(): Map<String, Long> {
  227.         return if (player != null) {
  228.             mapOf("duration" to (player?.duration ?: 0).toLong(), "currentPos" to (player?.currentPosition ?: 0).toLong())
  229.         } else {
  230.             mapOf("duration" to (0).toLong(), "currentPos" to (0).toLong())
  231.         }
  232.     }
  233.  
  234.     fun seekTo(forward: Boolean) {
  235.         if (player != null) {
  236.             val currentPos = (player?.currentPosition ?: 0).toLong()
  237.             val goto = if(forward) currentPos + 10000 else currentPos - 10000
  238.             player!!.seekTo(goto.toLong())
  239.         }
  240.     }
  241.  
  242.     fun seek(pos: Long) {
  243.         if (player != null) {
  244.             player!!.seekTo(pos)
  245.         }
  246.     }
  247.  
  248.     fun pause() {
  249.         if (player != null) {
  250.             player!!.playWhenReady = false
  251.         }
  252.     }
  253.  
  254.     fun stop() {
  255.         if (player != null) {
  256.             player!!.playWhenReady = false
  257.             player?.stop()
  258.             player?.release()
  259.             player?.removeListener(PlayerEventListener())
  260.             releaseMediaSession()
  261.             player = null
  262.         }
  263.     }
  264.  
  265.     private fun releaseMediaSession() {
  266.         mediaSessionConnector?.setPlayer(null);
  267.         playerNotificationManager?.setPlayer(null)
  268.         mediaSession?.release()
  269.     }
  270.  
  271.     fun mute() {
  272.         if (player != null) {
  273.             if(muted){
  274.                 player!!.volume = volumeBeforeMuted
  275.                 muted = false
  276.             }
  277.             else{
  278.                 volumeBeforeMuted = player!!.volume
  279.                 player!!.volume = 0F
  280.                 muted = true
  281.             }
  282.         }
  283.     }
  284.  
  285.     private inner class PlayerEventListener : Player.EventListener {
  286.         override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
  287.             if (playbackState == Player.STATE_ENDED) {
  288.                 channel.invokeMethod("stop", null)
  289.             }
  290.             if (playbackState == Player.STATE_READY) {
  291.                 if (player!!.playWhenReady) {
  292.                     channel.invokeMethod("playing", player!!.duration)
  293.                 } else {
  294.                     channel.invokeMethod("pause", null)
  295.                 }
  296.             } else if (playbackState == Player.STATE_BUFFERING) {
  297.                 channel.invokeMethod("buffering", null)
  298.             } else if (playbackState == Player.STATE_ENDED) {
  299.                 channel.invokeMethod("stop", null)
  300.             } else {
  301.                 print("ok")
  302.             }
  303.         }
  304.  
  305.         override fun onPlayerError(e: ExoPlaybackException?) {
  306.             Toast.makeText(ctx, "Error playing track, ensure you have an active internet connection ${e?.message ?: ""}", Toast.LENGTH_LONG).show();
  307.             channel.invokeMethod("pause", null)
  308.         }
  309.     }
  310. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement