LoginSignup
4
5

More than 5 years have passed since last update.

[ちょっとニッチ] Unity3dでiOS/Android端末の画面輝度を取得/変更(PlayMaker用Action)

Last updated at Posted at 2015-10-29

iOSネイティブプラグイン準備

Plugins/iOS以下に配置

BrightnessPlugin.m
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

#ifdef __cplusplus
extern "C" {
#endif

void setBrightness(float val) { [UIScreen mainScreen].brightness = val; }

float getBrightness() { return [UIScreen mainScreen].brightness; }

#ifdef __cplusplus
}
#endif

Android側準備

ネイティブプラグインビルドしてjarをPlugins/Android以下に配置したけどUnityビルドできなかった。
dexを変換できないだの何だの言うからgradleビルドスクリプト弄くり回したしjavaバージョンも確認したがトライアンドエラーに暮れた俺の半日は報われなかった。
だからC#側から遠まわしにjavaを実行することにした。

Plugins/Android/AndroidManifest.xmlにパーミッションを追加。

<uses-permission android:name="android.permission.WRITE_SETTINGS" />

PlayMakerのアクション

SetBrightness.cs

using System;
using UnityEngine;

#if !UNITY_EDITOR && UNITY_IOS
using System.Runtime.InteropServices;
#endif
namespace HutongGames.PlayMaker.Actions {
    [ActionCategory(ActionCategory.Device)]
    [Tooltip("Sets screen brightness.")]
    public class SetBrightness : FsmStateAction {
        #if !UNITY_EDITOR && UNITY_IOS
        [DllImport("__Internal")]
        private static extern void setBrightness(float brightness);
        #endif
        [ActionSection("Set up")]
        public bool everyFrame;
        [RequiredField]
        public FsmFloat brightness;

        public override void Reset() {
            everyFrame = false;
            brightness = null;
        }

        public override void OnEnter() {
            DoAction();
            if (!everyFrame)
                Finish();
        }

        public override void OnUpdate() {
            DoAction();
        }

        private void DoAction() {
            #if UNITY_EDITOR
            #elif UNITY_IOS
            setBrightness(brightness.Value);
            #elif UNITY_ANDROID
            var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
            activity.Call("runOnUiThread", new AndroidJavaRunnable(() => {
                var window = activity.Call<AndroidJavaObject>("getWindow");
                var lp = window.Call<AndroidJavaObject>("getAttributes");
                lp.Set("screenBrightness", brightness.Value);
                window.Call("setAttributes", lp);

                int b = 1 + (int)(Math.Min(1, Math.Max(0, brightness.Value)) * 254f); // 1 <= b <= 255
                var system = new AndroidJavaClass("android.provider.Settings.System");
                var contentResolver = activity.Call<AndroidJavaObject>("getContentResolver");
                system.CallStatic("putInt", contentResolver, system.CallStatic<string>("SCREEN_BRIGHTNESS_MODE"), 0);
                system.CallStatic("putInt", contentResolver, system.CallStatic<string>("SCREEN_BRIGHTNESS"), b);
            }));
            #endif
        }
    }
}
GetBrightness.cs
using System;
using UnityEngine;

#if !UNITY_EDITOR && UNITY_IOS
using System.Runtime.InteropServices;
#endif
namespace HutongGames.PlayMaker.Actions {
    [ActionCategory(ActionCategory.Device)]
    [Tooltip("Gets screen brightness.")]
    public class GetBrightness : FsmStateAction {
        #if !UNITY_EDITOR && UNITY_IOS
        [DllImport("__Internal")]
        private static extern float getBrightness();
        #endif
        [ActionSection("Set up")]
        public bool everyFrame;
        [ActionSection("Store Result")]
        [RequiredField]
        [UIHint(UIHint.Variable)]
        public FsmFloat brightness;

        public override void Reset() {
            everyFrame = false;
            brightness = null;
        }

        public override void OnEnter() {
            DoAction();
            if (!everyFrame)
                Finish();
        }

        public override void OnUpdate() {
            DoAction();
        }

        private void DoAction() {
            #if UNITY_EDITOR
            #elif UNITY_IOS
            brightness.Value = getBrightness();
            #elif UNITY_ANDROID
            var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
            var system = new AndroidJavaClass("android.provider.Settings.System");
            var contentResolver = activity.Call<AndroidJavaObject>("getContentResolver");
            var b = system.CallStatic<int>("getInt", contentResolver, system.CallStatic<string>("SCREEN_BRIGHTNESS"));
            brightness.Value = b / 255f;
            #endif
        }
    }
}

終わり

画面輝度を変更するUnityAPIがなかった。せめてサードパーティのアセットがあればいいが一切なかった。
もちろんPlayMakerを通さなくても通常のスクリプトで同じように記述しても問題なく動く。
今回はiOSのネイティブ側の準備が必要でPlayMaker用のC#だけではダメだったのでPlayMakerのEcosystemに追加できないのでこの場で公開した。

追記

getとsetの値についてsetで0を入れてしまうと画面が完全に見えなくなったりバグったりって話を聞いたので1以下にならないようにしたけど、getの時とsetの時でint(0~255)とfloat(0~1)間の変換の計算式が違うのが気持ち悪かったかも。

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5