I just released SpaceCat HD for Android TV. What it should have been a very simple and straight forward process turned out to give me quite a headache.
If you have a game that is gamepad-ready. Chances are that you are supporting MOGA controllers, simply because they are one of the best. If that’s the case you may also have this problem.
The not-so-obvious problem
If you want to publish for Android TV, you essentially have to do a few things in your manifest (see the full article on developer.android.com):
- Declare a TV Activity using an intent filter of the category CATEGORY_LEANBACK_LAUNCHER.
- Add a banner to the application (android:banner=”@drawable/banner”).
- Declare it as a game (android:isGame=”true”).
- Specify that it knows how to handle controllers.
- Specify that touchscreen is not required.
All these are very straight forward, but some of them require you to compile with targetSDK=21 (a.k.a. Lollipop) because is when they were introduced.
Another interesting change on Lollipop is the requirement of all service intents to be explicit. Any non-explicit one will throw an exception on runtime. This requirement is triggered when you compile with targetSDK=21.
And, obviously, the MOGA library does use a service with a non-explicit intent.
The invalid approaches
The first approach is to compile with a lower targetSDK, but then you can’t be on Android TV since the required manifest options aren’t available.
The second approach is to remove MOGA support, but then, the people that has those controllers will stop to have it supported.
The third option is to have multiple apks, one for Android TV with targetSDK=21 and another one for everyone else with a lower targetSDK. This sounds reasonable, but there is no clear way to separate Android TV from the rest and -as I was told by a Google Dev advocate- this was done in purpose.
But hold on, there is one more option, and it is the most obvious one, once you think about it.
The obvious solution
You just need to modify the code of the MOGA library to make it be an explicit intent. Except that the library is not open source.
It was pointed out to me by Robert Broglia, developer of Snes9x-EX+, that you could just use a decompiled version of the library, and then modify the init method. As you can see on his github project.
I’m really not a fan of having full libraries inside the source code, so I tried to just extend the controller to replace the init method for one using the explicit intent, that would have been a few lines of code, but the class is final.
At the end I created a new Controller that uses the explicit intent (and basically everything else is the same) and placed it under the package com.bda.controller.
It could have been easier
All this could have been much easier if
- MOGA had updated the library
- The Controller class wasn’t final
If you have a game that is MOGA-enabled and you want to port it to Android TV, I hope to have saved you some headaches.