Click here to Skip to main content
15,885,952 members
Articles / Mobile Apps / Android

How To: Use Leaderboards on Android with XPG

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
1 Feb 2012CPOL3 min read 14.7K   1  
This post discusses how to use Leaderboards on Android with XPG.

This is a continuation of the How To series. The previous post is here.

This article will cover:

  • Leaderboard types and setup
  • Accessing leaderboards in game
  • Posting a score to a leaderboard
  • Retrieving scores from a leaderboard

Prerequisites

Leaderboard Types and Setup

In order to setup a leaderboard, you’ll need to have a free developer account with XPG and have registered a game in the management app. Assuming you’ve done these things, you can click on the leaderboards tab in the management app and begin defining your leaderboards.

image

In the above image, you can see the leaderboard dialog. As with most display values in the XPG system, the leaderboard name is globalized to help you provide a local experience for the end user. A display image can be defined by clicking the icon in the top right corner. The XPG system allows you to define a game-unique identifier for your leaderboard which is particularly helpful when migrating from another system to XPG, or implementing XPG along side another system. The available score types are Float, Integer, Money, and Time and each can be used with a score order of Ascending or Descending. The score order indicates if the high scores take high ranks (Descending) or if the lower scores take high ranks (Ascending). You can also limit this leaderboard’s availability by game version. Game versions are defined on the Access Keys tab in the Games area of the management app. Each version gets a new access key (or secret key) which positively identifies your game and game version.

image

Accessing Leaderboards in Game

As with many things in XPG, accessing leaderboards within your game is very simple. When your game was initialized (discussed in this post), the leaderboards defined in the XPG Management App were loaded in-game. Once these leaderboards were loaded, the first page of scores for each of them was also retrieved and loaded.

Java Code
Java
@Override
protected void onStart() {
    super.onStart();
    position = this.getIntent().getIntExtra("position", 0);
    lb = XPGAPI.Instance.getCurrentGame().getLeaderboards().get(position);

    if (lb == null) {
        onBackPressed();
    }

    Button refreshButton = (Button) findViewById(R.id.lbview_buttonRefresh);
    refreshButton.setOnClickListener(new OnRefreshClicked());

    Button scoreHighButton = (Button) findViewById(R.id.lbview_scoreHigh);
    scoreHighButton.setOnClickListener(new OnScoreHighClicked());

    Button scoreMedButton = (Button) findViewById(R.id.lbview_scoreMed);
    scoreMedButton.setOnClickListener(new OnScoreMedClicked());

    Button scoreLowButton = (Button) findViewById(R.id.lbview_scoreLow);
    scoreLowButton.setOnClickListener(new OnScoreLowClicked());

    scores = lb.getScores();

    TextView tt = (TextView) findViewById(R.id.lbview_name);
    if (tt != null) {
        tt.setText(lb.getDisplayName());
    }

    if (scores != null && scores.size() > 0) {
        ListView lv = (ListView) findViewById(R.id.lbview_items);
        lv.setAdapter(new AdapterLeaderboardScores(
                ActivityLeaderboard.this, R.layout.lbview_listitem, scores));
    }

    XPGAPI.Instance.setCallbackSubmitScore(new SubmitScoreCompleted());
}
C# Code
C#
protected override void OnStart()
{
    base.OnStart();
    position = this.Intent.GetIntExtra("position", 0);

    try
    {
        lb = XPGAPI.Instance.CurrentGame.Leaderboards[position];
    }
    catch
    {
        OnBackPressed();
    }

    if (lb == null) { OnBackPressed(); }

    scores = lb.Scores.ToList();

    Button refreshButton = FindViewById<Button>(Resource.Id.lbview_buttonRefresh);
    refreshButton.Click += OnRefreshClicked;

    Button scoreHighButton = FindViewById<Button>(Resource.Id.lbview_scoreHigh);
    scoreHighButton.Click += OnScoreHighClicked;

    Button scoreMedButton = FindViewById<Button>(Resource.Id.lbview_scoreMed);
    scoreMedButton.Click += OnScoreMedClicked;

    Button scoreLowButton = FindViewById<Button>(Resource.Id.lbview_scoreLow);
    scoreLowButton.Click += OnScoreLowClicked;

    TextView tt = FindViewById<TextView>(Resource.Id.lbview_name);
    if (tt != null)
    {
        tt.SetText(lb.DisplayName, TextView.BufferType.Normal);
    }

    ListView lv = FindViewById<ListView>(Resource.Id.lbview_items);
    if (scores != null && scores.Count > 0)
    {
        lv.Adapter = new AdapterLeaderboardScores(this, Resource.Layout.lbview_listitem, scores);
    }
}

