feat(player): add mobile edge adjustments
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
<!-- Internet access permissions -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
|
||||
|
||||
|
||||
<!-- PIP and media session foreground service permissions -->
|
||||
|
||||
@@ -10,6 +10,7 @@ import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.SurfaceTexture
|
||||
import android.media.AudioManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
@@ -24,6 +25,7 @@ import android.view.KeyEvent
|
||||
import android.view.TextureView
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowInsets
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.content.FileProvider
|
||||
@@ -40,6 +42,7 @@ import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.embedding.engine.FlutterShellArgs
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import java.io.File
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class MainActivity : FlutterActivity() {
|
||||
|
||||
@@ -78,12 +81,14 @@ class MainActivity : FlutterActivity() {
|
||||
private val EXTERNAL_PLAYER_CHANNEL = "com.plezy/external_player"
|
||||
private val THEME_CHANNEL = "com.plezy/theme"
|
||||
private val DEVICE_CHANNEL = "com.plezy/device"
|
||||
private val DEVICE_ADJUSTMENT_CHANNEL = "com.plezy/device_adjustment"
|
||||
private val TEXT_INPUT_CHANNEL = "com.plezy/text_input"
|
||||
private val APP_EXIT_CHANNEL = "com.plezy/app_exit"
|
||||
private val APP_FOREGROUND_CHANNEL = "com.plezy/app_foreground"
|
||||
private var watchNextPlugin: WatchNextPlugin? = null
|
||||
private var nativeTextInputFocused = false
|
||||
private var pendingExternalPlayerResult: MethodChannel.Result? = null
|
||||
private var originalWindowBrightness: Float? = null
|
||||
|
||||
private inline fun logTextInputDiag(message: () -> String) {
|
||||
if (TEXT_INPUT_DIAGNOSTICS_ENABLED) {
|
||||
@@ -460,6 +465,10 @@ class MainActivity : FlutterActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, DEVICE_ADJUSTMENT_CHANNEL).setMethodCallHandler { call, result ->
|
||||
handleDeviceAdjustmentCall(call.method, call.arguments, result)
|
||||
}
|
||||
|
||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, TEXT_INPUT_CHANNEL).setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"setNativeTextInputFocused" -> {
|
||||
@@ -702,6 +711,94 @@ class MainActivity : FlutterActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleDeviceAdjustmentCall(method: String, arguments: Any?, result: MethodChannel.Result) {
|
||||
try {
|
||||
when (method) {
|
||||
"getBrightness" -> result.success(getScreenBrightnessFraction())
|
||||
"setBrightness" -> {
|
||||
setScreenBrightnessFraction(argumentAsDouble(arguments))
|
||||
result.success(null)
|
||||
}
|
||||
"restoreBrightness" -> {
|
||||
restoreScreenBrightness()
|
||||
result.success(null)
|
||||
}
|
||||
"getMediaVolume" -> result.success(getMediaVolumeFraction())
|
||||
"setMediaVolume" -> {
|
||||
setMediaVolumeFraction(argumentAsDouble(arguments))
|
||||
result.success(null)
|
||||
}
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
result.error("INVALID_ARGUMENT", e.message ?: e.javaClass.simpleName, null)
|
||||
} catch (e: Exception) {
|
||||
result.error("DEVICE_ADJUSTMENT_FAILED", e.message ?: e.javaClass.simpleName, null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun argumentAsDouble(arguments: Any?): Double {
|
||||
val value = (arguments as? Number)?.toDouble()
|
||||
?: throw IllegalArgumentException("Expected a numeric value")
|
||||
if (value.isNaN() || value.isInfinite()) {
|
||||
throw IllegalArgumentException("Expected a finite numeric value")
|
||||
}
|
||||
return value.coerceIn(0.0, 1.0)
|
||||
}
|
||||
|
||||
private fun getScreenBrightnessFraction(): Double {
|
||||
val windowBrightness = window.attributes.screenBrightness
|
||||
if (windowBrightness >= 0f) return windowBrightness.coerceIn(0f, 1f).toDouble()
|
||||
|
||||
return try {
|
||||
Settings.System.getInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS).coerceIn(0, 255) / 255.0
|
||||
} catch (e: Settings.SettingNotFoundException) {
|
||||
0.5
|
||||
}
|
||||
}
|
||||
|
||||
private fun setScreenBrightnessFraction(value: Double) {
|
||||
if (originalWindowBrightness == null) originalWindowBrightness = window.attributes.screenBrightness
|
||||
val attributes = window.attributes
|
||||
attributes.screenBrightness = value.coerceIn(0.0, 1.0).toFloat()
|
||||
window.attributes = attributes
|
||||
}
|
||||
|
||||
private fun restoreScreenBrightness() {
|
||||
val attributes = window.attributes
|
||||
attributes.screenBrightness = originalWindowBrightness ?: WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
|
||||
window.attributes = attributes
|
||||
originalWindowBrightness = null
|
||||
}
|
||||
|
||||
private fun getMediaVolumeFraction(): Double {
|
||||
val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
|
||||
val minVolume = streamMinVolume(audioManager)
|
||||
if (maxVolume <= minVolume) return 0.0
|
||||
|
||||
val volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC).coerceIn(minVolume, maxVolume)
|
||||
return (volume - minVolume).toDouble() / (maxVolume - minVolume).toDouble()
|
||||
}
|
||||
|
||||
private fun setMediaVolumeFraction(value: Double) {
|
||||
val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
|
||||
val minVolume = streamMinVolume(audioManager)
|
||||
val target = (minVolume + value.coerceIn(0.0, 1.0) * (maxVolume - minVolume))
|
||||
.roundToInt()
|
||||
.coerceIn(minVolume, maxVolume)
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, target, 0)
|
||||
}
|
||||
|
||||
private fun streamMinVolume(audioManager: AudioManager): Int {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) {
|
||||
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
|
||||
flutterEngine?.let { engine ->
|
||||
|
||||
Reference in New Issue
Block a user