Managing platform-specific code

One of the strong points of Libgdx is the cross-platform deployment feature since a single Java core project can be published to Android, iOS, HTML, and desktop with the help of RovoVM and Google Web Toolkit. However, in spite of abstracting the programmer from the dirty work, each platform has its particularities and there is still a need to handle them specifically under certain circumstances.

This recipe will deal with a real-life platform-specific problem that involves leading the user to a particular rating interface:

  • Desktop: This will route the user to a custom web
  • Android: This will route the user to the app's Google Play Store section
  • iOS: This will route the user to the app's Apple Store section
  • HTML: This will route the user to a custom web

Getting ready

The code for this recipe is spread across five projects. The first one is samples-core and has a com.cookbook.platforms package containing the PlatformResolver interface. The GdxSample abstract class, which implements the ApplicationListener interface and serves as base for each code sample of this book, will contain a static PlatformResolver member field so we can initialize it in the launcher classes with a particular implementation from the existing ones in the com.cookbook.samples folder of the rest of the projects (samples-android, samples-desktop, samples-gwt, and samples-ios).

An image is worth more than a thousand words, so the next diagram consolidates the previous explanation:

Getting ready

How to do it…

The approach is quite simple but a little bit messy because of the amount of files to touch. For the sake of clarity, the explanation will go from the interface to the implementation.

On the screen, a button will appear that will lead the clicker to the rating interface. Perform the following steps:

  1. First of all, write the PlatformResolver core interface whose mission is to abstract the behavior of each particular resolver:
    public interface PlatformResolver {
    public void rateGame();
    }

    Our main game class (GdxSample in this case) holds an instance to a specific PlatformResolver that is yet to be determined. It provides a getter and a setter to manage which resolver we must use:

    public abstract class GdxSamp2le implements ApplicationListener {
       protected static PlatformResolver platformResolver = null;
    
       public static PlatformResolver getPlatformResolver() {
          return platformResolver;
       }
    
       public static void setPlatformResolver(PlatformResolver platformResolver) {
          this.platformResolver = platformResolver;
       }
    ...
    }
  2. Implement a particular resolver per target platform. This is where individual behaviors are defined. For instance, the desktop might open a tab in your default browser with your custom rating website:
    public class DesktopResolver implements PlatformResolver {
       @Override
       public void rateGame() {
          System.out.println("Desktop");
          Gdx.net.openURI("https://facebook.com");
       }
    }

    Note

    Notice that Libgdx's net subsystem abstracts the programmer from dealing with platform-specific details for opening a web browser.

    In this particular case, we will keep the same behavior for the web version:

    public class WebResolver implements PlatformResolver {
    
    public void rateGame() {
    System.out.println("Web");
    Gdx.net.openURI("https://facebook.com ");
       }
    }

    Android applications are usually distributed in the Google Play Store, which has its own rating system for applications, so we will just make use of it:

    public class AndroidResolver implements PlatformResolver {
    public void rateGame() {
    System.out.println("Android");
    Gdx.net.openURI("https://play.google.com/store/apps/details?id=com.facebook.katana&hl=es");
       }
    }

    The same happens for iOS with its Apple Store:

    public class IOSResolver implements PlatformResolver {
       public void rateGame() {
    System.out.println("iOS");
    Gdx.net.openURI("http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=id284882215&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8");
       }
    }
  3. Now we need to assign each resolver to its corresponding platform, as shown in the following code:
    gdxSample.setPlatformResolver(new DesktopResolver());

    This would be the way to go with the desktop project; for the other ones, just instantiate the proper resolver type.

    Note

    Note that sometimes you will have to set different resolvers in the same starter class. This can be the case when using the OUYA gaming console, which is based on Android. You can solve this using an if-else branch:

    if(Ouya.runningOnOuya) {
       // you are running on a real Ouya device
       gdxSample.setPlatformResolver(new OUYAResolver());
    }
    else {
       // you are running on Android (no Ouya)
       gdxSample.setPlatformResolver(new AndroidResolver());
    }

There's more…

The scope of the preceding example is narrowed down in order to keep things simple but instead of a routing function to rate your application, you could make PlatformResolver work as a Façade by returning specific subsystems, such as APIs for social networks, leaderboards, and advertisements.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.185.196