Deploying your libGDX game to iOS in 2019

MrStahlfelge (Benjamin Schulte)
8 min readMar 26, 2019

--

Hey, it is 2020, folks! This article is a bit outdated, so maybe you want to check out the new one!

Being long around, libGDX still is one of the best frameworks for writing a 2D game in Java or for Android. While it is quite easy to run a libGDX game from source on Desktops and Android, deploying to HTML and iOS is not as straightforward. Difficulties of deploying to HTML are mainly technical, caused by inabilities of the target platform or the GWT compiler and can be worked around. The problems when it comes to deploying to iOS differ: Two different backends to choose from, outdated documentation and little spread knowledge might lead to the conclusion that deploying a libGDX game to iOS in 2019 does not work anymore or is a secret craft for those in the know. That’s sad, because from my experiences after I steep start, deploying a libGDX to iOS is easy and you can expect your game to run without problems.

What you need

Sadly, different from all the other platforms, there’s at least one thing you need to deploy to iOS: a Mac to compile. The good news is that a Mac or Mac Mini from 2009 is sufficient for now. If you, like me, use such an ancient device, you will not be able to use the iOS simulator to proper test your game, so you will also need an iOS device. If you have better hardware, you might not need that in general, but beware: some services like IAPs or push notifications are not available on the simulator. You should choose something with 64 bit support. You don’t have to own the test device — if someone is willing to lend you an iPhone or iPod for a while, Apple will let you deploy your game on it.

What you do not need

You do not need to pay something to Apple in order to test your game on iOS, these times are over. You can deploy to the iOS simulator without any hassle, and you can deploy to an iOS device connected to your Mac with a so-called “free provisioning profile”. This is for testing purposes and the app will only work for a short time, then you need to compile and deploy again to get it working again.

You still need the costly developer account when you want to publish your game on the app store, or when you want to use Apple’s services like Game Center, IAPs or the push notification service.

Multi OS Engine or RoboVM?

There are two backends available to deploy on iOS: RoboVM (subproject name is just “ios” or “ios-robovm”) and Multi OS Engine (subproject name “ios-moe”). This leads to some confusion, and to the questions: Why? And which one is better one (for me)?

We begin with the first question: Why are there two backends for iOS?

RoboVM was the first solution to deploy libGDX games to iOS. Coming from Sweden, it was open-source in the beginning and aimed to be a cross-platform solution to bring existing Android apps to iOS. It does not only support core Java API, but provides a lot of Android-specific functionality on iOS. When it was acquired by Xamarin in October 2015, it was made closed-source. Only six months later Xamarin was acquired by Microsoft and further development stopped completely. It looked like this was the end for RoboVM, and the new Multi OS Engine libGDX backend was made. Others were not convinced of the new solution and made efforts to maintain the last open-source version of RoboVM, thus libGDX’ RoboVM backend was not deprecated.

Now it is three years later, and we come to the second question: Which solution is the better one?

For my first test, I deployed the good old Superjumper demo game to an iOS device with RoboVM and MOE. My experiences: RoboVM compiled to a smaller ipa file (iOS counterpart of an apk), RoboVM’s version ran smooth on an old device while MOE had framerate drops, and I noticed that libGDX’ RoboVM backend still is more mature than the MOE backend (for example, accelerometer was not supported in MOE). The decision to use RoboVM was very easy based on this, and I did not regret it so far: RoboVM is still under active and good maintenance.

But you are in the comfortable position to be able to try both, and feel free to do so and leave a comment.

Getting RoboVM to work

