Checking for Android Tv in Unity

Usually if your making a game for AndroidTv it can be handy to detect at runtime when your connected to an AndroidTv or FireTv and change your controls.

The suggested approach described on the Android Developers website, seems to fail detecting most devices, there is an example of how to implement this method on the Unity forums.

The following code snippet uses Unity’s AndroidJavaObject & AndroidJavaClass similar to the example above however, it accesses the Android device and detects if it has the system feature Leanback or on older devices Television which indicates it has AndroidTv or FireTv support.

#if UNITY_ANDROID && !UNITY_EDITOR  // stop auto formatter removing unused using.
using UnityEngine;
#endif

/// <summary>
/// Used to retrieve if the hardware is set to AndroidTv or FireTv
/// </summary>
public class AndroidTvChecker {

#if UNITY_ANDROID && !UNITY_EDITOR
  private static AndroidJavaClass androidUnityActivity = null;

  /// <summary>    
  /// <para> Gets the current UnityActivity used on Android. </para>
  /// It will store the AndroidJavaClass for later use ensuring it is not creating a new
  /// class in memory every call.
  /// </summary>
  /// <returns> The AndroidActivity with the UnityPlayer running in it. </returns>
  public static AndroidJavaObject GetUnityActivity() {
    if (androidUnityActivity == null) {
      androidUnityActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    }
    return androidUnityActivity.GetStatic<AndroidJavaObject>("currentActivity");
  }
#endif

  private static bool? isTv = null;
  /// <summary>    
  /// Gets the current Android packageManager and checks if it has leanback or television.
  /// </summary>
  /// <returns> True if the device is an androidTv, false if not on android, or it fails. </returns>
  public static bool IsAndroidOrFireTv() {
    if (!isTv.HasValue) {
#if UNITY_ANDROID && !UNITY_EDITOR
      try {
        using (AndroidJavaObject context = GetUnityActivity().Call<AndroidJavaObject>("getApplicationContext"))
        using (AndroidJavaObject packageManager = context.Call<AndroidJavaObject>("getPackageManager")) {
          isTv = packageManager.Call<bool>("hasSystemFeature", "android.software.leanback") || packageManager.Call<bool>("hasSystemFeature", "android.hardware.type.television");
        }
      } catch (System.Exception e) {
        Debug.LogError("Couldn't Retrieve IsAndroidOrFireTv" + e);
        isTv = false;
      }
#else
      isTv = false;
#endif
    }

    return (bool)isTv;
  }
}

Using either of these approaches makes maintaining the code slightly easier as it does not require creating a separate plugin and keeping it up to date. Though at first glance the code is definitely difficult to read.

Related

comments powered by Disqus