본문 바로가기

Unity3D/C#

유니티 안드로이드 화면 최대 밝기, 화면 꺼짐 방지 (screenBrightness / Screen.sleepTimeout)

반응형

Screen Brightness

 

전광판 앱이나 QR 코드를 보여주는 화면, 운동 타이머처럼 화면을 오래 켜 두고 보는 앱에서는 두 가지가 꼭 필요합니다. 화면이 저절로 꺼지지 않아야 하고, 밖에서도 잘 보이도록 밝기를 최대로 올려야 합니다. 그런데 밝기를 바꾸려고 안드로이드 시스템 설정을 건드리면 「시스템 설정 변경」 권한을 따로 받아야 하고, 앱을 나간 뒤에도 밝기가 그대로 남아 버립니다. 안드로이드에는 앱 창 하나에만 적용되는 밝기 값(screenBrightness)이 있어서, 이 값을 쓰면 권한 없이 내 앱 화면만 밝게 만들 수 있고 앱을 나가면 원래 밝기로 돌아갑니다. Unity 에서는 AndroidJavaClass 로 이 값을 바꾸고, 화면 꺼짐은 Screen.sleepTimeout 으로 막을 수 있습니다. 이번 예시는 스크립트를 켜면 화면 꺼짐을 막고 최대 밝기로 올렸다가, 끄면 둘 다 시스템 설정을 따르게(밝기 -1 · SleepTimeout.SystemSetting) 돌려놓습니다. 앱이 그 전에 따로 정해 둔 값을 저장했다가 되살리지는 않습니다.

 

C# (UNITY 3D)

 

밝기를 바꾸는 부분은 어디서든 부를 수 있도록 static 클래스로 따로 만듭니다. 0~1 사이 값을 넣으면 그 밝기가 되고, -1 을 넣으면 시스템 밝기를 다시 따릅니다.

 

using UnityEngine;

//CodeFinder 코드파인더
//From https://codefinder.janndk.com/
public static class ScreenBrightness
{
    // 시스템 밝기를 따른다는 값 (이름을 System 으로 지으면 안 됩니다 - 아래 주의 참고)
    public const float FollowSystem = -1f;

    public static void Set_Brightness(float value)
    {
        // 0 에 가까우면 화면이 꺼진 것처럼 보이는 기기가 있어 바닥을 둡니다
        float brightness = value < 0f ? FollowSystem : Mathf.Clamp(value, 0.05f, 1f);
#if UNITY_ANDROID && !UNITY_EDITOR
        try
        {
            var player = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            var activity = player.GetStatic<AndroidJavaObject>("currentActivity");
            // 창 속성은 안드로이드 UI 스레드에서만 바꿀 수 있습니다
            activity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
            {
                using (var window = activity.Call<AndroidJavaObject>("getWindow"))
                using (var attributes = window.Call<AndroidJavaObject>("getAttributes"))
                {
                    attributes.Set("screenBrightness", brightness);
                    window.Call("setAttributes", attributes);
                }
            }));
        }
        catch (System.Exception e)
        {
            // 밝기를 못 바꿨다고 앱이 멈추면 안 됩니다
            Debug.LogWarning("밝기를 바꾸지 못했습니다: " + e.Message);
        }
#endif
    }
}

 

ScreenBrightness.cs 는 오브젝트에 붙이지 않아도 됩니다. 프로젝트 안에 파일만 있으면 됩니다.

 

다음은 실제로 화면을 지켜 주는 스크립트입니다. 화면을 켜 두어야 하는 화면(예: 재생 화면)의 오브젝트에 붙이면, 그 오브젝트가 켜질 때 최대 밝기 · 꺼짐 방지가 되고 꺼질 때 원래대로 돌아갑니다.

 

using UnityEngine;

//CodeFinder 코드파인더
//From https://codefinder.janndk.com/
public class ScreenKeeper : MonoBehaviour
{
    void OnEnable()
    {
        Start_Keep();
    }

    void OnDisable()
    {
        Stop_Keep();
    }

    public void Start_Keep()
    {
        Screen.sleepTimeout = SleepTimeout.NeverSleep;   // 화면 꺼짐 방지
        ScreenBrightness.Set_Brightness(1f);             // 최대 밝기
    }

    public void Stop_Keep()
    {
        ScreenBrightness.Set_Brightness(ScreenBrightness.FollowSystem);  // 원래 밝기로
        Screen.sleepTimeout = SleepTimeout.SystemSetting;                // 기기 설정대로
    }
}

 

함수(function)
Set_Brightness(float) : 앱 창의 밝기를 바꿉니다. 0.05~1 사이로 맞추고, 음수면 시스템 밝기를 따릅니다.
Start_Keep : 화면 꺼짐을 막고 최대 밝기로 올립니다.
Stop_Keep : 밝기와 화면 꺼짐을 시스템 설정을 따르게 돌려놓습니다.

 

변수(variable)
FollowSystem(float) : 시스템 밝기를 따르라는 값(-1). 안드로이드의 BRIGHTNESS_OVERRIDE_NONE 과 같은 값입니다.
brightness(float) : 실제로 창에 넣을 밝기 값입니다.

 

주의
1. 상수 이름을 System 으로 지으면 catch (System.Exception e) 의 System 이 그 상수로 읽혀서 컴파일 오류가 납니다. 이 부분은 #if UNITY_ANDROID 안에 있기 때문에 에디터에서는 아무 문제가 없다가 안드로이드로 빌드할 때만 오류가 납니다. 그래서 FollowSystem 처럼 겹치지 않는 이름을 씁니다.
2. 창 속성은 안드로이드 UI 스레드에서 바꾸는 것이라 runOnUiThread 로 보내 처리합니다. Unity 스크립트는 다른 스레드에서 돌기 때문에 이렇게 넘기는 게 안전합니다.
3. 에디터에서는 밝기가 바뀌지 않습니다. 실제 기기에 빌드해서 확인해야 합니다.
4. Screen.sleepTimeout 을 NeverSleep 으로 둔 채로 두면 배터리를 계속 씁니다. 필요한 화면을 벗어나면 꼭 SystemSetting 으로 돌려 놓습니다.
5. screenBrightness 는 이 앱 창에만 걸리는 값이라, 앱을 나가면 밝기가 시스템 값으로 돌아갑니다.

 

Unity 6000.3 (Unity 6.3) · 안드로이드 기준입니다. 시스템 밝기 설정은 건드리지 않기 때문에 AndroidManifest 에 권한을 추가할 필요가 없습니다.

 

이 코드는 제가 만든 전광판 앱 BeamSay 에서 쓰는 처리를 글에 맞게 두 클래스로 옮긴 것입니다. 옮긴 코드는 Unity 6000.3.14f1 Android 대상 컴파일에서 오류가 없었고, 기기에서는 앱 원본 코드로 확인했습니다.

 

 

반응형

Google Play 및 Google Play 로고는 Google LLC의 상표입니다.