zl程序教程

您现在的位置是:首页 >  云平台

当前栏目

Unity3D研究院之实时获取手机电流、电压、计算功率发热(一百一十八)

实时计算手机 获取 Unity3D 研究院 功率 电压
2023-09-27 14:27:15 时间

灵感来自Android的BatteryManager,可以实时获取到手机的电流。因为电压是恒定的,这样就能算出功率来,十分有助于统计手机发热问题。

BatteryManager并没有提供获取手机毫安的方法, 只提供了手机剩余毫安的方法,以及手机当前电量百分比。 这样虽然可以近似还原手机总毫安,但是还是有点偏差。还有一种方法是用com.android.internal.os.PowerProfile 来取手机电池总毫安时,但是在C#代码中写起来过于复杂,后续可以移植在java代码中。

测试的时候有点需要注意,不能插USB因为充电状态获取的电流是负数。

直接上代码。测试机是小米10 Pro

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

using UnityEngine;

 

public class NewBehaviourScript : MonoBehaviour

{

    float e = 0;

 

 

    private void OnGUI()

    {

        GUILayout.Label(string.Format($"<size=80>电池总容量{Power.capacity}毫安,电压{Power.voltage}伏</size>"));

        GUILayout.Label(string.Format($"<size=80>实时电流{e}毫安,实时功率{(int)(e * Power.voltage)},满电量能玩{((Power.capacity /e).ToString("f2"))}小时</size>"));

    }

 

 

    float t = 0f;

    private void Update()

    {

        if(Time.time - t > 1f)

        {

            t = Time.time;

            e = Power.electricity;

        }

    }

}

 

 

public class Power

{

 

 

  

    static public float electricity

    {

        get {

#if UNITY_ANDROID

            //获取电流(微安),避免频繁获取,取一次大概2毫秒

            float electricity = (float)manager.Call<int>("getIntProperty", PARAM_BATTERY);

            //小于1W就认为它的单位是毫安,否则认为是微安

            return ToMA(electricity);

#else

            return -1f;

#endif

 

        }

    }

    //获取电压 伏

    static public float voltage { get; private set; }

 

    //获取电池总容量 毫安

    static public int capacity { get; private set; }

 

    //获取实时电流参数

    static object[] PARAM_BATTERY = new object[] { 2 }; //BatteryManager.BATTERY_PROPERTY_CURRENT_NOW)

    static AndroidJavaObject manager;

    static Power()

    {

#if UNITY_ANDROID

        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");

        AndroidJavaObject currActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

        manager = currActivity.Call<AndroidJavaObject>("getSystemService", new object[] { "batterymanager" });

        capacity = (int)(ToMA((float)manager.Call<int>("getIntProperty", new object[] { 1 })) / ((float)manager.Call<int>("getIntProperty", new object[] { 4 })/100f));   //BATTERY_PROPERTY_CHARGE_COUNTER 1 BATTERY_PROPERTY_CAPACITY 4

 

        AndroidJavaObject receive = currActivity.Call<AndroidJavaObject>("registerReceiver", new object[] { null,new AndroidJavaObject("android.content.IntentFilter", new object[] { "android.intent.action.BATTERY_CHANGED" }) });

        if (receive != null)

        {  

            voltage = (float)receive.Call<int>("getIntExtra", new object[] { "voltage",0 })/1000f; //BatteryManager.EXTRA_VOLTAGE

        }

#endif

    }

 

    static float ToMA(float maOrua)

    {

        return maOrua < 10000 ? maOrua : maOrua / 1000f;

    }

}

 


通过这两个例子就能看出来,具体性能以及发热的比例了。欢迎有相关经验的小伙伴留言一起讨论。