It is indeed pretty easy to get your game to work on iOS. However, there’s not a single documentation to do so that is not outdated. So here’s a quick step by step guide:

  1. Generate your iOS RoboVM subproject
    You can skip this step if you generated your iOS subproject from the beginning of your project. If you did not do so, just generate a new libGDX project from the setup tool and merge the settings.gradle, main build.gradle and the ios subfolder. You should use at least RoboVM 2.3.5 as I experienced problems with older versions on iOS 12. If you want to use the simulator you should use at least RoboVM 2.3.7 (see below for more info). Pay attention: The RoboVM build tools and RoboVM dependencies must use the same version!
  2. Install the RoboVM plugin into Android Studio
    Grab the plugin from the download site. Pay attention: You must use the same version as the RoboVM version you defined in your build.gradle file, again. Install the plug in into Android Studio with the “Install plugin from disk” button in the plugins settings.
  3. Install Xcode
    Install Xcode from App Store, RoboVM needs it to compile and sign your game. You’ll also need it for the next step.
    Hint: With RoboVM ≤ 2.3.6 and Xcode versions ≥ 10.2, it is not possible to use simulators. Use RoboVM 2.3.7 or scroll at the end of the article how to use an older Xcode version..
  4. Set up a provisioning profile
    This is only needed if you want to deploy on a real device, you can skip this step for the simulator.
    If you already have a paid developer account and want to use Apple services, you can use an own provisioning profile you created in Apple’s backend. Or, if you don’t want to pay (for now), you can use the free provisioning. In any case, you should add your Apple account to Xcode, then create an empty project with the same app id as used in the robovm.properties file of your project. Choose to let Xcode manage the provisioning profile. Xcode will search for the correct (paid) provisioning profile or will create a free provisioning profile, link your app id and a device connected to your Mac to it. Because only the connected device will get linked, you have to repeat this step for every other device you connect and want to run your game on. Save the Xcode project for this case.
  5. Create iOS run configurations
    Back in Android Studio, you need to create some Run configurations for iOS. Go to Run/Edit configurations and add (+) a RoboVM iOS configuration. Either choose the Simulator and a x86 architecture, or choose “Attached device” with “arm64” and choose your signing identity and provisioning profile from step 4.
    If you’ve made any mistakes in step 4 or 5, launching your game on a real device will stop on verification (40%).
  6. Clean up ios.iml
    Due to a bug in Android Studio’s toolchain, an Android node is added to your ios.iml file when a Gradle sync is performed. So this annoying step has to be repeated after every Gradle sync. Open ios.iml and delete the complete node <component name="FacetManager"> <facet type="android-gradle" name="Android-Gradle">...</component>. If you forget this step, compiling and running the game will stop with a NullPointerException.

You are done, hit the run button and let the magic happen! If you have something to add to this guide, please use the comment section.

You will need to do some extra steps if you want to compile an ipa file to upload to the store. The ipa file needs to be signed and use yet another provisioning profile, but if you get this far you’ll manage these difficulties, too.

Things you’ll need to change

Based on my experiences, there’s a good chance your game will run fine on an iPhone — or crash immediately due to your sound files or use of reflection. You will need some changes in any case: Some things are not supported out of the box.

Take a look at the files robovm.properties, Info.plist.xml and robovm.xml. These are configuration files for your compilation and the plist file is something like your AndroidManifest.

Things that are typically to change or fix for iOS, or at least important to know:

  1. Sounds
    iOS can’t play OGG, so you need to use MP3. Also consider setting the allowIpod flag to true. I don’t know why the default is set to false, but players wanting to hear their own music or podcasts won’t like it when your game cuts off their own music.
  2. ForceLinkClasses for all your class that are instantiated by reflection
    Somehow similar to GWT, you need to list all classes that are instantiated only by reflection in your robovm.xml file within the ForceLinkClasses node.
  3. Localization
    If you’ve localized your game, this will not work out of the box. You have to add the supported languages to your Info.plist.xml in order for iOS to let you know about the user’s language settings.
  4. Java Exceptions won’t crash your game and won’t get reported
    Java Exceptions will be printed to the console, but not all exceptions will crash your game. It might be in an undefined state and not to use anymore. It is important to set an own default catch handler and raise a system exception to prevent this. Because you will be interested in knowing about crashes on your user’s devices, you should also somehow report the Java stacktrace to a backend. I recommend using my lib gdx-gameanalytics to use with gameanalytics.com, or use the code from it as an example.
  5. Support the iPhone X screen
    If you want to release your game, you’ll have to support the interesting screen format of the iPhone X.

That’s all for know! Again, if I forgot something, let me know via the comment section.

Known problems and workarounds

Empty list of simulators

With RoboVM ≤ 2.3.6 and xcode versions ≥ 10.2, it is not possible to use simulators. There are two ways to solve this:

  • Use xcode ≤ 10.1
    You can still download xcode 10.1 from Apple’s download page (but not from the App Store). Disadvantage is that xcode 10.1 has only support for deploying and debugging in iOS ≤ 12.1. (This does not apply on your compiled ipa file which will run on iOS ≥ 12.2 without problems). If you need to deploy and debug on newer iOS versions, you have to manually add the support files.
  • Use RoboVM 2.3.7
    RoboVM 2.3.7 fixes the problem.

Version history

Update 04/12/19: allowIpod flag added to sounds section.

Update 05/17/19: Added workaround for empty list of simulators

Update 06/19/19: RoboVM 2.3.7 is released

--

--