Last active
October 3, 2021 17:25
-
-
Save izyaboi/5d53cd3dada60fb2d024255576e5af97 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.bmradio | |
import android.content.Intent | |
import android.os.Bundle | |
import androidx.activity.ComponentActivity | |
import androidx.activity.compose.setContent | |
import androidx.compose.animation.ExperimentalAnimationApi | |
import androidx.compose.material.MaterialTheme | |
import androidx.compose.material.Surface | |
import androidx.core.view.WindowCompat | |
import com.example.bmradio.service.PlayerNotificationService | |
import com.example.bmradio.ui.theme.BMRadioTheme | |
import com.google.accompanist.insets.ProvideWindowInsets | |
import dagger.hilt.android.AndroidEntryPoint | |
import kotlinx.coroutines.ExperimentalCoroutinesApi | |
import kotlinx.coroutines.FlowPreview | |
import kotlinx.coroutines.InternalCoroutinesApi | |
import com.google.android.exoplayer2.SimpleExoPlayer | |
import android.content.ComponentName | |
import android.content.Context | |
import android.os.IBinder | |
import android.content.ServiceConnection | |
import android.util.AttributeSet | |
import android.view.View | |
import com.google.android.exoplayer2.util.Util | |
@ExperimentalCoroutinesApi | |
@AndroidEntryPoint | |
class MainActivity : ComponentActivity(){ | |
private var player: SimpleExoPlayer? = null | |
private lateinit var playerNotificationService: PlayerNotificationService | |
private var bound = false | |
private val serviceConnection: ServiceConnection = object : ServiceConnection { | |
override fun onServiceConnected(componentName: ComponentName, service: IBinder) { | |
val binder = service as PlayerNotificationService.LocalBinder | |
playerNotificationService = binder.getService() | |
bound = true | |
initPlayer() | |
} | |
override fun onServiceDisconnected(componentName: ComponentName) { | |
bound = false | |
} | |
} | |
private fun initPlayer() { | |
if(bound){ | |
player = playerNotificationService.player | |
} | |
} | |
@ExperimentalAnimationApi | |
@FlowPreview | |
@InternalCoroutinesApi | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
val intent = Intent(this,PlayerNotificationService::class.java) | |
Util.startForegroundService(this,intent) | |
initPlayer() | |
WindowCompat.setDecorFitsSystemWindows(window, false) | |
setContent { | |
BMRadioTheme { | |
ProvideWindowInsets{ | |
Surface(color = MaterialTheme.colors.background) { | |
MainScreen(player) | |
} | |
} | |
} | |
} | |
} | |
override fun onStart() { | |
super.onStart() | |
Intent(this, PlayerNotificationService::class.java).also { | |
bindService(intent,serviceConnection, Context.BIND_AUTO_CREATE) | |
} | |
} | |
override fun onStop() { | |
super.onStop() | |
unbindService(serviceConnection) | |
bound = false | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.bmradio.service | |
import android.app.Notification | |
import android.app.PendingIntent | |
import android.app.Service | |
import android.content.Intent | |
import android.graphics.Bitmap | |
import android.os.IBinder | |
import com.example.bmradio.MainActivity | |
import com.example.bmradio.R | |
import com.example.bmradio.di.AppModule | |
import com.google.android.exoplayer2.MediaItem | |
import com.google.android.exoplayer2.Player | |
import com.google.android.exoplayer2.SimpleExoPlayer | |
import com.google.android.exoplayer2.source.ProgressiveMediaSource | |
import com.google.android.exoplayer2.ui.PlayerNotificationManager | |
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource | |
import kotlinx.coroutines.ExperimentalCoroutinesApi | |
import android.os.Binder | |
@ExperimentalCoroutinesApi | |
class PlayerNotificationService : Service() { | |
var player: SimpleExoPlayer? = null | |
private lateinit var dataSourceFactory: DefaultHttpDataSource.Factory | |
private lateinit var playerNotificationManager: PlayerNotificationManager | |
private val binder: IBinder = LocalBinder() | |
private var notificationId = 123; | |
private var channelId = "channelId" | |
override fun onCreate() { | |
super.onCreate() | |
initPlayer() | |
} | |
private fun initPlayer() { | |
val context = this | |
player = SimpleExoPlayer.Builder(this) | |
.build() | |
.apply { | |
dataSourceFactory = DefaultHttpDataSource.Factory() | |
val source = ProgressiveMediaSource.Factory(dataSourceFactory) | |
.createMediaSource(MediaItem.fromUri(AppModule.RadioUrl)) | |
setMediaSource(source) | |
prepare() | |
} | |
playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel( | |
this, | |
channelId, | |
R.string.channel_name, | |
R.string.channel_desc, | |
notificationId, | |
object : PlayerNotificationManager.MediaDescriptionAdapter { | |
override fun createCurrentContentIntent(player: Player): PendingIntent? { | |
// return pending intent | |
val intent = Intent(context,MainActivity::class.java) | |
return PendingIntent.getActivity( | |
context, 0, intent, | |
PendingIntent.FLAG_UPDATE_CURRENT | |
) | |
} | |
//pass description here | |
override fun getCurrentContentText(player: Player): String? { | |
return "Description" | |
} | |
//pass title (mostly playing audio name) | |
override fun getCurrentContentTitle(player: Player): String { | |
return "Title" | |
} | |
// pass image as bitmap | |
override fun getCurrentLargeIcon( | |
player: Player, | |
callback: PlayerNotificationManager.BitmapCallback | |
): Bitmap? { | |
return null | |
} | |
}, | |
object : PlayerNotificationManager.NotificationListener { | |
override fun onNotificationPosted( | |
notificationId: Int, | |
notification: Notification, | |
onGoing: Boolean) { | |
startForeground(notificationId, notification) | |
} | |
override fun onNotificationCancelled( | |
notificationId: Int, | |
dismissedByUser: Boolean | |
) { | |
stopSelf() | |
} | |
} | |
) | |
playerNotificationManager.setPlayer(player) | |
} | |
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { | |
if(player == null){ | |
initPlayer() | |
} | |
return START_STICKY | |
} | |
// detach player | |
override fun onDestroy() { | |
playerNotificationManager.setPlayer(null) | |
player?.release() | |
super.onDestroy() | |
} | |
override fun onTaskRemoved(rootIntent: Intent?) { | |
super.onTaskRemoved(rootIntent) | |
stopSelf() | |
} | |
inner class LocalBinder : Binder() { | |
fun getService(): PlayerNotificationService = this@PlayerNotificationService | |
} | |
override fun onBind(p0: Intent?): IBinder = binder | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment