Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.example.lighthouse.services
- import android.app.Notification
- import android.app.PendingIntent
- import android.content.Context
- import android.content.Intent
- import android.graphics.Bitmap
- import android.graphics.BitmapFactory
- import android.net.Uri
- import android.os.Bundle
- import android.support.v4.media.MediaDescriptionCompat
- import android.support.v4.media.MediaMetadataCompat
- import android.support.v4.media.session.MediaSessionCompat
- import android.util.Log
- import android.widget.Toast
- import androidx.annotation.Nullable
- import androidx.annotation.UiThread
- import com.example.lighthouse.Application
- import com.example.lighthouse.MainActivity
- import com.example.lighthouse.R
- import com.google.android.exoplayer2.*
- import com.google.android.exoplayer2.audio.AudioAttributes
- import com.google.android.exoplayer2.source.ProgressiveMediaSource
- import com.google.android.exoplayer2.source.MediaSource
- import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
- import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
- import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
- import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator
- import com.google.android.exoplayer2.ui.PlayerNotificationManager
- import io.flutter.plugin.common.MethodChannel
- import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
- import kotlinx.coroutines.GlobalScope
- import kotlinx.coroutines.launch
- import java.net.URL
- class LighthouseStreamService(val ctx: Context, val channel: MethodChannel) {
- private var mediaSession: MediaSessionCompat? = null
- private var playerNotificationManager: PlayerNotificationManager? = null
- private var mediaSessionConnector: MediaSessionConnector? = null
- private var player: SimpleExoPlayer? = null
- private var volumeBeforeMuted = 0F
- private var muted = false
- private var bitmap: Bitmap? = null
- private fun preparePlayer(url: String) {
- val uri = Uri.parse(url)
- val mediaSource = buildMediaSource(ctx, uri)
- player!!.setAudioAttributes(attributes(), true)
- player!!.prepare(mediaSource, true, true)
- player!!.playWhenReady = true
- player!!.addListener(PlayerEventListener())
- }
- private fun initMediaSession(title: String, description: String, image: String) {
- Log.e("e", "he")
- try {
- playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
- ctx,
- Application.NOTIF_CHANNEL,
- R.string.playback_channel,
- R.string.channel_desc,
- 1,
- object : PlayerNotificationManager.MediaDescriptionAdapter {
- override fun getCurrentContentTitle(player: Player): String {
- return title
- }
- @Nullable
- override fun createCurrentContentIntent(player: Player): PendingIntent? = PendingIntent.getActivity(
- ctx,
- 0,
- Intent(ctx, MainActivity::class.java),
- PendingIntent.FLAG_UPDATE_CURRENT)
- @Nullable
- override fun getCurrentContentText(player: Player): String? {
- return description
- }
- @Nullable
- override fun getCurrentLargeIcon(player: Player, callback: PlayerNotificationManager.BitmapCallback): Bitmap? {
- if (bitmap != null) {
- return bitmap
- }
- GlobalScope.launch {
- bitmap = bitMapFromUri(image)
- callback.onBitmap(bitmap)
- }
- return null
- }
- },
- object : PlayerNotificationManager.NotificationListener {
- override fun onNotificationStarted(notificationId: Int, notification: Notification?) {
- // startForeground(notificationId, notification)
- }
- override fun onNotificationCancelled(notificationId: Int) {
- pause()
- }
- override fun onNotificationPosted(notificationId: Int, notification: Notification?, ongoing: Boolean) {
- if (ongoing) {
- print("foreground")
- } else {
- print("background")
- }
- }
- }
- )
- playerNotificationManager!!.setUseNavigationActionsInCompactView(false)
- playerNotificationManager!!.setUseNavigationActions(false)
- playerNotificationManager!!.setSmallIcon(R.mipmap.launcher_icon)
- playerNotificationManager!!.setUseStopAction(false)
- playerNotificationManager!!.setPlayer(player!!)
- mediaSession = MediaSessionCompat(ctx, "lighthouse_media_channel").apply {
- isActive = true
- }
- playerNotificationManager?.setMediaSessionToken(mediaSession?.sessionToken)
- mediaSessionConnector = MediaSessionConnector(mediaSession).apply {
- setQueueNavigator(object : TimelineQueueNavigator(mediaSession) {
- override fun getMediaDescription(player: Player, windowIndex: Int): MediaDescriptionCompat {
- val extras = Bundle().apply {
- putParcelable(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, BitmapFactory.decodeResource(ctx.resources, R.mipmap.launcher_icon))
- }
- return MediaDescriptionCompat.Builder()
- .setTitle(title)
- .setDescription(description)
- .setIconUri(Uri.parse(image))
- .setExtras(extras)
- .build()
- }
- })
- setPlayer(player)
- }
- } catch (e: Throwable) {
- Log.e("e", e.message)
- }
- }
- private fun initializePlayer(url: String, title: String, description: String, image: String): Long {
- if (player != null) {
- player?.release()
- player = null
- }
- player = ExoPlayerFactory.newSimpleInstance(
- ctx,
- DefaultRenderersFactory(ctx),
- DefaultTrackSelector(), DefaultLoadControl())
- preparePlayer(url);
- initMediaSession(title, description, image)
- return (player?.duration ?: 0).toLong()
- }
- private fun buildMediaSource(ctx: Context, uri: Uri): MediaSource {
- return ProgressiveMediaSource.Factory(DefaultDataSourceFactory(ctx, "com.thelighthouseapp.app")).createMediaSource(uri)
- }
- private fun attributes(): AudioAttributes? {
- return AudioAttributes.Builder()
- .setUsage(C.USAGE_MEDIA)
- .setContentType(C.CONTENT_TYPE_MUSIC)
- .build()
- }
- // private fun createNotification(title: String, description: String, image: String) {
- // notification = Notification.Builder(ctx, Application.NOTIF_CHANNEL)
- // .setSmallIcon(R.mipmap.launcher_icon)
- // .setLargeIcon(bitMapFromUri(image))
- // .setContentTitle(title)
- // .setContentText(description)
- // .setStyle(Notification.MediaStyle())
- // .build()
- // notificationManager.notify(1, notification);
- // }
- // private inner class ImageTask(): AsyncTask<String, Bitmap, Bitmap> {
- // override fun onPreExecute() {
- // super.onPreExecute()
- // }
- //
- // override fun doInBackground(vararg params: String?): Bitmap {
- // val image = bitMapFromUri(params[0] ?: "")
- // return image
- // }
- //
- // override fun onPostExecute(result: Bitmap?) {
- // playerNotificationManager!!
- //
- // }
- // }
- private fun bitMapFromUri(uri: String): Bitmap? {
- return try {
- val url = URL(uri)
- val connection = url.openConnection()
- connection.doInput = true;
- connection.connect()
- BitmapFactory.decodeStream(connection.getInputStream())
- } catch (e: Throwable) {
- e.printStackTrace()
- null
- }
- }
- fun play(url: String, isSameUrl: Boolean, title: String, description: String, image: String): Long {
- return if (player == null || !isSameUrl) {
- bitmap = null
- if (player != null) {
- player!!.stop()
- preparePlayer(url)
- releaseMediaSession()
- initMediaSession(title, description, image)
- player!!.playWhenReady = true
- return (player?.duration ?: 0).toLong()
- } else {
- initializePlayer(url, title, description, image)
- }
- } else {
- player!!.playWhenReady = true
- (player?.duration ?: 0).toLong()
- }
- }
- fun currentPos(): Map<String, Long> {
- return if (player != null) {
- mapOf("duration" to (player?.duration ?: 0).toLong(), "currentPos" to (player?.currentPosition ?: 0).toLong())
- } else {
- mapOf("duration" to (0).toLong(), "currentPos" to (0).toLong())
- }
- }
- fun seekTo(forward: Boolean) {
- if (player != null) {
- val currentPos = (player?.currentPosition ?: 0).toLong()
- val goto = if(forward) currentPos + 10000 else currentPos - 10000
- player!!.seekTo(goto.toLong())
- }
- }
- fun seek(pos: Long) {
- if (player != null) {
- player!!.seekTo(pos)
- }
- }
- fun pause() {
- if (player != null) {
- player!!.playWhenReady = false
- }
- }
- fun stop() {
- if (player != null) {
- player!!.playWhenReady = false
- player?.stop()
- player?.release()
- player?.removeListener(PlayerEventListener())
- releaseMediaSession()
- player = null
- }
- }
- private fun releaseMediaSession() {
- mediaSessionConnector?.setPlayer(null);
- playerNotificationManager?.setPlayer(null)
- mediaSession?.release()
- }
- fun mute() {
- if (player != null) {
- if(muted){
- player!!.volume = volumeBeforeMuted
- muted = false
- }
- else{
- volumeBeforeMuted = player!!.volume
- player!!.volume = 0F
- muted = true
- }
- }
- }
- private inner class PlayerEventListener : Player.EventListener {
- override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
- if (playbackState == Player.STATE_ENDED) {
- channel.invokeMethod("stop", null)
- }
- if (playbackState == Player.STATE_READY) {
- if (player!!.playWhenReady) {
- channel.invokeMethod("playing", player!!.duration)
- } else {
- channel.invokeMethod("pause", null)
- }
- } else if (playbackState == Player.STATE_BUFFERING) {
- channel.invokeMethod("buffering", null)
- } else if (playbackState == Player.STATE_ENDED) {
- channel.invokeMethod("stop", null)
- } else {
- print("ok")
- }
- }
- override fun onPlayerError(e: ExoPlaybackException?) {
- Toast.makeText(ctx, "Error playing track, ensure you have an active internet connection ${e?.message ?: ""}", Toast.LENGTH_LONG).show();
- channel.invokeMethod("pause", null)
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement