iOS|解决 setBrightness 调节屏幕亮度不生效的问题

在包含视频播放功能的 App 中,一种常见的交互是在播放器界面的左侧上下滑动调节屏幕亮度,右侧上下滑动调节音量。我们的 iOS App 里也是这样设计的,但最近在测试过程中,发现亮度调节不生效了。

摸索之路

代码里面调节亮度的实现是这样的:

- (void)setBrightnessUp {
    if([UIScreen mainScreen].brightness >=1){
        return;
    }
    [UIScreen mainScreen].brightness +=0.01;
    // ...
}

-(void)setBrightnessDown {
    if([UIScreen mainScreen].brightness <=0){
        return;
    }
    [UIScreen mainScreen].brightness -=0.01;
    // ...
}

这个实现在较早之前是没有问题的,那我首先想到比较可能是因为系统的更新,对这个 API 做了变更。于是先查阅了 UIKit/UIScreen/brightness 的官方文档,里面只提到了 brightness 属性只在 main screen 上被支持,取值范围是 [0.0, 1.0],以及亮度调节后,直到锁屏后才会失效——即使用户在锁屏之前已经关闭了 App。并没有看到什么值得特别留意的。

然后继续看代码里的 UIScreen.mainScreen,这个属性被标记为:

API_DEPRECATED("Use a UIScreen instance found through context instead: i.e, view.window.windowScene.screen", ios(2.0, API_TO_BE_DEPRECATED), visionos(1.0, API_TO_BE_DEPRECATED))

但当前在我使用的 SDK 18.2 版本中,这个属性应仍可正常使用。

在 Google 和 StackOverflow 找了一圈,大家讨论亮度调节不生效主要集中以下方面:

  • 后台调用不生效;

  • 模拟器上调节不生效;

  • viewDidLoad and viewWillAppear 中调用不生效;

  • 如何优雅地在 App 退出后恢复原有亮度;

也没有找到什么能匹配我的场景的解决方案。

加了一些日志,在调节亮度前后分别打印了 brightness 的值,发现它在调用 setBrightness 方法后并没有发生变化,也没有报错和告警,看起来就像是这个方法根本没有被调用一样。

也做了一些其它尝试,比如把调整亮度的代码显式调度到主线程、使用 view.window.windowScene.screen 替代 UIScreen.mainScreen 等,但都没有效果。

无奈之下,我问了 GitHub Copilot 一嘴,它的回答是这样的:

图片

我按它的建议检查了权限,确认了不存在权限问题。

有点绝望之际,看到它提供的代码里调整亮度的粒度是 0.1,而我的代码里是 0.01,于是我尝试将粒度改为 0.1,然后奇迹发生了,亮度调节生效了

这就有点匪夷所思了……于是我又尝试了其它的粒度值,结果如下:

  • 0.01,不生效;

  • 0.02,不生效;

  • 0.03 及以上,生效,但是从输出可以看到,实际调整后的亮度值都是 0.05 的倍数,即 0.05、0.1、0.15、0.2……,而不是 0.03、0.06、0.09、0.12……

我找到安装了以前老版本 App 的一个老平板(iOS 10.3.3),在上面测试了一下,发现在这个版本上,0.01 的调节粒度是可以生效的。

也就是说,在 iOS (10.3.3, 18.2) 之间靠近后者的某个版本上,[UIScreen mainScreen].brightness 的调节粒度发生了变化,由 0.01 变为了 0.05。

至此破案了,顺便吐槽一下,官方文档里对此毫无提及,实在是……略坑。

参考

  • https://developer.apple.com/documentation/uikit/uiscreen/brightness?language=objc

  • https://stackoverflow.com/questions/54229300/not-able-to-set-brightness-when-app-enter-in-background-can-any-one-have-any-id

  • https://stackoverflow.com/questions/12362885/ios-uiscreen-setbrightness-doesnt-work

  • https://stackoverflow.com/questions/61765014/why-cannot-i-set-uiscreen-main-brightness


如果读完文章有收获,可以关注我的微信公众号「闷骚的程序员」并🌟设为星标🌟,随时阅读更多内容。

