mobile: keep screen on while playing/recording media (#3317)

* android: keep screen on while playing/recording media

* ios: keep screen on while playing/recording media

* different implementation on ios

* Revert "android: keep screen on while playing/recording media"

This reverts commit d291f006e9.

* different implementation on android

* refactor

---------

Co-authored-by: Avently <avently@local>
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
This commit is contained in:
Stanislav Dmitrenko
2023-11-08 00:56:38 +08:00
committed by GitHub
parent 3e46c5dfaf
commit 2dc621a56c
8 changed files with 43 additions and 3 deletions

View File

@@ -48,6 +48,7 @@ actual class RecorderNative: RecorderInterface {
recStartedAt = System.currentTimeMillis()
progressJob = CoroutineScope(Dispatchers.Default).launch {
while(isActive) {
keepScreenOn(true)
onProgressUpdate(progress(), false)
delay(50)
}
@@ -84,6 +85,7 @@ actual class RecorderNative: RecorderInterface {
progressJob = null
filePath = null
recorder = null
keepScreenOn(false)
return (realDuration(path) ?: 0).also { recStartedAt = null }
}
@@ -170,6 +172,7 @@ actual object AudioPlayer: AudioPlayerInterface {
progressJob = CoroutineScope(Dispatchers.Default).launch {
onProgressUpdate(player.currentPosition, TrackState.PLAYING)
while(isActive && player.isPlaying) {
keepScreenOn(true)
// Even when current position is equal to duration, the player has isPlaying == true for some time,
// so help to make the playback stopped in UI immediately
if (player.currentPosition == player.duration) {
@@ -187,6 +190,7 @@ actual object AudioPlayer: AudioPlayerInterface {
if (isActive) {
onProgressUpdate(player.duration, TrackState.PAUSED)
}
keepScreenOn(false)
onProgressUpdate(null, TrackState.PAUSED)
}
return player.duration
@@ -196,6 +200,7 @@ actual object AudioPlayer: AudioPlayerInterface {
progressJob?.cancel()
progressJob = null
player.pause()
keepScreenOn(false)
return player.currentPosition
}
@@ -203,6 +208,7 @@ actual object AudioPlayer: AudioPlayerInterface {
if (currentlyPlaying.value == null) return
player.stop()
stopListener()
keepScreenOn(false)
}
override fun stop(item: ChatItem) = stop(item.file?.fileName)
@@ -263,6 +269,7 @@ actual object AudioPlayer: AudioPlayerInterface {
override fun pause(audioPlaying: MutableState<Boolean>, pro: MutableState<Int>) {
pro.value = pause()
audioPlaying.value = false
keepScreenOn(false)
}
override fun seekTo(ms: Int, pro: MutableState<Int>, filePath: String?) {

View File

@@ -1,13 +1,10 @@
package chat.simplex.common.platform
import android.media.MediaMetadataRetriever
import android.media.session.PlaybackState
import android.net.Uri
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import chat.simplex.common.helpers.toUri
import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR
import com.google.android.exoplayer2.*
@@ -134,6 +131,7 @@ actual class VideoPlayer actual constructor(
player.addListener(object: Player.Listener{
override fun onIsPlayingChanged(isPlaying: Boolean) {
super.onIsPlayingChanged(isPlaying)
keepScreenOn(isPlaying)
// Produce non-ideal transition from stopped to playing state while showing preview image in ChatView
// videoPlaying.value = isPlaying
}
@@ -192,6 +190,7 @@ actual class VideoPlayer actual constructor(
override fun release(remove: Boolean) {
player.release()
keepScreenOn(false)
if (remove) {
VideoPlayerHolder.players.remove(uri to gallery)
}

View File

@@ -196,12 +196,14 @@ actual fun ActiveCallView() {
chatModel.activeCallViewIsVisible.value = true
// After the first call, End command gets added to the list which prevents making another calls
chatModel.callCommand.removeAll { it is WCallCommand.End }
keepScreenOn(true)
onDispose {
activity.volumeControlStream = prevVolumeControlStream
// Unlock orientation
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
chatModel.activeCallViewIsVisible.value = false
chatModel.callCommand.clear()
keepScreenOn(false)
}
}
}

View File

@@ -11,6 +11,7 @@ import android.text.Spanned
import android.text.SpannedString
import android.text.style.*
import android.util.Base64
import android.view.WindowManager
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.*
@@ -43,6 +44,17 @@ fun Resources.getText(id: StringResource, vararg args: Any): CharSequence {
return HtmlCompat.fromHtml(formattedHtml, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
fun keepScreenOn(on: Boolean) {
val window = mainActivity.get()?.window ?: return
Handler(Looper.getMainLooper()).post {
if (on) {
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
}
}
actual fun escapedHtmlToAnnotatedString(text: String, density: Density): AnnotatedString {
return spannableStringToAnnotatedString(HtmlCompat.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY), density)
}