Using volume buttons on Android in Unity3d

后端 未结 4 355
深忆病人
深忆病人 2021-01-25 21:28

I am attempting to use the volume buttons in a unity3d game on Android. Unfortunately I can\'t see anything pertaining to volume being mapped as a KeyCode, so it seems to me tha

4条回答
  •  有刺的猬
    2021-01-25 21:42

    Another approach is to use phone volume (Ok, it's a workaround^^). If the volume increase, so the volume button "UP" was pressed. Or, if the volume decrease, it means that the volume button "DOWN" was pressed. To access phone volume i used this stackoverflow answer: Unity3D: is it possible to check the volume of both Android and iPhone devices?

    Here is my solution for android (I didn't had the competence to deal with ios, but I guess the previous answer is giving some clues):

    public static class Common {
    
        private static AndroidJavaObject s_mainActivity = null;
        private static AndroidJavaObject s_androidAudioManager = null;
    
        public static AndroidJavaObject GetAndroidAudioManager()
        {
            if (s_androidAudioManager == null)
            {
                s_androidAudioManager = GetMainActivity().Call("getSystemService", "audio");
            }
            return s_androidAudioManager;
        }
    
        public static AndroidJavaObject GetMainActivity()
        {
            if (s_mainActivity == null)
            {
                var unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
                s_mainActivity = unityPlayerClass.GetStatic("currentActivity");
            }
            return s_mainActivity;
        }
    
        public static bool IsRunningOnAndroid()
        {
    #if UNITY_ANDROID && !UNITY_EDITOR
            return true;
    #else
            return false;
    #endif
        }
    }
    
    
    
    using UnityEngine;
    using System.Collections.Generic;
    
    public interface VolumeListener
    {
         void OnVolumeUp();
         void OnVolumeDown();
    }
    
    public abstract class VolumeListenerGO : MonoBehaviour, VolumeListener
    {
        public abstract void OnVolumeUp();
        public abstract void OnVolumeDown();
    }
    
    
    public class VolumeButton : MonoBehaviour {
    
        public bool m_bGetVolumeFromPhone = true;
        //for non gameobject listener
        public List m_vVolumeListener = null;
        //for gameobject listener (easier to edit in scene mode)
        public VolumeListenerGO[] m_vVolumeListenerGO = null;
    
        private float m_fPrevVolume = -1;
        private bool m_bShutDown = false;
    
        //quick access to reference
        private static VolumeButton s_instance = null;
    
    
        public static VolumeButton Get()
        {
            return s_instance;
        }
    
        //Get phone volume if running or android or application volume if running on pc
        //(or wanted by user)
        public float GetVolume()
        {
            if(m_bGetVolumeFromPhone && Common.IsRunningOnAndroid())
            {
                AndroidJavaObject audioManager = Common.GetAndroidAudioManager();
                return audioManager.Call("getStreamVolume", 3);
            }
            else
            {
                return AudioListener.volume;
            }
    
        }
    
        //set phone or application volume (according if running on android or if user want application volume)
        public void SetVolume(float a_fVolume)
        {
            if (m_bGetVolumeFromPhone && Common.IsRunningOnAndroid())
            {
                AndroidJavaObject audioManager = Common.GetAndroidAudioManager();
                audioManager.Call("setStreamVolume", 3, (int)a_fVolume, 0);
            }
            else
            {
                AudioListener.volume = a_fVolume;
            }
        }
    
        private void ResetVolume()
        {
            SetVolume(m_fPrevVolume);
        }
    
        void Start () {
            s_instance = this;
            PowerOn();
        }
    
        void OnVolumeDown()
        {
            if (m_vVolumeListener != null)
            {
                foreach (VolumeListener listener in m_vVolumeListener)
                {
                    listener.OnVolumeDown();
                }
            }
            if (m_vVolumeListenerGO != null)
            {
                foreach (VolumeListener listener in m_vVolumeListenerGO)
                {
                    listener.OnVolumeDown();
                }
            }
        }
    
        void OnVolumeUp()
        {
            if (m_vVolumeListener != null)
            {
                foreach (VolumeListener listener in m_vVolumeListener)
                {
                    listener.OnVolumeUp();
                }
            }
            if (m_vVolumeListenerGO != null)
            {
                foreach (VolumeListener listener in m_vVolumeListenerGO)
                {
                    listener.OnVolumeUp();
                }
            }
    
        }
    
        //If user want to change volume, he has to mute this script first
        //else the script will interpret this has a user input and resetvolume
        public void ShutDown()
        {
            m_bShutDown = true;
        }
    
        //to unmute the script
        public void PowerOn()
        {
            m_bShutDown = false;
            //get the volume to avoid interpretating previous change (when script was muted) as user input
            m_fPrevVolume = GetVolume();
        }
    
        // Update is called once per frame
        void Update () {
            if (m_bShutDown)
                return;
    
            float fCurrentVolume = GetVolume();
            float fDiff = fCurrentVolume - m_fPrevVolume;
    
            //if volume change, compute the difference and call listener according to
            if(fDiff < 0)
            { 
                ResetVolume();
                OnVolumeDown(); 
            }
            else if(fDiff > 0)
            {
                ResetVolume();
                OnVolumeUp();
            }
        }
    
    }
    

    I tested it on samsung note 4. Work also in VR mode with SamsungGear Input. Hope it can serve to someone.

    EDIT:

    This solution doesn't work if volume is minimum or maximum. So you have to set volume somewhere between minimum and maximum volume before.

    //to unmute the script
    public void PowerOn()
    {
        m_bShutDown = false;
        //get the volume to avoid interpretating previous change (when script was muted) as user input
        m_fPrevVolume = GetVolume();
    
        //if volume is set to max, reduce it -> if not, there will be no detection for volume up
        if (m_fPrevVolume == GetMaxVolume())
        {
            --m_fPrevVolume;
            SetVolume(m_fPrevVolume);
        }
    
    }
    
    //Get max volume phone
    public float GetMaxVolume()
    {
        if (m_bGetVolumeFromPhone && Common.IsRunningOnAndroid())
        {
            AndroidJavaObject audioManager = Common.GetAndroidAudioManager();
            return audioManager.Call("getStreamMaxVolume", 3);
        }
        else
        {
            return 1;
        }
    }
    

    Method for getting max volume was found there:

    Android: how to play music at maximum possible volume?

提交回复
热议问题