So far I only found questions about how to make ExoPlayer keep playing when app goes to background. Why the hell is that the case by me without coding this bs??
This is what I have so far and it's inside RecyclerView OnBingViewHolder:
val player = ExoPlayer.Builder(context).build()
val mediaItem: MediaItem = MediaItem.fromUri(fileUrl)
player.setMediaItem(mediaItem)
player.repeatMode = Player.REPEAT_MODE_ONE
holder.vidPlayer.player = player
player.prepare()
player.seekTo(100)
// player.play()
holder.vidPlayer.setTag(mpTag, player)
holder.vidPlayer.setTag(manuelPlayTag, false)
holder.vidPlayer.setTag(manuelPauseTag, false)
player.addListener(object : Player.Listener { // player listener
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
if (playWhenReady && playbackState == Player.STATE_READY) {
Log.d(tagg, "state: plays")
holder.vidPlayer.hideController()
} else if (playWhenReady) {
// might be idle (plays after prepare()),
// buffering (plays when data available)
// or ended (plays when seek away from end)
} else {
Log.d(tagg, "state: pause")
holder.vidPlayer.showController()
}
}
})
how I prevent the play when app goes to background?
When your app goes to the background the active Fragment/Activity's Lifecycle method onPause (and onStop) is called. In the onPause method you can cycle through your bound ViewHolders and stop the video player(s).
You can simply stop the ExoPlayer when the app goes to the background.
override fun onStop() {
super.onStop()
simpleExoPlayer.stop()
}
And in onStart just prepare() the ExoPlayer again:
override fun onStart() {
super.onStart()
simpleExoPlayer.prepare()
}
In order to automatically play the media, you need to set playWhenReady = true.
simpleExoPlayer.playWhenReady = true
By setting playWhenReady = true it will automcatically play the content and we don't need to explicitly call simpleExoPlayer.play().
Related
I just want to delay a task in a fragment and if the app goes to the background while the delay is running the scope should never resume when the app comes to the foreground:
With following 2 approaches both will execute once the app comes back again, but I want that this never returns once the app was in the background. How to achieve that?
lifecycleScope.launch {
lifecycle.whenResumed {
Timber.d("before delay 1")
delay(15000)
Timber.d("after delay 1")
}
}
lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
Timber.d("before delay 2")
delay(15000)
Timber.d("after delay 2")
}
}
kotlinx.coroutines.delay()
A Job launched by lifecycleScope will not be canceled until lifecycle destroy
https://developer.android.com/reference/kotlin/androidx/lifecycle/LifecycleCoroutineScope
If you need to run it once you have to write something like this
private var delayedJob: Job? = null
override fun onResume() {
if(delayedJob == null) {
delayedJob = lifecycleScope.launch {
Timber.d("before delay")
delay(15000)
Timber.d("after delay")
}
}
}
override fun onPause() {
delayedJob?.cancel()
}
Google cloud TTS audio does not stop after activity destroy.
googleCloudTTS = GoogleCloudTTSFactory.create(BuildConfig.API_KEY)
override fun onDestroy() {
destroyStory()
super.onDestroy()
}
// destroy story
private fun destroyStory() {
IS_PLAY_AUDIO = false
// googleCloudTTS?.stop()
googleCloudTTS?.close()
}
I tried with both googleCloudTTS?.close() and googleCloudTTS?.stop() but doesn't stop playing audio.
I am new to programming and I am making a basic app for radio in which an introduction audio sounds when you press a button, then a second audio should appear until the network connection of the online radio is established.
I have managed to make the intro audio sound complete when I click, then silence is generated until the online radio plays, but I don't know how to put a second audio that detects the charging status before the radio plays. This is my code:
fun MediaPlayerRadio(){
mediaPlayer = MediaPlayer.create(
this#MainActivity,
Uri.parse("https://radiolink.com")
)
mediaPlayer?.start()
}
........................................................................
fun MediaPlayerIntroSound(){
mediaPlayer = MediaPlayer.create(this, R.raw.SoundIntro)
mediaPlayer?.start()
}
........................................................................
fun click_Button_Radio(){
btn.setOnClickListener(){
if (btn.isSelected){
btn.isSelected = false
mediaPlayer?.stop()
}else{
btn.isSelected = !btn.isSelected
MediaPlayerIntroSound()
mediaPlayer!!.setOnCompletionListener(object : MediaPlayer.OnCompletionListener {
override fun onCompletion(mp: MediaPlayer?) {
MediaPlayerRadio()
}
})
}
}
}
I hope you can support me with this.
For this, you will have to use 2 media players, one for intro sound and another for actual sound.
While the time actual sound media player gets ready, you can play different audios on the intro sound media player.
To stop the intro audio player once the other player is ready, you can make use of a view model.
//Play Media player
mediaPlayer = MediaPlayer.create(this#MainActivity, R.raw.first_audio)
mediaPlayer.start()
// Add completion listener, so that we can change the audio
// once the first one is finished
mediaPlayer.setOnCompletionListener {
mediaPlayer.release()
mediaPlayer = MediaPlayer.create(this#MainActivity, R.raw.second_audio)
mediaPlayer.start()
}
// We are observing a MutableLiveData of Boolean type,
// once it is true we will stop the intro media player
// and start the radio player
viewModel.isPlayerReady.observe(this) { isReady ->
if(isReady) {
mediaPlayer.stop()
// Start radio media player
}
}
// This is how I am changing the value of MutableLiveData
demoBtn.setOnClickListener {
viewModel.isPlayerReady.value = true
}
I have tested the above approach and it works fine as expected.
Steps to link a view model to the activity:
Add the dependency: implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
Make a view model class and a mutable live variable of type boolean in it.
class MainViewModel: ViewModel() {
val isPlayerReady = MutableLiveData<Boolean>()
}
Link view model with the activity.
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
....
}
I am trying to implement the PierfrancescoSoffritti youtube Player but I am having issues the player callback OnReady never gets called
here is my code I don't know whats the issue here
<com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
android:id="#+id/player_youtube"
android:keepScreenOn="true"
app:showYouTubeButton="false"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
here is the XML
here is my kotlin implementation I am dynamically loading the video id to the player
viewModel.playYoutube.observe(this, EventObserver {
with(binding.playerYoutube) {
lifecycle.addObserver(this)
isVisible = true
addFullScreenListener(this#MyCourseActivity)
}
setYoutubePlayer(viewModel.youtubeUrl!!)
})
}
private fun setYoutubePlayer(youtubeUrl: String) {
if (::youtubePlayer.isInitialized) {
val id = getYoutubeVideoId(youtubeUrl)
youtubePlayer.loadVideo(id, 0f)
}
binding.playerYoutube.addYouTubePlayerListener(object : AbstractYouTubePlayerListener() {
override fun onCurrentSecond(youTubePlayer: YouTubePlayer, second: Float) {
super.onCurrentSecond(youTubePlayer, second)
Timber.d("onCurrentSecond %s ",second)
}
override fun onReady(youTubePlayer: YouTubePlayer) {
Timber.d("onReady called YouTube")
youtubePlayer = youTubePlayer
youtubePlayer.addListener(tracker)
val id = getYoutubeVideoId(youtubeUrl)
youTubePlayer.loadVideo(id, 0f)
}
})
Timber.d("tracker state %s",tracker.state)
Timber.d("tracker state %s",tracker.currentSecond)
Timber.d("tracker state %s",tracker.videoDuration)
Timber.d("tracker state %s",tracker.videoId)
}
I am using kotlin and androidX Dependencies
kindly guide me on why the player isn't working
the states which I am receiving are ->
tracker state UNKNOWN
tracker state 0.0
tracker state 0.0
tracker state null
In my app I want to display a splash screen and after 4 seconds go to HomeActivity. However, I would like to pause the execution by touching imageview imageSplash and resume when releasing. How to do this?
GlobalScope.launch(context = Dispatchers.Main) {
imageSplash.setOnTouchListener { view, motionEvent ->
when(motionEvent.action){
MotionEvent.ACTION_DOWN ->{
true
}
MotionEvent.ACTION_UP->{
true
}
else ->{
false
}
}
}
delay(4000)
val intent = Intent(this#SplashActivity, HomeActivity::class.java)
startActivity(intent)
finish()
}
Kotlin coroutine is of a type kotlinx.coroutines.Job.
That class does not have methods to pause or resume a job.
Alternatively:
You need to write a logic with 2 coroutines.
One that starts HomeActivity after 4 seconds.
Second that listens ACTION_DOWN and ACTION_UP motion events. On ACTION_DOWN you cancel the first coroutine Job, and after ACTION_UP (after N seconds) you show HomeActivity from a second coroutine.
A bit late, but hopefully it will help.
As mentioned by #I.Step, coroutines do not offer functionality for pausing and resuming so, in this case, a simple flag like var isPaused: Boolean could work. You'll just need to check it while the coroutine is running.
Example:
private var isPaused = false
GlobalScope.launch(...) {
while (isActive)
{
if (!isPaused)
{
// do your work here
}
}
}
fun pause()
{
isPaused = true
}
fun resume()
{
isPaused = false
}