<think>嗯,用户问的是如何在Unity中获取控制手机亮度的权限。首先,我得回忆一下Android和iOS系统的权限机制。因为Unity本身没有直接控制屏幕亮度的API,所以需要通过调用原生代码来实现。 首先,对于Android系统,用户可能需要修改屏幕亮度,这需要用到WRITE_SETTINGS权限。记得在AndroidManifest.xml中添加这个权限。然后,可能需要用AndroidJavaClass和AndroidJavaObject来调用系统的Settings.System接口,调整亮度值。不过,不同Android版本可能有不同的限制,比如Android 6.0以上可能需要检查权限,或者引导用户手动开启权限,因为WRITE_SETTINGS属于特殊权限,无法通过常规请求弹窗获取。 然后是iOS部分,苹果的权限管理比较严格,控制亮度可能需要私有API,但这样可能会导致应用被拒。所以可能需要用Unity的Screen.brightness属性,但不确定是否需要额外权限。可能需要在Xcode工程中配置某些设置,或者使用iOS的原生代码通过Unity的接口调用。不过用户可能需要注意App Store的审核政策,避免使用私有API。 接下来,用户可能需要示例代码,所以应该提供一个简单的脚本,演示如何在Unity中调用Android的接口修改亮度。同时提醒用户需要在Player Settings里设置正确的配置,比如禁用自动亮度调节,处理不同设备的亮度范围(比如Android的亮度值通常是0-255)。 另外,要注意不同设备的兼容性问题,有些手机厂商可能修改了亮度设置的方式,导致代码不生效。需要测试不同的设备,或者寻找更稳定的方法。可能还需要处理异常,比如没有权限时的回退方案,或者提示用户手动调整设置。 最后,应该总结步骤,分Android和iOS两部分,强调权限配置和原生代码调用,以及注意事项和潜在问题。用户可能需要具体的代码示例和操作步骤,所以尽量详细地列出修改AndroidManifest.xml的方法,以及C#脚本的编写要点。</think>在 Unity 中控制手机屏幕亮度需要调用原生系统 API,并确保已获取相关权限。以下是针对 **Android** 和 **iOS** 的主要步骤: --- ### **Android 平台** #### 1. **添加权限** - 在 `Assets/Plugins/Android/AndroidManifest.xml` 中添加以下权限: ```xml <uses-permission android:name="android.permission.WRITE_SETTINGS" /> ``` #### 2. **通过 Unity 调用 Android API** - **编写 C# 脚本**: ```csharp using UnityEngine; public class BrightnessController : MonoBehaviour { // 设置亮度(0~1 范围) public static void SetBrightness(float brightness) { if (Application.platform == RuntimePlatform.Android) { using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) using (AndroidJavaObject contentResolver = currentActivity.Call<AndroidJavaObject>("getContentResolver")) using (AndroidJavaClass settingsSystem = new AndroidJavaClass("android.provider.Settings$System")) { int brightnessValue = (int)(brightness * 255); // Android 亮度范围为 0~255 bool success = settingsSystem.CallStatic<bool>("putInt", contentResolver, settingsSystem.GetStatic<string>("SCREEN_BRIGHTNESS"), brightnessValue); if (success) { // 部分设备需要重启 Activity 或发送广播生效 AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent"); string action = "android.intent.action.SCREEN_BRIGHTNESS_CHANGED"; AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", action); currentActivity.Call("sendBroadcast", intent); } } } else { Screen.brightness = brightness; // 仅适用于 Unity Editor 测试 } } } ``` #### 3. **权限检查与请求** - `WRITE_SETTINGS` 是敏感权限,需用户手动授予: ```csharp public void RequestBrightnessPermission() { if (Application.platform != RuntimePlatform.Android) return; using (AndroidJavaClass settingsClass = new AndroidJavaClass("android.provider.Settings")) using (AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity")) { // 跳转到系统设置界面让用户手动授权 AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", settingsClass.GetStatic<string>("ACTION_MANAGE_WRITE_SETTINGS")); intent.Call<AndroidJavaObject>("setData", new AndroidJavaObject("android.net.Uri").CallStatic<AndroidJavaObject>("parse", "package:" + activity.Call<string>("getPackageName"))); activity.Call("startActivity", intent); } } ``` --- ### **iOS 平台** - **直接使用 Unity API**: ```csharp Screen.brightness = 0.5f; // 0~1 范围,无需额外权限 ``` - iOS 系统自动管理亮度权限,但实际效果可能受系统限制(如低电量模式)。 --- ### **注意事项** 1. **Android 设备兼容性**: - 部分厂商可能限制修改亮度(如华为/小米),需测试目标设备。 - 需关闭系统自动亮度调节:`Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 0`。 2. **Unity Editor 测试**: - 使用 `Screen.brightness` 在编辑器内模拟效果,但实际设备需原生代码支持。 3. **iOS 审核风险**: - 避免使用私有 API,直接依赖 Unity 的 `Screen.brightness` 更安全。 --- ### **完整流程示例** 1. 在 Unity 中创建 `BrightnessController` 脚本。 2. 修改 `AndroidManifest.xml` 添加权限。 3. 调用 `SetBrightness()` 方法并处理权限请求逻辑。 建议进一步封装权限检查和系统兼容性处理,确保用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值