[Huawei Developers] Freemind R:
More information like this, you can visit HUAWEI Developer Forum​

Introduction

Huawei Game service provides a centralized place for you to manage game services and configure metadata for authorizing and authenticating your game. Using Huawei game service, developer can access range of capabilities to help develop your games more efficiently.

Features

1. Developers can promote their game efficiently and quickly.

2. Developers can easily build the foundation of game by implementing features like achievements and events.

3. Developers can perform in-depth operations tailored to their game and their users.

In this article, we will implement leaderboard feature provided by Huawei game service in Tic tac toe game.

To understand event feature provided by Huawei game service, please refer my last article.

Prerequisites

1. Developer has created an application on App Gallery Connect. Follow Creating an App.

2. Integrating app gallery connect SDK. Please refer to AppGallery Connect Service Getting Started.

3. Developer has integrated Huawei Account kit. Follow this tutorial to integrate account kit.

4. HUAWEI mobile phone with HMS Core 4.0.0.300 or later installed.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618070140.92092760100629623808428454256332:50510729055018:2800:F1750F7780372C4D0F8569359D22312A3FC1D7EE5A7B2EEDD05F6AB8A4C70C87.jpg"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618070140.92092760100629623808428454256332:50510729055018:2800:F1750F7780372C4D0F8569359D22312A3FC1D7EE5A7B2EEDD05F6AB8A4C70C87.jpg[/IMG]​

Setup:

1. Enable Huawei Game service in Manage APIS. Please refer to Service Enabling.

2. Add appgallery connect plug-in in app-level build.gradle

apply plugin: 'com.huawei.agconnect'

3. Add following dependencies in app-level build.gradle and click on Sync Now and wait till synchronization is done.

dependencies {
implementation 'com.huawei.hms:base:4.0.4.301'
implementation 'com.huawei.hms:hwid:4.0.4.300'
implementation 'com.huawei.hms:iap:4.0.4.300'
implementation 'com.huawei.hms:game:4.0.3.301'
}

Initialization

Once Initial set up is done, let’s implement Huawei game service in Tic tac toe game

1. Add the following code in onCreate() method of Application class.

public class GameServiceApplication extends Application {

@Override
public void onCreate() {
super.onCreate();
HuaweiMobileServicesUtil.setApplication(this);
}

@Override
public void onTerminate() {
super.onTerminate();
}
}

2. To initialize the game

private void init() {
JosAppsClient appsClient = JosApps.getJosAppsClient(this, null);
appsClient.init();
Log.i(TAG, "initialization success");

}

Sign in

1. When app is launched, Huawei sign-in page is displayed.

2. User enters Huawei Huawei ID and password to sign in.

3. After a successful sign in, the app obtains player information corresponding to Huawei ID.

Please refer to this article for sign in implementation.

Game Leaderboards

The term Leaderboard is often used in gaming platform to signify rank among people who play various titles. Players can be ranked against other players based on their skills. Overall, leaderboards can provide an incentive for players to improve as they give many a sense of superiority or accomplishment.

Creating a Leaderboard in AppGallery Connect

1. Sign in to AppGallery Connect and select My apps.

2. Select an app from the app list to create an event.

3. Click the Operate tab and go to Products > Leaderboard. Click Create.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618054153.66671109726034146459452683822389:50510729055018:2800:428EF507C81301E5FFA715B56B580C77947C346D3B5BCD8B4DF13CAB17C2D027.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618054153.66671109726034146459452683822389:50510729055018:2800:428EF507C81301E5FFA715B56B580C77947C346D3B5BCD8B4DF13CAB17C2D027.png[/IMG]​

4. Configure the leaderboard information and click Save.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618054338.42168493686807350487542334412422:50510729055018:2800:23844A852041E6052F5A2C9DBA3B41220380C4E9E526C00D82AE4504558A3BB3.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618054338.42168493686807350487542334412422:50510729055018:2800:23844A852041E6052F5A2C9DBA3B41220380C4E9E526C00D82AE4504558A3BB3.png[/IMG]​

5. Check your leaderboard ID on the event list and properly save the ID for development.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618055551.17485489430882469286231959750589:50510729055018:2800:7C2F2AD54588FF5CF71C8692D95ED78077CCCC8D037C15CBDBC60D44EE5B473E.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618055551.17485489430882469286231959750589:50510729055018:2800:7C2F2AD54588FF5CF71C8692D95ED78077CCCC8D037C15CBDBC60D44EE5B473E.png[/IMG]​

Development

To initialize leaderboard , we need to obtain instance of RankingsClient

RankingsClient client = Games.getRankingsClient(this, mAuthHuaweiId);

mAuthHuaweiId is obtained during sign in.

2. To allow player's score to be displayed on leaderboard, call setRankingSwitchStauts() method, and pass 1 as parameter. the player's leaderboard switch is set to 0

private void enableRankingSwitchStatus (int status) {
Task<Integer> task = rankingsClient.setRankingSwitchStatus(status);
task.addOnSuccessListener(new OnSuccessListener<Integer>() {
@Override
public void onSuccess(Integer statusValue) {
// success to set the value,the server will reponse the latest value.
Log.d(TAG, "setRankingSwitchStatus success : " +statusValue) ;
}
});
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// errCode information
if (e instanceof ApiException) {
String result = "Err Code:" + ((ApiException) e).getStatusCode();
Log.e(TAG , "setRankingSwitchStatus error : " + result);
}
}
});
}

3. To check the leaderboard switch settings

Task<Integer> task = rankingsClient.getRankingSwitchStatus();
task.addOnSuccessListener(new OnSuccessListener<Integer>() {
@Override
public void onSuccess(Integer statusValue) {
//success to get the latest value
}
});
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {

// errCode information
if (e instanceof ApiException) {
String result = "err :" + ((ApiException) e).getStatusCode();
}
}
});

onSuccess() will return either 0 or 1. 0 indicates leaderboard is not enabled for players. If 1 is returned, your game submits the updated score of the player.

4. To submit the score

private void submitRanking(int score) {

rankingsClient.submitRankingScore(LEADERBOARD_ID, score);
}

LEADERBOARD_ID indicates the ID of the leaderboard which is generated while defining the event in AppGallery connect.

5. To obtain leaderboard, we need to call getCurrentRankingSummary(id, isRealTime)

Task<Ranking> task = rankingsClient.getRankingSummary(id, isRealTime);
task.addOnSuccessListener(new OnSuccessListener<Ranking>() {
@Override
public void onSuccess(Ranking s) {
showLog( " success. ");
if (task.getResult() == null) {
Log.d(TAG, "Ranking result is null");
tvLeaderboard.setText("Ranking result is null");
return;
}

Ranking ranking = task.getResult();
StringBuffer buffer = new StringBuffer();
buffer.append("-------Ranking-------\n");
if (ranking == null) {
buffer.append("ranking is null");
} else {

buffer.append("\n DisplayName:" + ranking.getRankingDisplayName());

iv.setVisibility(View.VISIBLE);
Glide.with(this).load(ranking.getRankingImageUri()).into(iv);

buffer.append("\n ScoreOrder:" + ranking.getRankingScoreOrder());

if (ranking.getRankingVariants() != null) {
buffer.append("\n Variants.size:" + ranking.getRankingVariants().size());
if (ranking.getRankingVariants().size() > 0) {
showRankingVariant(ranking.getRankingVariants() , buffer);
}
}
}
}
});

isRealTime is a Boolean which indicates whether to obtain result from huawei server (true) or local cache.

id indicates the ID of the leaderboard which is generated while defining the event in AppGallery connect.

6. To display only specified number of top rankings, we need to call getRankingTopScores(id, timeDimension, maxResult, offsetPlayerRank, pageDirection)

Task<RankingsClient.RankingScores> task
= rankingsClient.getRankingTopScores(id, timeDimension, maxResults, offsetPlayerRank, pageDirection);
task.addOnSuccessListener(new OnSuccessListener<RankingsClient.RankingScores>() {
@Override
public void onSuccess(RankingsClient.RankingScores s) {
showLog(" success. ");

Ranking ranking = task.getResult().getRanking();
List<RankingScore> scoresBuffer = task.getResult().getRankingScores();

for (int i = 0; i < scoresBuffer.size(); i++) {
printRankingScore(scoresBuffer.get(i), i);
}

}
});

private void printRankingScore(RankingScore s, int index) {
StringBuffer buffer = new StringBuffer();
buffer.append("------RankingScore " + index + "------\n");
if (s == null) {
buffer.append("rankingScore is null\n");
return;
}

String displayScore = s.getRankingDisplayScore();
buffer.append(" DisplayScore: " + displayScore).append("\n");

buffer.append(" TimeDimension: " + s.getTimeDimension()).append("\n");
buffer.append(" RawPlayerScore: " + s.getPlayerRawScore()).append("\n");
buffer.append(" PlayerRank: " + s.getPlayerRank()).append("\n");

String displayRank = s.getDisplayRank();
buffer.append(" getDisplayRank: " + displayRank).append("\n");

buffer.append(" ScoreTag: " + s.getScoreTips()).append("\n");
buffer.append(" updateTime: " + s.getScoreTimestamp()).append("\n");

String playerDisplayName = s.getScoreOwnerDisplayName();
buffer.append(" PlayerDisplayName: " + playerDisplayName).append("\n");
buffer.append(" PlayerHiResImageUri: " + s.getScoreOwnerHiIconUri()).append("\n");
buffer.append(" PlayerIconImageUri: " + s.getScoreOwnerIconUri()).append("\n\n");
Log.d(TAG , buffer.toString());
tvLeaderboard.setText(buffer.toString());
}

id indicates the ID of the leaderboard which is generated while defining the event in AppGallery connect.

timeDimension indicates time frame. Provide 0 for daily, 1 for weekly, 2 for all time .

maxResults indicates maximum number of records on each page. The value is an integer ranging from 1 to 21.

offsetPlayerRank specifies rank by offsetPlayerRank.For example, if offsetPlayerRank is set to 5 and pageDirection is set to 0, one additional page of scores starting from the fifth rank downwards will be loaded.

pageDirection indicates data obtaing direction. Currently 0 is supported, indicating data of next page is obtained.

7. To display the score of current player , we need to call getCurrentPlayerRankingScore(id, timeDimension)

Task<RankingScore> task = rankingsClient.getCurrentPlayerRankingScore(id, timeDimension);

task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
showLog(" failure. exception: " + e);
}
});
task.addOnSuccessListener(new OnSuccessListener<RankingScore>() {
@Override
public void onSuccess(RankingScore s) {
showLog(" success. ");
StringBuffer buffer = new StringBuffer();
if (task.getResult() == null) {
buffer.append("RankingScore result is null");
return;
}
buffer.append("=======RankingScore=======\n");
RankingScore s = task.getResult();
printRankingScore(s, 0);

}
});
task.addOnCanceledListener(new OnCanceledListener() {
@Override
public void onCanceled() {
showLog(method + " canceled. ");
}
});

private void printRankingScore(RankingScore s, int index) {
StringBuffer buffer = new StringBuffer();
buffer.append("------RankingScore " + index + "------\n");
if (s == null) {
buffer.append("rankingScore is null\n");
return;
}

String displayScore = s.getRankingDisplayScore();
buffer.append(" DisplayScore: " + displayScore).append("\n");

buffer.append(" TimeDimension: " + s.getTimeDimension()).append("\n");
buffer.append(" RawPlayerScore: " + s.getPlayerRawScore()).append("\n");
buffer.append(" PlayerRank: " + s.getPlayerRank()).append("\n");

String displayRank = s.getDisplayRank();
buffer.append(" getDisplayRank: " + displayRank).append("\n");

buffer.append(" ScoreTag: " + s.getScoreTips()).append("\n");
buffer.append(" updateTime: " + s.getScoreTimestamp()).append("\n");

String playerDisplayName = s.getScoreOwnerDisplayName();
buffer.append(" PlayerDisplayName: " + playerDisplayName).append("\n");
buffer.append(" PlayerHiResImageUri: " + s.getScoreOwnerHiIconUri()).append("\n");
buffer.append(" PlayerIconImageUri: " + s.getScoreOwnerIconUri()).append("\n\n");
Log.d(TAG , buffer.toString());
tvLeaderboard.setText(buffer.toString());
}

id indicates the ID of the leaderboard which is generated while defining the event in AppGallery connect.

timeDimension indicates time frame. Provide 0 for daily, 1 for weekly, 2 for all time .

Screenshots

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618065327.64846993817427472633246938345914:50510729055018:2800:5BDE5DFDA1FFCF1C3CD0EA8FB92B3AF295DC3084D34EE2BD1512C27636070A74.jpg"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618065327.64846993817427472633246938345914:50510729055018:2800:5BDE5DFDA1FFCF1C3CD0EA8FB92B3AF295DC3084D34EE2BD1512C27636070A74.jpg[/IMG]

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618065335.92220153261702893080290058441386:50510729055018:2800:7DD18CBC775EDB22D679F5700941AE94B7B4D3C22D07862ABAC4FD27BB908D47.jpg"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618065335.92220153261702893080290058441386:50510729055018:2800:7DD18CBC775EDB22D679F5700941AE94B7B4D3C22D07862ABAC4FD27BB908D47.jpg[/IMG]

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618065344.00308092791472216662719136695093:50510729055018:2800:B25142265811EB8DBF854112120E657D6FE6C99EE049502164C354CB0C26A1E9.jpg"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618065344.00308092791472216662719136695093:50510729055018:2800:B25142265811EB8DBF854112120E657D6FE6C99EE049502164C354CB0C26A1E9.jpg[/IMG]

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618065549.75966390470284437301742414452722:50510729055018:2800:18529C436CCBA717BA76F1900A1773173B57E2DFC6EBB4C87874BEC173BA2248.jpg"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618065549.75966390470284437301742414452722:50510729055018:2800:18529C436CCBA717BA76F1900A1773173B57E2DFC6EBB4C87874BEC173BA2248.jpg[/IMG]

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618065555.32042090923139384936014152722541:50510729055018:2800:4CE326BFA93533667DBD183F9AD8D56CC143F7D243347BEF1E97C198DD1C1863.jpg"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/940/588/2640091000001940588.20200618065555.32042090923139384936014152722541:50510729055018:2800:4CE326BFA93533667DBD183F9AD8D56CC143F7D243347BEF1E97C198DD1C1863.jpg[/IMG]​