Mobile Zone is brought to you in partnership with:

German has posted 18 posts at DZone. View Full User Profile

Using an MBaaS in your Mobile Game (Part 1): Preferences Manager on the Cloud

06.28.2013
| 1328 views |
  • submit to reddit

If you don't want your game to be isolated from the outside world, a back-end server is a must-have. A server provides a way to manage users, share game data (high scores, achievements, etc) and enable social interactions (among others). However, creating your own back-end is quite challenging (check out for example the multiple steps and extensive crypto signing required to verify back-end calls on Android apps as suggested by Google's Tim Bray).

Fortunately, game developers can leverage services like Kii Cloud that provide everything they need to have a robust, scalable gaming back-end that works across the multiple platforms that your game supports while still offering a soft learning curve. This removes the complexity of back-end implementation and allows you to focus on building your game.

In order to show indie game developers the value of a mobile back-end service, I'm going to provide a series of blog posts targeting specific game-related needs such as distributed high score maintenance, user registration, game data storage and social interactions among users. For these examples I'm going to use the open source Android game "Frozen Bubble" (a nice game originally created for Linux with a decent Android port that doesn't include any type of backend functionality).

Frozen Bubble screenshot
Frozen Bubble for Android screenshot

Let's get started with how to support Facebook authentication and game preferences on the "cloud" using the Kii SDK. As you probably already know Kii Cloud initialization is trivial after you add the jar library to the class path (for more info about installation please see this page):

	/**
	 * Initialize KiiSDK Please change APP_ID/APP_KEY to your application
	 */
	private void initKiiCloud() {
		Kii.initialize(
                      Constants.APP_ID,
		      Constants.APP_KEY,
		      Site.US
		);
	}

I have already covered Facebook authentication in detail here and the process for supporting it in Frozen Bubble is no different. We're basically going to use the game's splash screen to trigger a Facebook authentication automatically which will translate into us having a specific Kii user to work with (if the auth process is successful). Note that the process is a signup + signin. The first time you run the app you'll be redirected to a Facebook page where you can enable the application to sign in with your Facebook user. After you accept, you won't see the Facebook page again (signing in is automatic after that).

Frozen Bubble Facebook Auth
Frozen Bubble Facebook Auth

The code basically looks like this:

   /**
     * Facebook login
     */
    private void facebookLogin() {
    	Log.d(TAG, "Initializing facebook login");
    	KiiSocialConnect facebook = Kii.socialConnect(SocialNetwork.FACEBOOK);
    	facebook.initialize(Constants.FB_APP_ID, null, null);
		facebook.logIn(this, null, new KiiSocialCallBack(){   
    		@Override   
    		public void onLoginCompleted(SocialNetwork network, KiiUser user, Exception exception) {     
    			super.onLoginCompleted(network, user, exception);
    	                if (exception != null) {
    	        	   Log.d(TAG, "Facebook login exception");
    	        	   return;
    	                }
    	                Log.d(TAG, "Facebook login completed");
    	                Log.d(TAG, "User is: " + KiiUser.getCurrentUser().getUsername());
    	                startFrozenBubble();
    		}
    	});
	}

Plus the line of code needed on the onActivityResult() method of the activity:

        Kii.socialConnect(SocialNetwork.FACEBOOK).respondAuthOnActivityResult(requestCode, resultCode, data);

To make things simple we're enforcing the Facebook auth when the application starts (i.e. the app won't run if you don't do the auth via Facebook). Ideally, we want the Facebook authentication to be an option among other standard signup/signin alternatives. Overall, the code needed to support Facebook authetication is minimal and all the redirection to the Facebook pages is handled automatically (just don't forget to provide the INTERNET permission in your Android manifest file).

Now let's move to managing data on Kii Cloud. Think about this: what's the difference between storing your game preferences on a standard preferences local file rather than on the cloud? You got it right, you can keep the same game preferences across devices as long as the user is the same. Wouldn't it be nice to allow your users to start from the last level they played even if they switch devices?

Let's take a look at how to create a user scope preferences manager on the cloud. Basically we'll work with one object (KiiObject) and store the preferences as key/value pairs. You can freely define your objects by adding any key-value pairs without setting any schemas or doing any extra customization. For this we'll encapsulate the functionality in a PreferencesManager class which works with a user scope KiiBucket (a bucket for cloud objects tied to each user of your app). Within this class is how we will work with the bucket and the cloud preferences object:

         KiiBucket userBucket = Kii.user().bucket("game_preferences");
         KiiObject cloudPrefs = userBucket.object();
         cloudPrefs.set("fullscreen", true);
         cloudPrefs.save();

See how easy it's to set key/value pairs on a KiiObject using set()? Keep in mind that save() is a remote call and will block/delay your UI thread so you might want to use the async version of save() that relies on a callback. In the code snippet above, we're initializing the bucket and the prefs object - but the bucket will be created on the cloud only after we call save(). Also note that we can call Kii.user() because we have authenticated via Facebook, otherwise, without a signed in user, you simply can't request a user scope bucket.

But how do we find out if there are preferences already stored on the cloud that we need to load? For that we use a Kii Cloud query:

        // Define query conditions. This is an empty "get all objects" query 
	KiiQuery query = new KiiQuery();
	query.setLimit(1);
	// Query the bucket for preferences object
	KiiQueryResult result = userBucket.query(query);
        List objLists = result.getResult();
	for (KiiObject obj : objLists) {
	      cloudPrefs = obj;
	      Log.d(TAG, "Preferences found");
	}

We're just querying for the preferences object in the bucket. You can have any number of buckets, Kii's backend is optimized for horizontal scaling - you can never have too many buckets, but can have objects that are too deep. That's why we just used a dedicated bucket for the preferences object. We're limiting the results to one for illustrating purposes though this is not actually necessary (we're using a single object to store all the preferences and we discard any duplicate if it were present). Once we retrieved the object from the cloud we can get values for specific keys:

        cloudPrefs.getString(key, default);
        cloudPrefs.getBoolean(key, default);
	cloudPrefs.getInt(key, default);

Note: These methods will return the default value if the keys are not found.

Overall it's very simple to work with a preferences manager on Kii Cloud. You can go ahead and check out the sample Frozen Bubble app with a PreferencesManagerimplementation that you can use in your own app. One word of advice: the sample uses sync calls to the cloud service which cause the game to lose some frames. Even though this is not noticeable I strongly advice you to use the asynchronous versions of these methods (e.g. save()) which return automatically and rely on a callback to tell you what happened or give you the results.

If you want to go deeper on data management with the Kii Cloud please check our excellent documentation. I will keep adding backend functionality to Frozen Bubble using Kii Cloud so stay tuned (eg. distributed high scores, push notifications, chat, analytics, etc)

Happy coding!!

Published at DZone with permission of its author, German Viscuso.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)