Posting a Score to a Leaderboard

There are overloads in C# and Java provided to work with each of the score types mentioned above. The API will perform local updates of the leaderboard data after posting a score to the server when it detects that no user data from other players has affected the ranking other than the local user. Alternatively, the API will also initiate a full update of the leaderboard local data if it detects that one or more users have affected the leaderboard ranking other than the local user. This is all handled auto-magically in order to conserve bandwidth, processor time, and device battery.

Here is an example of score posting simplicity.

Java Code
Java
private class OnScoreHighClicked implements OnClickListener {
    @Override
    public void onClick(View arg0) {
        if (userScore != null) {
            XPGAPI.Instance.submitScore(lb.getLeaderboardTag(), new Double(
                    userScore.getUserScore().doubleValue() + 10), null);
        } else {
            try {
                XPGLeaderboardScoreInfo score = ((XPGLeaderboardScoreInfo) scores
                        .get(0));
                XPGAPI.Instance
                        .submitScore(lb.getLeaderboardTag(), new Double(
                                score.getUserScore().doubleValue() + 10),
                                null);
            } catch (Exception e) {
                XPGAPI.Instance.submitScore(lb.getLeaderboardTag(),
                        new Double(10), null);
            }
        }
    }
}
C# Code
C#
public void OnScoreHighClicked(object sender, EventArgs e)
{
    if (userScore != null)
    {
        XPGAPI.Instance.SubmitScore
        (lb.LeaderboardTag, userScore.UserScore + 10, SubmitScoreCompleted);
    }
    else
    {
        try
        {
            XPGLeaderboardScoreInfo score = scores[0];
            XPGAPI.Instance.SubmitScore
            (lb.LeaderboardTag, score.UserScore + 10, SubmitScoreCompleted);
        }
        catch (Exception ex)
        {
            XPGAPI.Instance.SubmitScore(lb.LeaderboardTag, 10, SubmitScoreCompleted);
        }
    }
}

Retrieving Scores from a Leaderboard

Retrieving scores from XPG is equally simple. The scores are stored locally on the leaderboard instance of the initialized game instance, so there are no collections for you to keep up with and manage on your own. Also, leaderboards support paging, so you are not required to have all the ranked user scores in memory at once.

Java Code
Java
private class OnRefreshClicked implements OnClickListener {
    @Override
    public void onClick(View arg0) {
        XPGAPI.Instance.getScores(lb.getLeaderboardTag(), 0,
                new GetScoresCompleted());
    }
}

private class GetScoresCompleted extends
            XPGAPICallbackGeneric<XPGScoresResultInfo> {
    @Override
    public void gotResponse(
            XPGAPIResponseGeneric<XPGScoresResultInfo> response) {
        if (!response.getFailed() && response.getBody() != null) {
            lb = XPGAPI.Instance.getCurrentGame().getLeaderboards()
                    .get(position);
            scores = lb.getScores();
            ListView lv = (ListView) findViewById(R.id.lbview_items);
            lv.setAdapter(new AdapterLeaderboardScores(
                    ActivityLeaderboard.this, R.layout.lbview_listitem,
                    scores));
        } else {
            Toast.makeText(ActivityLeaderboard.this,
                    "GetScores failed: " + response.getMessage(),
                    Toast.LENGTH_LONG).show();
        }
    }
}
C# Code
C#
public void OnRefreshClicked(object sender, EventArgs e)
{
    XPGAPI.Instance.GetScores(lb.LeaderboardTag, 0, GetScoresCompleted);
}

public void GetScoresCompleted(XPGAPIResponse<XPGScoresResultInfo> response)
{
    if (!response.Failed)
    {
        if (response.Body != null && response.Body.Scores != null 
                                  && response.Body.Scores.Count > 0)
        {
            scores = response.Body.Scores.ToList();
            ListView lv = FindViewById<ListView>(Resource.Id.lbview_items);
            lv.Adapter = new AdapterLeaderboardScores
                         (this, Resource.Layout.lbview_listitem, scores);
        }
    }
    else
    {
        Toast.MakeText
        (this, "GetScores failed: " + response.Message, ToastLength.Long).Show();
    }
}

Full Code

Java Code
Java
package XPG.Demo.Android;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.xpglive.api.XPGAPI;
import com.xpglive.api.XPGAPICallbackGeneric;
import com.xpglive.api.XPGAPIResponseGeneric;
import com.xpglive.api.XPGLeaderboardInfo;
import com.xpglive.api.XPGLeaderboardScoreInfo;
import com.xpglive.api.XPGScoreResultInfo;
import com.xpglive.api.XPGScoresResultInfo;

public class ActivityLeaderboard extends Activity {
    XPGLeaderboardInfo lb = null;
    private int position;
    private XPGLeaderboardScoreInfo userScore;
    private ArrayList<XPGLeaderboardScoreInfo> scores;

    @Override
    protected void onStart() {
        super.onStart();
        position = this.getIntent().getIntExtra("position", 0);
        lb = XPGAPI.Instance.getCurrentGame().getLeaderboards().get(position);

        if (lb == null) {
            onBackPressed();
        }

        Button refreshButton = (Button) findViewById(R.id.lbview_buttonRefresh);
        refreshButton.setOnClickListener(new OnRefreshClicked());

        Button scoreHighButton = (Button) findViewById(R.id.lbview_scoreHigh);
        scoreHighButton.setOnClickListener(new OnScoreHighClicked());

        Button scoreMedButton = (Button) findViewById(R.id.lbview_scoreMed);
        scoreMedButton.setOnClickListener(new OnScoreMedClicked());

        Button scoreLowButton = (Button) findViewById(R.id.lbview_scoreLow);
        scoreLowButton.setOnClickListener(new OnScoreLowClicked());

        scores = lb.getScores();

        TextView tt = (TextView) findViewById(R.id.lbview_name);
        if (tt != null) {
            tt.setText(lb.getDisplayName());
        }

        if (scores != null && scores.size() > 0) {
            ListView lv = (ListView) findViewById(R.id.lbview_items);
            lv.setAdapter(new AdapterLeaderboardScores(
                    ActivityLeaderboard.this, R.layout.lbview_listitem, scores));
        }

        XPGAPI.Instance.setCallbackSubmitScore(new SubmitScoreCompleted());
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.lbview);
    }

    private class OnRefreshClicked implements OnClickListener {
        @Override
        public void onClick(View arg0) {
            XPGAPI.Instance.getScores(lb.getLeaderboardTag(), 0,
                    new GetScoresCompleted());
        }
    }

    private class OnScoreHighClicked implements OnClickListener {
        @Override
        public void onClick(View arg0) {
            if (userScore != null) {
                XPGAPI.Instance.submitScore(lb.getLeaderboardTag(), new Double(
                        userScore.getUserScore().doubleValue() + 10), null);
            } else {
                try {
                    XPGLeaderboardScoreInfo score = ((XPGLeaderboardScoreInfo) scores
                            .get(0));
                    XPGAPI.Instance
                            .submitScore(lb.getLeaderboardTag(), new Double(
                                    score.getUserScore().doubleValue() + 10),
                                    null);
                } catch (Exception e) {
                    XPGAPI.Instance.submitScore(lb.getLeaderboardTag(),
                            new Double(10), null);
                }
            }
        }
    }

    private class OnScoreMedClicked implements OnClickListener {
        @Override
        public void onClick(View arg0) {
            if (userScore != null) {
                XPGAPI.Instance.submitScore(lb.getLeaderboardTag(), new Double(
                        userScore.getUserScore().doubleValue() + 5), null);
            } else {
                try {
                    XPGLeaderboardScoreInfo score = ((XPGLeaderboardScoreInfo) scores
                            .get(0));
                    XPGAPI.Instance.submitScore(lb.getLeaderboardTag(),
                            new Double(score.getUserScore().doubleValue() + 5),
                            null);
                } catch (Exception e) {
                    XPGAPI.Instance.submitScore(lb.getLeaderboardTag(),
                            new Double(5), null);
                }
            }
        }
    }

    private class OnScoreLowClicked implements OnClickListener {
        @Override
        public void onClick(View arg0) {
            if (userScore != null) {
                XPGAPI.Instance.submitScore(lb.getLeaderboardTag(), new Double(
                        userScore.getUserScore().doubleValue() + 1), null);
            } else {
                try {
                    XPGLeaderboardScoreInfo score = ((XPGLeaderboardScoreInfo) scores
                            .get(0));
                    XPGAPI.Instance.submitScore(lb.getLeaderboardTag(),
                            new Double(score.getUserScore().doubleValue() + 1),
                            null);
                } catch (Exception e) {
                    XPGAPI.Instance.submitScore(lb.getLeaderboardTag(),
                            new Double(1), null);
                }
            }
        }
    }

    private class GetScoresCompleted extends
            XPGAPICallbackGeneric<XPGScoresResultInfo> {
        @Override
        public void gotResponse(
                XPGAPIResponseGeneric<XPGScoresResultInfo> response) {
            if (!response.getFailed() && response.getBody() != null) {
                lb = XPGAPI.Instance.getCurrentGame().getLeaderboards()
                        .get(position);
                scores = lb.getScores();
                ListView lv = (ListView) findViewById(R.id.lbview_items);
                lv.setAdapter(new AdapterLeaderboardScores(
                        ActivityLeaderboard.this, R.layout.lbview_listitem,
                        scores));
            } else {
                Toast.makeText(ActivityLeaderboard.this,
                        "GetScores failed: " + response.getMessage(),
                        Toast.LENGTH_LONG).show();
            }
        }
    }

    private class SubmitScoreCompleted extends
            XPGAPICallbackGeneric<XPGScoreResultInfo> {
        @Override
        public void gotResponse(
                XPGAPIResponseGeneric<XPGScoreResultInfo> response) {
            if (!response.getFailed()) {
                lb = XPGAPI.Instance.getCurrentGame().getLeaderboards()
                        .get(position);
                scores = lb.getScores();
                ListView lv = (ListView) findViewById(R.id.lbview_items);
                lv.setAdapter(new AdapterLeaderboardScores(
                        ActivityLeaderboard.this, R.layout.lbview_listitem,
                        scores));
            } else {
                Toast.makeText(ActivityLeaderboard.this,
                        "SubmitScore failed: " + response.getMessage(),
                        Toast.LENGTH_LONG).show();
            }
        }
    }

    private class AdapterLeaderboardScores extends
            ArrayAdapter<XPGLeaderboardScoreInfo> {
        private ArrayList<XPGLeaderboardScoreInfo> items;

        public AdapterLeaderboardScores(Context context,
                int textViewResourceId,
                ArrayList<XPGLeaderboardScoreInfo> scoreItems) {
            super(context, textViewResourceId, scoreItems);
            this.items = scoreItems;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = vi.inflate(R.layout.lbview_listitem, null);
            }
            XPGLeaderboardScoreInfo score = items.get(position);
            if (score != null) {
                if (score.getUserName().equalsIgnoreCase(
                        XPGAPI.Instance.getCurrentUser().getUserName())) {
                    userScore = score;
                }
                TextView name = (TextView) convertView
                        .findViewById(R.id.lbview_itemname);
                if (name != null) {
                    name.setText("User: " + score.getUserNameDisplay());
                }
                TextView scoreVal = (TextView) convertView
                        .findViewById(R.id.lbview_itemscore);
                if (scoreVal != null) {
                    scoreVal.setText("Score: " + score.getUserScore());
                }
            }
            return convertView;
        }
    }
}
C# Code
C#
using System;
using System.Collections.Generic;
using System.Linq;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Util;
using Android.Views;
using Android.Widget;
using XPG.Demo.MonoDroid;

namespace XPG.Demo.Android
{
    [Activity(Label = "XPG Demo MonoDroid")]
    public class ActivityLeaderboard : Activity
    {
        private int position;
        XPGLeaderboardInfo lb = null;
        private XPGLeaderboardScoreInfo userScore;
        private List<XPGLeaderboardScoreInfo> scores;

        protected override void OnStart()
        {
            base.OnStart();
            position = this.Intent.GetIntExtra("position", 0);

            try
            {
                lb = XPGAPI.Instance.CurrentGame.Leaderboards[position];
            }
            catch
            {
                OnBackPressed();
            }

            if (lb == null) { OnBackPressed(); }

            scores = lb.Scores.ToList();

            Button refreshButton = FindViewById<Button>(Resource.Id.lbview_buttonRefresh);
            refreshButton.Click += OnRefreshClicked;

            Button scoreHighButton = FindViewById<Button>(Resource.Id.lbview_scoreHigh);
            scoreHighButton.Click += OnScoreHighClicked;

            Button scoreMedButton = FindViewById<Button>(Resource.Id.lbview_scoreMed);
            scoreMedButton.Click += OnScoreMedClicked;

            Button scoreLowButton = FindViewById<Button>(Resource.Id.lbview_scoreLow);
            scoreLowButton.Click += OnScoreLowClicked;

            TextView tt = FindViewById<TextView>(Resource.Id.lbview_name);
            if (tt != null)
            {
                tt.SetText(lb.DisplayName, TextView.BufferType.Normal);
            }

            ListView lv = FindViewById<ListView>(Resource.Id.lbview_items);
            if (scores != null && scores.Count > 0)
            {
                lv.Adapter = new AdapterLeaderboardScores
                       (this, Resource.Layout.lbview_listitem, scores);
            }
        }

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.lbview);
        }

        public void OnRefreshClicked(object sender, EventArgs e)
        {
            XPGAPI.Instance.GetScores(lb.LeaderboardTag, 0, GetScoresCompleted);
        }

        public void OnScoreHighClicked(object sender, EventArgs e)
        {
#if ANDROID
            Log.Debug("XPG", "lb.ScoreType = " + lb.ScoreType);
#endif
            if (userScore != null)
            {
                XPGAPI.Instance.SubmitScore(lb.LeaderboardTag, 
                          userScore.UserScore + 10, SubmitScoreCompleted);
            }
            else
            {
                try
                {
                    XPGLeaderboardScoreInfo score = scores[0];
                    XPGAPI.Instance.SubmitScore(lb.LeaderboardTag, 
                              score.UserScore + 10, SubmitScoreCompleted);
                }
                catch (Exception ex)
                {
                    XPGAPI.Instance.SubmitScore(lb.LeaderboardTag, 10, SubmitScoreCompleted);
                }
            }
        }

        public void OnScoreMedClicked(object sender, EventArgs e)
        {
#if ANDROID
            Log.Debug("XPG", "lb.ScoreType = " + lb.ScoreType);
#endif
            if (userScore != null)
            {
                XPGAPI.Instance.SubmitScore(lb.LeaderboardTag, 
                           userScore.UserScore + 5, SubmitScoreCompleted);
            }
            else
            {
                try
                {
                    XPGLeaderboardScoreInfo score = scores[0];
                    XPGAPI.Instance.SubmitScore(lb.LeaderboardTag, score.UserScore + 5, 
                                                SubmitScoreCompleted);
                }
                catch (Exception ex)
                {
                    XPGAPI.Instance.SubmitScore(lb.LeaderboardTag, 5, SubmitScoreCompleted);
                }
            }
        }

        public void OnScoreLowClicked(object sender, EventArgs e)
        {
#if ANDROID
            Log.Debug("XPG", "lb.ScoreType = " + lb.ScoreType);
#endif
            if (userScore != null)
            {
                XPGAPI.Instance.SubmitScore(lb.LeaderboardTag, 
                            userScore.UserScore + 1, SubmitScoreCompleted);
            }
            else
            {
                try
                {
                    XPGLeaderboardScoreInfo score = scores[0];
                    XPGAPI.Instance.SubmitScore(lb.LeaderboardTag, 
                               score.UserScore + 1, SubmitScoreCompleted);
                }
                catch (Exception ex)
                {
                    XPGAPI.Instance.SubmitScore(lb.LeaderboardTag, 1, SubmitScoreCompleted);
                }
            }
        }

        public void GetScoresCompleted(XPGAPIResponse<XPGScoresResultInfo> response)
        {
            if (!response.Failed)
            {
                if (response.Body != null && response.Body.Scores != null 
                            && response.Body.Scores.Count > 0)
                {
                    scores = response.Body.Scores.ToList();
                    ListView lv = FindViewById<ListView>(Resource.Id.lbview_items);
                    lv.Adapter = new AdapterLeaderboardScores
                                 (this, Resource.Layout.lbview_listitem, scores);
                }
            }
            else
            {
                Toast.MakeText
                (this, "GetScores failed: " + response.Message, ToastLength.Long).Show();
            }
        }

        public void SubmitScoreCompleted(XPGAPIResponse<XPGScoreResultInfo> response)
        {
            if (!response.Failed)
            {
                XPGAPI.Instance.GetScores(lb.LeaderboardTag, 0, GetScoresCompleted);
            }
            else
            {
                Toast.MakeText(this, "SubmitScore failed: " + 
                               response.Message, ToastLength.Long).Show();
            }
        }

        private class AdapterLeaderboardScores : ArrayAdapter<XPGLeaderboardScoreInfo>
        {
            private List<XPGLeaderboardScoreInfo> items;
            private Context ctxt;

            public AdapterLeaderboardScores(Context context,
                    int textViewResourceId,
                    List<XPGLeaderboardScoreInfo> scores)
                : base(context, textViewResourceId, scores)
            {
                this.items = scores;
                ctxt = context;
            }

            public override View GetView(int position, View convertView, ViewGroup parent)
            {
                if (convertView == null)
                {
                    LayoutInflater vi = (LayoutInflater)ctxt.GetSystemService
                                        (Context.LayoutInflaterService);
                    convertView = vi.Inflate(Resource.Layout.lbview_listitem, null);
                }
                XPGLeaderboardScoreInfo score = items[position];
                if (score != null && !score.UserName.Equals(
                        "No Scores To Display.", StringComparison.OrdinalIgnoreCase))
                {
                    TextView name = convertView.FindViewById<TextView>(Resource.Id.lbview_itemname);
                    if (name != null)
                    {
                        name.SetText("User: " + score.UserNameDisplay, TextView.BufferType.Normal);
                    }
                    TextView scoreVal = convertView.FindViewById<TextView>(Resource.Id.lbview_itemscore);
                    if (scoreVal != null)
                    {
                        scoreVal.SetText("Score: " + score.UserScore, TextView.BufferType.Normal);
                    }
                }
                else
                {
                    TextView name = convertView.FindViewById<TextView>(Resource.Id.lbview_itemname);
                    if (name != null)
                    {
                        name.SetText(score.UserName, TextView.BufferType.Normal);
                    }
                }
                return convertView;
            }
        }
    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.
This is a Organisation (No members)


Comments and Discussions

 
-- There are no messages in this forum --