Use app level screen brightness instead of changing the system brightness

This also fixes an issue where we don't correctly restore the auto brightness state of the device

Changelog: changed
This commit is contained in:
Kai
2025-06-13 14:51:48 -05:00
parent 13100dc38d
commit 11fd27b774
7 changed files with 41 additions and 99 deletions
-1
View File
@@ -14,7 +14,6 @@
<!--<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>--> <!--<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS" tools:ignore="ProtectedPermissions"/>
<application <application
android:allowBackup="true" android:allowBackup="true"
@@ -1037,19 +1037,16 @@ class Settings : FragmentedStorageFileJson() {
@FormField(R.string.toggle_full_screen, FieldForm.TOGGLE, R.string.toggle_full_screen_descr, 3) @FormField(R.string.toggle_full_screen, FieldForm.TOGGLE, R.string.toggle_full_screen_descr, 3)
var toggleFullscreen: Boolean = true; var toggleFullscreen: Boolean = true;
@FormField(R.string.system_brightness, FieldForm.TOGGLE, R.string.system_brightness_descr, 4) @FormField(R.string.screen_brightness, FieldForm.TOGGLE, R.string.screen_brightness_desc, 4)
var useSystemBrightness: Boolean = false; var controlScreenBrightness: Boolean = true;
@FormField(R.string.system_volume, FieldForm.TOGGLE, R.string.system_volume_descr, 5) @FormField(R.string.system_volume, FieldForm.TOGGLE, R.string.system_volume_descr, 5)
var useSystemVolume: Boolean = true; var useSystemVolume: Boolean = true;
@FormField(R.string.restore_system_brightness, FieldForm.TOGGLE, R.string.restore_system_brightness_descr, 6) @FormField(R.string.zoom_option, FieldForm.TOGGLE, R.string.zoom_option_descr, 6)
var restoreSystemBrightness: Boolean = true;
@FormField(R.string.zoom_option, FieldForm.TOGGLE, R.string.zoom_option_descr, 7)
var zoom: Boolean = true; var zoom: Boolean = true;
@FormField(R.string.pan_option, FieldForm.TOGGLE, R.string.pan_option_descr, 8) @FormField(R.string.pan_option, FieldForm.TOGGLE, R.string.pan_option_descr, 7)
var pan: Boolean = true; var pan: Boolean = true;
} }
@@ -455,10 +455,6 @@ class VideoDetailFragment() : MainFragment() {
activity?.enterPictureInPictureMode(params); activity?.enterPictureInPictureMode(params);
} }
} }
if (isFullscreen) {
viewDetail?.restoreBrightness()
}
} }
fun forcePictureInPicture() { fun forcePictureInPicture() {
@@ -495,10 +491,6 @@ class VideoDetailFragment() : MainFragment() {
_isActive = true; _isActive = true;
_leavingPiP = false; _leavingPiP = false;
if (isFullscreen) {
_viewDetail?.saveBrightness()
}
_viewDetail?.let { _viewDetail?.let {
Logger.v(TAG, "onResume preventPictureInPicture=false"); Logger.v(TAG, "onResume preventPictureInPicture=false");
it.preventPictureInPicture = false; it.preventPictureInPicture = false;
@@ -2575,15 +2575,6 @@ class VideoDetailView : ConstraintLayout {
} }
} }
fun saveBrightness() {
if (Settings.instance.gestureControls.useSystemBrightness) {
_player.gestureControl.saveBrightness()
}
}
fun restoreBrightness() {
_player.gestureControl.restoreBrightness()
}
fun setFullscreen(fullscreen : Boolean) { fun setFullscreen(fullscreen : Boolean) {
Logger.i(TAG, "setFullscreen(fullscreen=$fullscreen)") Logger.i(TAG, "setFullscreen(fullscreen=$fullscreen)")
_player.setFullScreen(fullscreen) _player.setFullScreen(fullscreen)
@@ -3219,6 +3210,8 @@ class VideoDetailView : ConstraintLayout {
fun applyFragment(frag: VideoDetailFragment) { fun applyFragment(frag: VideoDetailFragment) {
fragment = frag; fragment = frag;
_player.fragment = frag
} }
@@ -8,7 +8,6 @@ import android.graphics.Matrix
import android.graphics.drawable.Animatable import android.graphics.drawable.Animatable
import android.media.AudioManager import android.media.AudioManager
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log
import android.view.GestureDetector import android.view.GestureDetector
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MotionEvent import android.view.MotionEvent
@@ -24,7 +23,6 @@ import androidx.core.animation.doOnStart
import androidx.core.view.GestureDetectorCompat import androidx.core.view.GestureDetectorCompat
import com.futo.platformplayer.R import com.futo.platformplayer.R
import com.futo.platformplayer.Settings import com.futo.platformplayer.Settings
import com.futo.platformplayer.UIDialogs
import com.futo.platformplayer.constructs.Event0 import com.futo.platformplayer.constructs.Event0
import com.futo.platformplayer.constructs.Event1 import com.futo.platformplayer.constructs.Event1
import com.futo.platformplayer.constructs.Event2 import com.futo.platformplayer.constructs.Event2
@@ -70,8 +68,6 @@ class GestureControlView : LinearLayout {
private val _progressSound: CircularProgressBar; private val _progressSound: CircularProgressBar;
private var _animatorSound: ObjectAnimator? = null; private var _animatorSound: ObjectAnimator? = null;
private var _brightnessFactor = 1.0f; private var _brightnessFactor = 1.0f;
private var _originalBrightnessFactor = 1.0f;
private var _originalBrightnessMode: Int = 0;
private var _adjustingBrightness: Boolean = false; private var _adjustingBrightness: Boolean = false;
private val _layoutControlsBrightness: FrameLayout; private val _layoutControlsBrightness: FrameLayout;
private val _progressBrightness: CircularProgressBar; private val _progressBrightness: CircularProgressBar;
@@ -110,6 +106,7 @@ class GestureControlView : LinearLayout {
val onSeek = Event1<Long>(); val onSeek = Event1<Long>();
val onBrightnessAdjusted = Event1<Float>(); val onBrightnessAdjusted = Event1<Float>();
val onBrightnessCleared = Event0();
val onPan = Event2<Float, Float>(); val onPan = Event2<Float, Float>();
val onZoom = Event1<Float>(); val onZoom = Event1<Float>();
val onSoundAdjusted = Event1<Float>(); val onSoundAdjusted = Event1<Float>();
@@ -781,60 +778,21 @@ class GestureControlView : LinearLayout {
_animatorBrightness?.start(); _animatorBrightness?.start();
} }
fun saveBrightness() {
try {
_originalBrightnessMode = android.provider.Settings.System.getInt(context.contentResolver, android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE)
val brightness = android.provider.Settings.System.getInt(context.contentResolver, android.provider.Settings.System.SCREEN_BRIGHTNESS)
_brightnessFactor = brightness / 255.0f;
Log.i(TAG, "Starting brightness brightness: $brightness, _brightnessFactor: $_brightnessFactor, _originalBrightnessMode: $_originalBrightnessMode")
_originalBrightnessFactor = _brightnessFactor
} catch (e: Throwable) {
Settings.instance.gestureControls.useSystemBrightness = false
Settings.instance.save()
UIDialogs.toast(context, "useSystemBrightness disabled due to an error")
}
}
fun restoreBrightness() {
if (Settings.instance.gestureControls.restoreSystemBrightness) {
onBrightnessAdjusted.emit(_originalBrightnessFactor)
if (android.provider.Settings.System.canWrite(context)) {
Log.i(TAG, "Restoring system brightness mode _originalBrightnessMode: $_originalBrightnessMode")
android.provider.Settings.System.putInt(
context.contentResolver,
android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE,
_originalBrightnessMode
)
}
}
}
fun setFullscreen(isFullScreen: Boolean) { fun setFullscreen(isFullScreen: Boolean) {
resetZoomPan() resetZoomPan()
if (isFullScreen) { onBrightnessCleared.emit()
if (Settings.instance.gestureControls.useSystemBrightness) { _brightnessFactor = 1.0f
saveBrightness()
}
if (isFullScreen) {
if (Settings.instance.gestureControls.useSystemVolume) { if (Settings.instance.gestureControls.useSystemVolume) {
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
val currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) val currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
_soundFactor = currentVolume.toFloat() / maxVolume.toFloat() _soundFactor = currentVolume.toFloat() / maxVolume.toFloat()
} }
onBrightnessAdjusted.emit(_brightnessFactor);
onSoundAdjusted.emit(_soundFactor); onSoundAdjusted.emit(_soundFactor);
} else { } else {
if (Settings.instance.gestureControls.useSystemBrightness) {
restoreBrightness()
} else {
onBrightnessAdjusted.emit(1.0f);
}
//onSoundAdjusted.emit(1.0f); //onSoundAdjusted.emit(1.0f);
stopAdjustingBrightness(); stopAdjustingBrightness();
stopAdjustingSound(); stopAdjustingSound();
@@ -13,6 +13,7 @@ import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.WindowManager
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.TextView import android.widget.TextView
@@ -40,6 +41,7 @@ import com.futo.platformplayer.constructs.Event1
import com.futo.platformplayer.constructs.Event2 import com.futo.platformplayer.constructs.Event2
import com.futo.platformplayer.constructs.Event3 import com.futo.platformplayer.constructs.Event3
import com.futo.platformplayer.formatDuration import com.futo.platformplayer.formatDuration
import com.futo.platformplayer.fragment.mainactivity.main.VideoDetailFragment
import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.states.StateApp import com.futo.platformplayer.states.StateApp
import com.futo.platformplayer.states.StatePlayer import com.futo.platformplayer.states.StatePlayer
@@ -62,6 +64,8 @@ class FutoVideoPlayer : FutoVideoPlayerBase {
var isFullScreen: Boolean = false var isFullScreen: Boolean = false
private set; private set;
var fragment: VideoDetailFragment? = null
//Views //Views
private val _root: ConstraintLayout; private val _root: ConstraintLayout;
private val _videoView: PlayerView; private val _videoView: PlayerView;
@@ -283,17 +287,25 @@ class FutoVideoPlayer : FutoVideoPlayerBase {
}; };
gestureControl.onToggleFullscreen.subscribe { setFullScreen(!isFullScreen) }; gestureControl.onToggleFullscreen.subscribe { setFullScreen(!isFullScreen) };
gestureControl.onBrightnessAdjusted.subscribe { gestureControl.onBrightnessAdjusted.subscribe {
if (Settings.instance.gestureControls.useSystemBrightness) { if (Settings.instance.gestureControls.controlScreenBrightness) {
setSystemBrightness(it) setScreenBrightness(it)
} else { } else {
setBrightnessOverlay(it)
if (it == 1.0f) { if (it == 1.0f) {
_overlay_brightness.visibility = View.GONE; _overlay_brightness.visibility = View.GONE;
} else { } else {
_overlay_brightness.visibility = View.VISIBLE; _overlay_brightness.visibility = View.VISIBLE;
_overlay_brightness.setBackgroundColor(Color.valueOf(0.0f, 0.0f, 0.0f, (1.0f - it)).toArgb());
} }
} }
}; }
gestureControl.onBrightnessCleared.subscribe {
if (Settings.instance.gestureControls.controlScreenBrightness) {
clearCustomScreenBrightness()
} else {
setBrightnessOverlay(1.0f)
_overlay_brightness.visibility = View.GONE
}
}
gestureControl.onPan.subscribe { x, y -> gestureControl.onPan.subscribe { x, y ->
_videoView.translationX = x _videoView.translationX = x
_videoView.translationY = y _videoView.translationY = y
@@ -476,33 +488,26 @@ class FutoVideoPlayer : FutoVideoPlayerBase {
} }
} }
private fun setBrightnessOverlay(brightness: Float) {
_overlay_brightness.setBackgroundColor(
Color.valueOf(0.0f, 0.0f, 0.0f, (1.0f - brightness)).toArgb()
)
}
private fun updateAutoplayButton() { private fun updateAutoplayButton() {
_control_autoplay.setColorFilter(ContextCompat.getColor(context, if (StatePlayer.instance.autoplay) com.futo.futopay.R.color.primary else R.color.white)) _control_autoplay.setColorFilter(ContextCompat.getColor(context, if (StatePlayer.instance.autoplay) com.futo.futopay.R.color.primary else R.color.white))
_control_autoplay_fullscreen.setColorFilter(ContextCompat.getColor(context, if (StatePlayer.instance.autoplay) com.futo.futopay.R.color.primary else R.color.white)) _control_autoplay_fullscreen.setColorFilter(ContextCompat.getColor(context, if (StatePlayer.instance.autoplay) com.futo.futopay.R.color.primary else R.color.white))
} }
private fun setSystemBrightness(brightness: Float) { private fun clearCustomScreenBrightness() {
Log.i(TAG, "setSystemBrightness $brightness") setScreenBrightness(null)
if (android.provider.Settings.System.canWrite(context)) {
Log.i(TAG, "setSystemBrightness canWrite $brightness")
android.provider.Settings.System.putInt(context.contentResolver, android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE, android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
android.provider.Settings.System.putInt(context.contentResolver, android.provider.Settings.System.SCREEN_BRIGHTNESS, (brightness * 255.0f).toInt().coerceAtLeast(1).coerceAtMost(255));
} else if (!_promptedForPermissions) {
Log.i(TAG, "setSystemBrightness prompt $brightness")
_promptedForPermissions = true
UIDialogs.showConfirmationDialog(context, "System brightness controls require explicit permission", action = {
openAndroidPermissionsMenu()
})
} else {
Log.i(TAG, "setSystemBrightness no permission?")
//No permissions but already prompted, ignore
}
} }
private fun openAndroidPermissionsMenu() { private fun setScreenBrightness(brightness: Float?) {
val intent = Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS) val layoutParams: WindowManager.LayoutParams? = fragment?.activity?.window?.attributes
intent.setData(Uri.parse("package:" + context.packageName)) layoutParams?.screenBrightness =
context.startActivity(intent) brightness ?: WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
fragment?.activity?.window?.attributes = layoutParams
} }
fun updateNextPrevious() { fun updateNextPrevious() {
+2 -4
View File
@@ -397,10 +397,8 @@
<string name="brightness_slider_descr">Enable slide gesture to change brightness</string> <string name="brightness_slider_descr">Enable slide gesture to change brightness</string>
<string name="toggle_full_screen">Toggle full screen</string> <string name="toggle_full_screen">Toggle full screen</string>
<string name="toggle_full_screen_descr">Enable swipe gesture to toggle full screen</string> <string name="toggle_full_screen_descr">Enable swipe gesture to toggle full screen</string>
<string name="system_brightness">System brightness</string> <string name="screen_brightness">Control screen brightness</string>
<string name="system_brightness_descr">Gesture controls adjust system brightness</string> <string name="screen_brightness_desc">Gesture controls adjust the device screen brightness instead of an overlay filter</string>
<string name="restore_system_brightness">Restore system brightness</string>
<string name="restore_system_brightness_descr">Restore system brightness when exiting full screen</string>
<string name="zoom_option">Enable zoom</string> <string name="zoom_option">Enable zoom</string>
<string name="zoom_option_descr">Enable two finger pinch zoom gesture</string> <string name="zoom_option_descr">Enable two finger pinch zoom gesture</string>
<string name="pan_option">Enable pan</string> <string name="pan_option">Enable pan</string>