Search Unity

Input System Issues with Amazon Fire Tv Controller. [Solved]

Discussion in 'Input System' started by OscarLeif, Oct 9, 2021.

  1. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    69
    Hello I was working on joystick support for Amazon Fire TV devices.

    Just go to final post I wrote a solution

    Input System I have issues.
    When I try to use Input System I can only get this
    Input Values View attachment 934912
    The previous Input Manager can Handle more Inputs. But I cannot figure out how to enable all the previous supported Inputs (Buttons)

    Input manager can read Joystick Button 0.
    It was even possible to read the "Back Button" via Input.GetKey(KeyCode.Escape)
    But it was really reading the Keyboard Input, it was fine.

    I try to override the Input Buttons using a custom UnityPlayerActivity.

    Code (CSharp):
    1. public class UnityAtaPlayerActivity extends UnityPlayerActivity
    2. {
    3.     //This Java Code
    4.    //Override the UnityPlayerActivity
    5.     private int PlayPauseTarget = KeyEvent.KEYCODE_SPACE;
    6.     private int MediRewindTarget = KeyEvent.KEYCODE_G;
    7.     private int FastForwardTarget = KeyEvent.KEYCODE_R;
    8.  
    9.     private int DPadCenterTarget = KeyEvent.KEYCODE_BUTTON_A; // This is a GamePad
    10.     private int MenuTarget = KeyEvent.KEYCODE_MENU;
    11.     private int BackTarget = KeyEvent.KEYCODE_BACK;
    12.  
    13.     @Override
    14.     public boolean onKeyUp(int keyCode, KeyEvent event)
    15.     {
    16.         switch (keyCode)
    17.         {
    18.             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
    19.                 KeyEvent newEvent = new KeyEvent(KeyEvent.ACTION_UP, PlayPauseTarget);
    20.                 return mUnityPlayer.injectEvent(newEvent);        
    21.             default:
    22.                 return mUnityPlayer.injectEvent(event);
    23.         }
    24.     }
    25.     @Override
    26.     public boolean onKeyDown(int keyCode, KeyEvent event)
    27.     {
    28.         switch(keyCode)
    29.         {
    30.             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
    31.                 KeyEvent newEvent = new KeyEvent(KeyEvent.ACTION_DOWN, PlayPauseTarget);
    32.                 return mUnityPlayer.injectEvent(newEvent);          
    33.             default:
    34.                 return mUnityPlayer.injectEvent(event);
    35.         }
    36.     }
    37. }
    But time is not working, I don't understand why.
    What I only found what this
    View attachment 934918
    The Input debug have 2 android Joysticks

    The First one Triggers the override Keys from the Custom UnityPlayerMainActivity.
    The Second triggers the keys from the first Image. No DPad_center.

    I mean how can I give support for this remote controller for Input System?
    It's possible to map this controller via Android ?
     
    Last edited: Oct 15, 2021
  2. dmytro_at_unity

    dmytro_at_unity

    Unity Technologies

    Joined:
    Feb 12, 2021
    Posts:
    212
    I've checked what keyboard bindings we have right now:

    https://developer.amazon.com/docs/fire-tv/remote-input.html

    So these should be mapped as following:
    KEYCODE_BACK = Escape
    KEYCODE_MENU = Menu/contextmenu
    KEYCODE_DPAD_UP = Up arrow
    KEYCODE_DPAD_DOWN = Down arrow
    KEYCODE_DPAD_LEFT = Left arrow
    KEYCODE_DPAD_RIGHT = Right arrow

    But these 4 are not mapped currently:
    KEYCODE_DPAD_CENTER = not mapped
    KEYCODE_MEDIA_PLAY_PAUSE = not mapped
    KEYCODE_MEDIA_REWIND = not mapped
    KEYCODE_MEDIA_FAST_FORWARD = not mapped

    The code that you're suggesting looks reasonable on a first look, so if you put breakpoints do you see KEYCODE_MEDIA_PLAY_PAUSE coming in? Also you're overriding the activity, but I recon you have unity player frame view in focus, so you need to override UnityPlayer also

    Also don't forget that there are two more handlers, four in total:
    Code (CSharp):
    1. public boolean onKeyUp(int keyCode, KeyEvent event)
    2. public boolean onKeyDown(int keyCode, KeyEvent event)
    3. public boolean onKeyMultiple(int keyCode, int count, KeyEvent event)
    4. public boolean onKeyLongPress(int keyCode, KeyEvent event)
     
  3. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    69
    dmytro_at_unity

    When using the old input, It was possible to use the non mapped keys like this.
    Because it will return Keyboard input making everything super easier, just inject

    KEYCODE_MEDIA_PLAY_PAUSE -> KeyEvent.KEYCODE_SPACE.
    When Press PlayPause I get need to read Key.Space in InputSystem.

    Code (CSharp):
    1.  
    2. //This is Android Code!!!!
    3. public class UnityAtaPlayerActivity extends UnityPlayerActivity
    4. {  
    5.     @Override
    6.     public boolean onKeyUp(int keyCode, KeyEvent event)
    7.     {
    8.         switch (keyCode)
    9.         {
    10.             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
    11.                 KeyEvent newEvent = new KeyEvent(KeyEvent.ACTION_UP); KeyEvent.KEYCODE_SPACE;
    12.                 return mUnityPlayer.injectEvent(newEvent);
    13.             default:
    14.                 return mUnityPlayer.injectEvent(event);
    15.         }
    16.     }
    17. }
    But this only works with the Old Input System. You cannot use this because it never trigger UnityEngine.InputSystem.Keyboard.
    Maybe this need an update or fix in the Input System Library ?
     
    Last edited: Oct 11, 2021
  4. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    69
    I try to create a Custom Device.
    But the result wasn't great.
    For now this could be the best solution I can figure out.

    The mapped keys are get by reading the Input System Keyboard.
    The Non Mapped keys are get by using Android Java Calls to the Override Main Activity.

    It was working, until I compile with IL2CPP (The Build that I need to upload in any Store)
    I don't know what to from here.

    Code (CSharp):
    1. using System.Linq;
    2. using System.Runtime.InteropServices;
    3. using UnityEngine;
    4. using UnityEngine.InputSystem;
    5. using UnityEngine.InputSystem.Controls;
    6. using UnityEngine.InputSystem.Layouts;
    7. using UnityEngine.InputSystem.LowLevel;
    8. using UnityEngine.InputSystem.Utilities;
    9. #if UNITY_EDITOR
    10. using UnityEditor;
    11. #endif
    12.  
    13. public struct AftvRemoteDeviceState : IInputStateTypeInfo
    14. {
    15.     public FourCC format => new FourCC('A','G','C');
    16.     //Buttons
    17.     [InputControl(name = "selectButton", layout = "Button", bit = 0, displayName = "Select Button")]
    18.     [InputControl(name = "backButton", layout = "Button", bit = 1, displayName = "Back Button")]
    19.     [InputControl(name = "menuButton", layout = "Button", bit = 2, displayName = "Menu Button")]
    20.     [InputControl(name = "rewindButton", layout = "Button", bit = 3, displayName = "Rewind Button")]
    21.     [InputControl(name = "playPauseButton", layout = "Button", bit = 4, displayName = "PlayPause Button")]
    22.     [InputControl(name = "fastForwardButton", layout = "Button", bit = 5, displayName = "FastForward Button")]
    23.     public ushort buttons;
    24.  
    25.     [InputControl(name = "stick", format = "VC2B", layout = "Stick", displayName = "Main Stick")]
    26.     [InputControl(name = "stick/x", defaultState = 127, format = "BYTE",
    27.         offset = 0,
    28.         parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5")]
    29.     public byte x;
    30.     [InputControl(name = "stick/y", defaultState = 127, format = "BYTE",
    31.         offset = 1,
    32.         parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5")]
    33.     [InputControl(name = "stick/up", parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp=2,clampMin=0,clampMax=1")]
    34.     [InputControl(name = "stick/down", parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp=2,clampMin=-1,clampMax=0,invert")]
    35.     [InputControl(name = "stick/left", parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp=2,clampMin=-1,clampMax=0,invert")]
    36.     [InputControl(name = "stick/right", parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp=2,clampMin=0,clampMax=1")]
    37.     public byte y;
    38. }
    39.  
    40. #if UNITY_EDITOR
    41. [InitializeOnLoad] // Call static class constructor in editor.
    42. #endif
    43. [InputControlLayout(stateType = typeof(AftvRemoteDeviceState))]
    44. public class AftvRemoteDevice : InputDevice, IInputUpdateCallbackReceiver
    45. {
    46. #if UNITY_EDITOR
    47.     static AftvRemoteDevice()
    48.     {
    49.         Initialize();
    50.     }
    51. #endif
    52.  
    53.     [RuntimeInitializeOnLoadMethod]
    54.     public static void Initialize()
    55.     {
    56.         InputSystem.RegisterLayout<AftvRemoteDevice>
    57.            (
    58.                matches: new InputDeviceMatcher()
    59.                .WithInterface("Android")
    60.                .WithDeviceClass("AndroidGameController")
    61.                .WithCapability("vendorId", 369) //
    62.                .WithCapability("productId", 1043)
    63.            );
    64.     }
    65.  
    66.     public ButtonControl selectButton { get; private set; }
    67.     public ButtonControl backButton { get; private set; }
    68.     public ButtonControl menuButton { get; private set; }
    69.  
    70.     //Unity Activity Override Buttons
    71.     public ButtonControl rewindButton { get; private set; }
    72.     public ButtonControl playPauseButton { get; private set; }
    73.     public ButtonControl fastForwardButton { get; private set; }
    74.  
    75.     public StickControl stick { get; private set; }
    76.  
    77.     private static AndroidJavaClass javaClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    78.  
    79.     protected override void FinishSetup()
    80.     {
    81.         base.FinishSetup();
    82.  
    83.         selectButton = GetChildControl<ButtonControl>("selectButton");
    84.         backButton = GetChildControl<ButtonControl>("backButton");
    85.         menuButton = GetChildControl<ButtonControl>("menuButton");
    86.  
    87.         rewindButton = GetChildControl<ButtonControl>("rewindButton");
    88.         playPauseButton = GetChildControl<ButtonControl>("playPauseButton");
    89.         fastForwardButton = GetChildControl<ButtonControl>("fastForwardButton");
    90.  
    91.         stick = GetChildControl<StickControl>("stick");
    92.  
    93.     }
    94.  
    95.     public static AftvRemoteDevice current { get; private set; }
    96.     public override void MakeCurrent()
    97.     {
    98.         base.MakeCurrent();
    99.         current = this;
    100.     }
    101.  
    102.     protected override void OnRemoved()
    103.     {
    104.         base.OnRemoved();
    105.         if (current == this)
    106.             current = null;
    107.     }
    108.  
    109.  
    110.     public void OnUpdate()
    111.     {
    112.         var keyboard = Keyboard.current;
    113.  
    114.         if (keyboard == null)
    115.             return;
    116.  
    117.         //Debug.Log("Aftv Update");
    118.         AftvRemoteDeviceState state = new AftvRemoteDeviceState();
    119.  
    120.         state.x = 127;
    121.         state.y = 127;
    122.  
    123.         var wPressed = keyboard.wKey.isPressed || keyboard.upArrowKey.isPressed;
    124.         var aPressed = keyboard.aKey.isPressed || keyboard.leftArrowKey.isPressed;
    125.         var sPressed = keyboard.sKey.isPressed || keyboard.downArrowKey.isPressed;
    126.         var dPressed = keyboard.dKey.isPressed || keyboard.rightAltKey.isPressed;
    127.  
    128.         if (aPressed)
    129.             state.x -= 127;
    130.         if (dPressed)
    131.             state.x += 127;
    132.         if (wPressed)
    133.             state.y += 127;
    134.         if (sPressed)
    135.             state.y -= 127;
    136.  
    137.         // Map buttons to 1, 2, and 3.
    138.  
    139.         if (keyboard.leftMetaKey.isPressed || keyboard.rightMetaKey.isPressed || keyboard.escapeKey.isPressed)//back
    140.             state.buttons |= 1 << 1;
    141.         if (keyboard.contextMenuKey.isPressed)//menu
    142.             state.buttons |= 1 << 2;
    143.  
    144.  
    145.         ///Call this Only Works once
    146.         ///For the Rewind KeyButton
    147.         ///After that the Input Fails.
    148.         ///I wonder If I can make this different
    149.         ///
    150. #if UNITY_ANDROID && !UNITY_EDITOR
    151.         using (AndroidJavaObject currentActivity = javaClass.GetStatic<AndroidJavaObject>("currentActivity"))
    152.         {
    153.             if (currentActivity.GetStatic<bool>("DPadCenter"))//select
    154.                 state.buttons |= 1 << 0;
    155.  
    156.             if (currentActivity.GetStatic<bool>("RewindButtonDown"))//RewindButton
    157.             {
    158.                 state.buttons |= 1 << 3;
    159.             }
    160.             if (currentActivity.GetStatic<bool>("PlayPauseButtonDown"))//PlayPauseButton
    161.             {
    162.                 state.buttons |= 1 << 4;
    163.             }
    164.             if (currentActivity.GetStatic<bool>("FastForwardButtonDown"))//ForwardButton
    165.             {
    166.                 state.buttons |= 1 << 5;
    167.             }
    168.         }
    169. #endif
    170.         InputSystem.QueueStateEvent(this, state);
    171.     }
    172.  
    173. #if UNITY_EDITOR
    174.     [MenuItem("Tools/Custom Device Sample/Create Aftv Device")]
    175.     private static void CreateDevice()
    176.     {
    177.         // This is the code that you would normally run at the point where
    178.         // you discover devices of your custom type.    
    179.         InputSystem.AddDevice<AftvRemoteDevice>();
    180.     }
    181.  
    182.     // For completeness sake, let's also add code to remove one instance of our
    183.     // custom device. Note that you can also manually remove the device from
    184.     // the input debugger by right-clicking in and selecting "Remove Device".
    185.     [MenuItem("Tools/Custom Device Sample/Remove Aftv Device")]
    186.     private static void RemoveDevice()
    187.     {
    188.         var customDevice = InputSystem.devices.FirstOrDefault(x => x is AftvRemoteDevice);
    189.         if (customDevice != null)
    190.             InputSystem.RemoveDevice(customDevice);
    191.     }
    192.  
    193. #endif
    194.  
    195. }
    This is the override Unity Main Activity


    Code (JavaScript):
    1. public class UnityAtaPlayerActivity extends UnityPlayerActivity
    2. {
    3.     public static boolean DPadCenter;
    4.     public static boolean PlayPauseButtonDown;
    5.     public static boolean RewindButtonDown;
    6.     public static boolean FastForwardButtonDown;
    7.  
    8.     @Override
    9.     public boolean onKeyUp(int keyCode, KeyEvent event)
    10.     {
    11.         switch (keyCode)
    12.         {
    13.             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
    14.                 this.PlayPauseButtonDown=false;
    15.             case KeyEvent.KEYCODE_MEDIA_REWIND:
    16.                 this.RewindButtonDown=false;
    17.             case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
    18.                 this.FastForwardButtonDown=false;
    19.             case KeyEvent.KEYCODE_DPAD_CENTER:
    20.                 this.DPadCenter=false;
    21.         }
    22.         return mUnityPlayer.injectEvent(event);
    23.     }
    24.  
    25.     @Override
    26.     public boolean onKeyDown(int keyCode, KeyEvent event)
    27.     {
    28.         switch (keyCode)
    29.         {
    30.             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
    31.                 this.PlayPauseButtonDown=true;
    32.             case KeyEvent.KEYCODE_MEDIA_REWIND:
    33.                 this.RewindButtonDown=true;
    34.             case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
    35.                 this.FastForwardButtonDown=true;
    36.             case KeyEvent.KEYCODE_DPAD_CENTER:
    37.                 this.DPadCenter=true;
    38.         }
    39.         return mUnityPlayer.injectEvent(event);
    40.     }
    41. }
    In the debug version the controllers work a little bit strange, when I use the Dpad it works fine.
    When using the Media button (Rewind, Play,Pause) it works the first time, after that it fails.
     
    Last edited: Oct 12, 2021
  5. dmytro_at_unity

    dmytro_at_unity

    Unity Technologies

    Joined:
    Feb 12, 2021
    Posts:
    212
    > It was working, until I compile with IL2CPP

    Likely because of stripping, try placing [Preserve] on the struct/fields.

    > This is the override Unity Main Activity

    Try overriding UnityPlayer frame, not just activity. I'm not 100% sure but activity might not get keyboard callbacks when frame is in focus.
     
  6. dmytro_at_unity

    dmytro_at_unity

    Unity Technologies

    Joined:
    Feb 12, 2021
    Posts:
    212
    @OscarLeif another detail which might be relevant, is that we use deviceId of events for device association, so if you're creating a new event be sure to base it's on original event so fields like deviceId, eventTime, flags, source, etc are preserved.

    There are copy ctor KeyEvent(KeyEvent origEvent) and there also expanded constructor KeyEvent(long downTime, long eventTime, int action, int code, int repeat, int metaState, int deviceId, int scancode, int flags, int source) for this.
     
    Last edited: Oct 13, 2021
  7. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    69
    @dmytro_at_unity
    How you override "UnityPlayer Frame" ?
    Right now I add the [Preserve] on the struct and it's working in the IL2CPP Build.
    I was working on this and I found that UI navigation with this plugin works fine.
    Something interesting was that the Input debugger never register the Input Keys called from the Main Activity.

    While the UI navigation works, I cannot get this plugin works with the Component "Player Input"
    Maybe it's the activity override keys are not called in the correct time....But the custom device doesn't have Execution Order.
     
  8. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    69
    Ok I check the Source Code of the Input System.
    And with this Script the Remote control of the Fire TV should work fine.
    I didn't know you could actually check how the Input System works.
    With this you don't need

    -modify the Android Main Activity (Probably we should avoid doing that)
    -call weird JNI scripts (that create a lot of Unnecessary garbage)

    The Bit Values where comes from ?

    Here: https://github.com/Unity-Technologi...InputSystem/Plugins/Android/AndroidKeyCode.cs
    It's the same values from the Android API
    https://developer.android.com/reference/android/view/KeyEvent#summary

    If you wan to support Volume Up and Down just add the keys with the Bit value from the previous links.
    But I suggest it's not a great Idea override or use those buttons (but you can :D)

    Code (CSharp):
    1. using System.Linq;
    2. using UnityEngine;
    3. using UnityEngine.InputSystem;
    4. using UnityEngine.InputSystem.Controls;
    5. using UnityEngine.InputSystem.Layouts;
    6. using UnityEngine.InputSystem.LowLevel;
    7. using UnityEngine.InputSystem.Utilities;
    8. using UnityEngine.Scripting;
    9.  
    10. #if UNITY_EDITOR
    11. using UnityEditor;
    12. #endif
    13.  
    14. [Preserve]
    15. public struct AftvRemoteDeviceState : IInputStateTypeInfo
    16. {
    17.     public FourCC format => new FourCC('A', 'G', 'C');
    18.  
    19.     //Mapped Here
    20.     [InputControl(name = "dPadUpButton", layout = "Button", bit = 19, displayName = "Dpad Up")]
    21.     [InputControl(name = "dPadRightButton", layout = "Button", bit = 22, displayName = "Dpad Right")]
    22.     [InputControl(name = "dPadDownButton", layout = "Button", bit = 20, displayName = "Dpad Down")]
    23.     [InputControl(name = "dPadLeftButton", layout = "Button", bit = 21, displayName = "Dpad Left")]
    24.     [InputControl(name = "backButton", layout = "Button", bit = 4, displayName = "Back Button")]
    25.     [InputControl(name = "menuButton", layout = "Button", bit = 82, displayName = "Menu Button")]
    26.     //Non Maped
    27.     [InputControl(name = "selectButton", layout = "Button", bit = 23, displayName = "Select Button")]
    28.     [InputControl(name = "rewindButton", layout = "Button", bit = 89, displayName = "Rewind Button")]
    29.     [InputControl(name = "playPauseButton", layout = "Button", bit = 85, displayName = "Play Pause Button")]
    30.     [InputControl(name = "fastForwardButton", layout = "Button", bit = 90, displayName = "Fast Forward Button")]
    31.     public uint buttons;
    32. }
    33.  
    34. #if UNITY_EDITOR
    35. [InitializeOnLoad] // Call static class constructor in editor.
    36. #endif
    37. [Preserve]
    38. [InputControlLayout(displayName = "Aftv Remote", stateType = typeof(AftvRemoteDeviceState))]
    39. public class AftvRemoteDevice : InputDevice
    40. {
    41. #if UNITY_EDITOR
    42.     static AftvRemoteDevice()
    43.     {
    44.         Initialize();
    45.     }
    46. #endif
    47.  
    48.     [RuntimeInitializeOnLoadMethod]
    49.     private static void Initialize()
    50.     {
    51.         InputSystem.RegisterLayout<AftvRemoteDevice>
    52.             (
    53.                 matches: new InputDeviceMatcher()
    54.                 .WithInterface("Android")
    55.                 .WithDeviceClass("AndroidGameController")
    56.                 .WithProduct("Amazon Fire TV Remote")
    57.             );
    58.     }
    59.  
    60.     public ButtonControl dPadUpButton { get; private set; }
    61.     public ButtonControl dPadRightButton { get; private set; }
    62.     public ButtonControl dPadDownButton { get; private set; }
    63.     public ButtonControl dPadLeftButton { get; private set; }
    64.     public ButtonControl selectButton { get; private set; }
    65.     public ButtonControl rewindButton { get; private set; }
    66.     public ButtonControl playPauseButton { get; private set; }
    67.     public ButtonControl fastForwardButton { get; private set; }
    68.     public ButtonControl backButton { get; private set; }
    69.     public ButtonControl menuButton { get; private set; }
    70.     public bool SelectButtonDown { get; set; }
    71.     public bool RewindButtonDown { get; set; }
    72.     public bool PlayPauseButtonDown { get; set; }
    73.     public bool FastForwardButtonDown { get; set; }
    74.  
    75.     protected override void FinishSetup()
    76.     {
    77.         base.FinishSetup();
    78.         dPadUpButton = GetChildControl<ButtonControl>("dPadUpButton");
    79.         dPadRightButton = GetChildControl<ButtonControl>("dPadRightButton");
    80.         dPadDownButton = GetChildControl<ButtonControl>("dPadDownButton");
    81.         dPadLeftButton = GetChildControl<ButtonControl>("dPadLeftButton");
    82.  
    83.         rewindButton = GetChildControl<ButtonControl>("rewindButton");
    84.         playPauseButton = GetChildControl<ButtonControl>("playPauseButton");
    85.         fastForwardButton = GetChildControl<ButtonControl>("fastForwardButton");
    86.  
    87.         backButton = GetChildControl<ButtonControl>("backButton");
    88.         menuButton = GetChildControl<ButtonControl>("menuButton");
    89.         selectButton = GetChildControl<ButtonControl>("selectButton");    
    90.     }
    91.  
    92.     public static AftvRemoteDevice current { get; private set; }
    93.  
    94.     public override void MakeCurrent()
    95.     {
    96.         base.MakeCurrent();
    97.         current = this;
    98.     }
    99.  
    100.     protected override void OnRemoved()
    101.     {
    102.         base.OnRemoved();
    103.         if (current == this)
    104.             current = null;
    105.     }
    106.  
    107.     #region Editor
    108. #if UNITY_EDITOR
    109.     [MenuItem("Tools/AftvRemote/Create Device")]
    110.     private static void CreateDevice()
    111.     {
    112.         InputSystem.AddDevice<AftvRemoteDevice>();
    113.     }
    114.     [MenuItem("Tools/AftvRemote/Remove Device")]
    115.     private static void RemoveDevice()
    116.     {
    117.         var customDevice = InputSystem.devices.FirstOrDefault(x => x is AftvRemoteDevice);
    118.         if (customDevice != null)
    119.             InputSystem.RemoveDevice(customDevice);
    120.     }
    121. #endif
    122.     #endregion
    123. }
    124.  
    But even if this was completed I still found some issues with the component "PlayerInput"
    It doesn't work, I use then an Input Action and this one works....If I found something I will post more.
     
    Last edited: Oct 15, 2021
  9. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    69
    I found more problems with the Fire OS.
    While the controller works and event the Input debugger reports Input.
    Some button actions stop working when I load a second scene.
    This happens with any controller.
     
  10. Drakonhawk

    Drakonhawk

    Joined:
    Feb 7, 2020
    Posts:
    6
    Thanks for your work. I could add support for NVIDIA SHIELD Remote by simply register a second device in Initialize() method.

    Code (CSharp):
    1. InputSystem.RegisterLayout<AndroidTVRemoteDevice>
    2.     (
    3.         matches: new InputDeviceMatcher()
    4.         .WithInterface("Android")
    5.         .WithDeviceClass("AndroidGameController")
    6.         .WithProduct("NVIDIA SHIELD Remote")
    7.     );
     
  11. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    69
    Hello!

    If I remember I stop using the Input System because It trigger a lot of errors beyond the editor.
    For example I remember Trying to use a Gamepad & a Keyboard on Windows Fails.
    Fire TV have this Crazy Error: When I try to Use Events, I don't remember they will not work.
    Not sure if because it was on a Fire TV (Unity Clearly says they will not support Fire OS).

    Check here: https://forum.unity.com/threads/fire-os-not-supported.613579/

    I just write this because I spend a lot of time to finally not use this. I really wanted to use the Input System actually is more lightweight than the previous Input Manager but is not stable, at the time I write this message.
     
  12. Justice_Developer

    Justice_Developer

    Joined:
    Mar 23, 2014
    Posts:
    13
    In case someone comes across this post again (it's highly ranked on google for fire tv with the new input system), I have found a solution and turned it into an Asset. It adds Fire TV & Android TV remote devices to the input system.

    Supports Fire TV 2. Gen & 3. Gen remotes and I was able to publish my game to the amazon app store with it.

    It does not support volume +/- and mute buttons, as this is against Amazons guidelines and you will probably fail their app review.

    https://assetstore.unity.com/packag...t-for-fire-tv-android-tv-and-google-tv-221855

    (I hope linking to my asset from the asset store is okay on these forums)
     
  13. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    69
    Well Unity Input system on Android read the bit values.
    so Fire Tv and Android TV should be the same.


    The Only stuff missing was the "Virtual Keys" for Android.
    I try to setup a game using the input system for android but I found that virtual keys didn't work while the old "Input Manager" work fine.

    I was close to switch to the Input System...Not really know if this is important.
     
  14. AbraTabia

    AbraTabia

    Joined:
    Jul 21, 2019
    Posts:
    11
    Hey everyone, so after 2 days and about 50 rebuilds of my game on to my firetv device, I wanted to share how this worked out in the end since this post was confusing, and one of the first pages to come back for search results on this topic. I found this post in the first hour of trying to solve this problem, and the answer was right there in front of me the entire time. But I understand this thread was originally for Oscar as the OP, and he was figuring stuff out in the process, and eventually it seems wasn't able to use this solution. So it sounds like it might not work and is not the accepted answer ... well Oscar's solution is really the best one. (full credit to him for the attached file).

    It's not really laid out for a new reader, and while Frenchy gave great information, all of which is true but didn't make sense to me until after I solved the problem. So Firetv works with Unity Input System but there is no device for it as of this writing, I even checked the newest version as of today. Unity should add this device, along with additional entries for other Android devices as DragonHawk did above (that post was helpful too). But in the meantime here is how to add a custom device for firetv.

    Oscar's file is perfect, and is not a script, it is a struct. So download it below and simply add it to your project. You do not need to edit it or add it to any scenes, game object etc. Just put it in your project and Unity will detect it and add it to the input system. You can see it in the input debugger and it works there, I will not cover that part but its fully working there. It also becomes available in all the UI menus under "Other" for device type. No matter what you try, without a device for Firetv you will never find the center D pad button or the menu button (back works as the escape key, and arrows as the d pad), so without this you may feel some hope but its never going to fully work without a custom device.

    When on a firetv, or any other android devices you add to the device list, the game will automatically use that controller. If you download the sample from Unity about a custom device, it is extremely well commented and this all will make more sense (but not required). In custom code you now access the buttons like this:

    Instead of: <Mouse>/leftButton it is:

    <AftvRemoteDevice>/selectButton
    <AftvRemoteDevice>/menuButton

    The back button is still escape, it was commented out so I assumed for a reason, but escape works fine and I still use the arrow keys like I used to, but here are those as well:

    <AftvRemoteDevice>/dPadUpButton
    <AftvRemoteDevice>/dPadDownButton
    <AftvRemoteDevice>/dPadLeftButton
    <AftvRemoteDevice>/dPadRightButton

    And the 3 bottom buttons you are not supposed to use, but they work as well:

    <AftvRemoteDevice>/rewindButton
    <AftvRemoteDevice>/playPauseButton
    <AftvRemoteDevice>/fastForwardButton

    Software Mouse:
    If you use a software mouse with the new input system, make sure to also add the dpad and select button to that so the mouse can use it too. Mouse settings: Under Stick Action, add a 2D Vector and the 4 options are the arrow keys (I use the actual arrow keys so my game also works with a keyboard, and they work with firetv too). You can of course use the custom dpad ones too.
    Required: Add the select button to the left click action: <AftvRemoteDevice>/selectButton

    You might also need to edit your Input Settings Asset under UI, point and click and add the custom device there as well. Enable keyboard and mouse for the custom device too. Any other sources of problems are likely in the Input Manager settings under Project Settings.

    Keep on gaming everyone.
     

    Attached Files: