I am trying to write a custom Activity to show leaderboards on my game in a way that the look and feel is more integrated with the style of my app than the default Leaderboards provided in Google Play Games Services. However, I am having issues retrieving data.
In order to get, for instance, All time Public Top Scores on my global leaderboard, I use the following code:
protected void getTopScores() {
PendingResult<Leaderboards.LoadScoresResult> pendingScores = Games.
Leaderboards.loadTopScores(
googleApiClient,
GLOBAL_LEADERBOARD_ID,
LeaderboardVariant.TIME_SPAN_ALL_TIME,
LeaderboardVariant.COLLECTION_PUBLIC,
25,
true);
processPendingResult(pendingScores);
}
protected void processPendingResult(PendingResult<Leaderboards.LoadScoresResult> pendingScores){
pendingScores.setResultCallback(new ResultCallback<Leaderboards.LoadScoresResult>() {
#Override
public void onResult(Leaderboards.LoadScoresResult loadScoresResult) {
List<LeaderboardScore> leaderboardScores = extractScores(loadScoresResult);
notifyScoresLoaded(leaderboardScores);
}
});
}
protected List<LeaderboardScore> extractScores(Leaderboards.LoadScoresResult loadScoresResult) {
LeaderboardScoreBuffer buffer = loadScoresResult.getScores();
List<LeaderboardScore> leaderboardScores = new ArrayList<>();
for(int i = 0; i < buffer.getCount(); i++){
leaderboardScores.add(buffer.get(i));
}
return leaderboardScores;
}
However, the LeaderboardScoreBuffer is empty. I made sure that my profile is public on the Google Play Games app, but still it doesn't appear.
Besides, if I try to use LeaderboardVariant.COLLECTION_SOCIAL instead, I receive a single value corresponding to the logged in user, but I have some other users play-testing the game who I've added to my Google+ circles.
What am I missing here?
Related
I'm developing an android app with achievements. Is it possible to know if the achievement is unlocked (or if the goal is reached on incremental ones)?
I've found solutions for old implementations which use Games.Achievements and add a callback function, but it is deprecated. This is the code I'm using for unlocking my achievements:
Games.getAchievementsClient(MyActivity.this, acct).unlockImmediate(my_achievement_id));
I'd like to add a listener to know if after the execution of my code the achievement is unlocked.
Solved using load method:
Games.getAchievementsClient(MyActivity.this, acct).load(true).addOnSuccessListener(new OnSuccessListener<AnnotatedData<AchievementBuffer>>() {
#Override
public void onSuccess(AnnotatedData<AchievementBuffer> achievementBufferAnnotatedData) {
AchievementBuffer buffer = achievementBufferAnnotatedData.get();
Achievement achievement;
Iterator<Achievement> iterator = buffer.iterator();
while (iterator.hasNext()) {
achievement = iterator.next();
if (achievement.getAchievementId().equals(myAchievementId) && achievement.getState() == Achievement.STATE_UNLOCKED) {
// The achievement is unlocked
} else {
// The achievement is locked
}
}
}
});
I have it showing fine for one leader board, whatever board, I call it by itself. When I want to show all of the boards I make the call below. It shows the last board called only. I understand this, what I want to know is there a way to just call the leader boards without calling one at a time so the user can compare the scores to each other?
private void signToLeaderBoard() {
if (mGoogleApiClient.isConnected()) {
startActivityForResult(Games.Leaderboards.getLeaderboardIntent(mGoogleApiClient,
context.getString(R.string.leaderboard_game_high_score)), 1);
startActivityForResult(Games.Leaderboards.getLeaderboardIntent(mGoogleApiClient,
context.getString(R.string.leaderboard_total_high_score)),1);
startActivityForResult(Games.Leaderboards.getLeaderboardIntent(mGoogleApiClient,
context.getString(R.string.leaderboard_grab_a_word_count)), 1);
} else {
// make dialog asking to sign in
}
}
Ok, I guess if I spent more time researching for an answer I'd saved myself time asking the question. I have made the changes to the code below. and it works great.
private static final int RC_UNUSED = 5001;
private void signToLeaderBoard() {
if (mGoogleApiClient.isConnected()) {
startActivityForResult(Games.Leaderboards.getAllLeaderboardsIntent(mGoogleApiClient),
RC_UNUSED);
// startActivityForResult(Games.Leaderboards.getLeaderboardIntent(mGoogleApiClient,
// context.getString(R.string.leaderboard_game_high_score)), 1);
} else {
// make dialog asking to sign in
}
}
I'm experiencing a really annoying problem which i didn't have in any previous game which used Google Play Games API.
My game is working well, not yet published, but the API is published, and everything is working, from submitting a score to viewing the leaderboard.
Now, i need to explain the issue first.
My API account on the Google dev Console has two Oauth keys, the debug and the realese. When i finished the game and tried to view the leaderboard, i viewed it without any problem, but when tried to submit a score, the leaderboard opens and then close without showing my local/global score, its like a glitch in the leaderboard.
I've fixed this issue by publishing the Game's Service. Now i'm having the same issue but with the released APK, the isseu was fixed in the Debug, and i've tried the same steps with the released APK, nothing work.
Every Google account will have the same issue viewing the leaderboard if a score has been submitted, no issue will occur when the user try to only view the leaderboard.
Both Debug and Release keys are added to the firebase and Oauth in Google Dev API Control, and already added the emails im using as testers.
Long story short: After submitting a score, the leaderboard won't open (the leaderboards menu will show, but when selecting a leaderboard this glitched closing will happen).
No logcat was caught, and my code is as the following:
Connection code / not needed
To view the leaderboards:
private void OpenLeaderboards() {
if(mGoogleApiClient.isConnected()){
try {
UpdateAddictionLeaderboard(ReturnSavedClick());
startActivityForResult(Games.Leaderboards.getAllLeaderboardsIntent(mGoogleApiClient), REQUEST_LEADERBOARD);
} catch (SecurityException e){
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
}
} else {
isTried = false;
mGoogleApiClient.connect();
}
}
To submit a score:
private void UpdateTopScore(final String LeaderBoard, final String Title, final int mSavedScore, final int mMethod){
Games.Leaderboards.loadCurrentPlayerLeaderboardScore(
mGoogleApiClient,LeaderBoard,
LeaderboardVariant.TIME_SPAN_ALL_TIME,
LeaderboardVariant.COLLECTION_PUBLIC)
.setResultCallback(new ResultCallback<Leaderboards.LoadPlayerScoreResult>() {
#Override
public void onResult(#NonNull Leaderboards.LoadPlayerScoreResult arg0) {
if(isScoreResultValid(arg0)){
long score = arg0.getScore().getRawScore();
Bundle bundle = new Bundle();
bundle.putLong(FirebaseAnalytics.Param.SCORE, score);
bundle.putString(LeaderBoard, Title + " Leaderboard");
mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.POST_SCORE, bundle);
if(mSavedScore > score){
Games.Leaderboards.submitScore(mGoogleApiClient, LeaderBoard, mSavedScore);
} else {
if(mMethod == 0) {
mEditor.putInt(FIRSTSCORE, mSavedScore).apply();
} else {
mEditor.putInt(SECONDSCORE, mSavedScore).apply();
}
}
} else {
Games.Leaderboards.submitScore(mGoogleApiClient, LeaderBoard, mSavedScore);
}
}
});
}
private boolean isScoreResultValid(final Leaderboards.LoadPlayerScoreResult scoreResult) {
return scoreResult != null && GamesStatusCodes.STATUS_OK == scoreResult.getStatus().getStatusCode() && scoreResult.getScore() != null;
}
I'm working on an unpublished google play app which I want to integrate with google play services. In the game, I want to be able to display friends (people in your Google+ circles) who also play the game, so you can send eachother gifts and visit eachother. Seems like loadConnectedPlayers() is ideal for this. Here's how I'm implementing this:
Games.Players.loadConnectedPlayers(mHelper.getApiClient(), true).setResultCallback(new ResultCallback<Players.LoadPlayersResult>()
{
#Override
public void onResult(Players.LoadPlayersResult loadPlayersResult)
{
if(loadPlayersResult != null)
{
if (loadPlayersResult.getStatus().getStatusCode() == GamesStatusCodes.STATUS_OK)
{
if (loadPlayersResult.getPlayers() != null)
{
PlayerBuffer playerBuffer = loadPlayersResult.getPlayers();
Log.d(TAG, "Number of players returned: "+ playerBuffer.getCount());
for (int i =0; i<playerBuffer.getCount(); ++i)
{
// TODO: Stuff with each player
}
playerBuffer.close();
}
}
}
}
}
However, I'm getting a buffer of 0 players returned. The status code for the result is STATUS_OK, meaning there weren't any errors. The two test players I am using both have authorized the game, both have eachother in their circles, and have public permissions for the game. I can't see any issues in my code, so I'm wondering if this an issue with the app not being published yet? If so, how does one test social features on an unpublished app? Any insight would be greatly appreciated.
I am using google play services leaderboard to upload the score of a user. Is there a way to retrieve the score of a user programmatically?
My use case is that I want to run multiplier game where users have level which goes up and down based on their wins/loses (sort of like stackoverflow reputation). I need to retrieve the old score to upload the new modified score.
How can I do that? I didn't see this anywhere on the tutorials.
Thanks
In theory, you can by doing something like that:
gameHelper.getGamesClient().loadLeaderboardMetadata(this, false);
/**
* Called when the data is loaded
*/
#Override
public void onLeaderboardMetadataLoaded(int statusCode, LeaderboardBuffer leaderboards) {
// If the fragment is currently added to an activity
if (isAdded()) {
// There's been an error on leaderboards loading
if (statusCode != GamesClient.STATUS_OK) {
if (leaderboards != null) leaderboards.close();
// Error
return;
}
ArrayList<LeaderboardVariant> variants;
Iterator<Leaderboard> it = leaderboards.iterator();
while (it.hasNext()) {
Leaderboard leaderboard = it.next();
final String id = leaderboard.getLeaderboardId();
variants = leaderboard.getVariants();
// For each leaderboard
for (LeaderboardVariant variant: variants) {
if (variant.getCollection() == LeaderboardVariant.COLLECTION_PUBLIC &&
variant.getTimeSpan() == LeaderboardVariant.TIME_SPAN_ALL_TIME) {
int rawScore = (int) variant.getRawPlayerScore();
}
}
}
}
if (leaderboards != null) leaderboards.close();
}
... but the reality is that you can't because the data is outdated, see here: Play games loadLeaderboardMetadata() returns outdated data
It probably is a bug, but as there's no place to submit play-games bugs...
Anyway, why don't you keep a local copy of the scores you submitted? Wouldn't it be the easier way to do it?
[UPDATE]
It seems that you can achieve what you want by using the loadCurrentPlayerLeaderboardScore instead of the loadLeaderboardMetadata method. That one doesn't seem to return outdated data. Check it here
In case someone is still looking for the solution, according to the latest android releases,the method described in the above answer is deprecated now.
The Latest way to do it is as follows:
private LeaderboardsClient mLeaderboardsClient = Games.getLeaderboardsClient(this, googleSignInAccount);
private void updateLeaderboards(final String leaderboardId) {
mLeaderboardsClient.loadCurrentPlayerLeaderboardScore(
leaderboardId,
LeaderboardVariant.TIME_SPAN_ALL_TIME,
LeaderboardVariant.COLLECTION_PUBLIC
).addOnSuccessListener(new OnSuccessListener<AnnotatedData<LeaderboardScore>>() {
#Override
public void onSuccess(AnnotatedData<LeaderboardScore> leaderboardScoreAnnotatedData) {
if (leaderboardScoreAnnotatedData.get() == null)
mLeaderboardsClient.submitScore(leaderboardId, 1);
else {
long currentscore = leaderboardScoreAnnotatedData.get().getRawScore();
mLeaderboardsClient.submitScore(leaderboardId, currentscore + 1);
}
}
});
}