Using volume buttons on Android in Unity3d

后端 未结 4 356
深忆病人
深忆病人 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<AndroidJavaObject>("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<AndroidJavaObject>("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<VolumeListener> 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<int>("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<int>("getStreamMaxVolume", 3);
        }
        else
        {
            return 1;
        }
    }
    

    Method for getting max volume was found there:

    Android: how to play music at maximum possible volume?

    0 讨论(0)
  • 2021-01-25 21:43

    You can build your app as an android studio/eclipse project and modify the UnityPlayerActivity (see: Extending the UnityPlayerActivity Java Code)

    Then you can use the volume keys as described in this SO answer: Android - Volume Buttons used in my application

    An example of comunication from activity to unity3d context:

    UnityPlayer.UnitySendMessage("TheNameOfYourGameObject", "PublicMethodInThatGameObject", "StringArgument");
    

    Note that there have been rumors of Samsung (not Google) not accepting an app to their stores if the button behaviour has changed.

    Also, it would be good UX, if the user will still be able to change the volume of your app.

    0 讨论(0)
  • 2021-01-25 21:46

    I'm guessing you're inquiring about volume buttons because your app got rejected by Samsung? Specifically, your app submission to Samsung will fail due to lack of support for Samsung Camera volume buttons and Samsung Homesync. The easiest workaround is to simply deselect support for these two items when submitting your game. If you switch to Advanced Mode in the Samsung Dashboard, you can select/deselect each device that you do/don't support. Just deselect all of the Samsung Camera entries and deselect Samsung Homesync when submitting your app.

    0 讨论(0)
  • 2021-01-25 21:57

    I do not think you can map controls to the volume buttons in Unity (using keycodes). Those buttons are controlled by the system OS, it would be a bad idea to map anything to it anyways.

    You can however map to the Android touch buttons. I beileve back is Keycode.Escape and menu is Keycode.Menu.

    0 讨论(0)
提交回复
热议问题