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.
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'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 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?
I'm trying to develop a simple Turn based multiplayer game in android using Play games services. I followed all the steps in the docs: https://developers.google.com/games/services/android/turnbasedMultiplayer#implementing_auto-matching The only difference is that I don't want my players to be able to invite friends I want it to be purely Automatching. The game is only 2 player and it can only start ONCE 2 players have been matched. My problem is it doesn't seem to be automatching players. I run the app on 2 devices and they never seem to find each other... They both connect to the Play Games Services fine but they both just create a new game. Here is my code after I connect the GoogleApiClient.
#Override
public void onConnected(Bundle bundle) {
pDialog.dismiss();
Toast.makeText(this, "Connected", Toast.LENGTH_LONG).show();
showDialog("Matching players");
Bundle autoMatchCriteria = RoomConfig.createAutoMatchCriteria(1,1,0);
TurnBasedMatchConfig tbmc=TurnBasedMatchConfig.builder().
setAutoMatchCriteria(autoMatchCriteria).build();
Games.TurnBasedMultiplayer.createMatch(mGoogleApiClient,
tbmc).setResultCallback(new MatchInitiatedCallback(this));
}
Here is my MatchInitiatedCallback
public class MatchInitiatedCallback implements
ResultCallback<TurnBasedMultiplayer.InitiateMatchResult> {
private Context context;
public MatchInitiatedCallback(Context c) {
context = c;
}
#Override
public void onResult(TurnBasedMultiplayer.InitiateMatchResult
initiateMatchResult) {
pDialog.dismiss();
if(!initiateMatchResult.getStatus().isSuccess()) {
Toast.makeText(context, "ERROR: " +
initiateMatchResult.getStatus().getStatusCode(), Toast.LENGTH_LONG).show();
return;
}
TurnBasedMatch match = initiateMatchResult.getMatch();
if(match.getData() != null) {
Toast.makeText(context, "Player2 " + match.getData().toString(),
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, "Player1", Toast.LENGTH_LONG).show();
initGame(match);
}
}
}
Both devices show the TOAST that says: "Player1" and call the initGame(match) method which is here:
public void initGame(TurnBasedMatch match) {
String initialise = "initialised";
Games.TurnBasedMultiplayer.takeTurn(mGoogleApiClient,
match.getMatchId(),initialise.getBytes(Charset.forName("UTF-16")),
match.getParticipantId(Games.Players.getCurrentPlayerId(mGoogleApiClient))).
setResultCallback(this);
}
#Override
public void onResult(TurnBasedMultiplayer.UpdateMatchResult
updateMatchResult) {
if(updateMatchResult.getMatch().getStatus() ==
TurnBasedMatch.MATCH_STATUS_AUTO_MATCHING) {
Toast.makeText(this, "Still automatching",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Not automatching", Toast.LENGTH_LONG).show();
}
}
And once again they both Display the TOAST: "Still automatching"
What am I doing wrong. Why don't the devices automatch. Did I skip a step somewhere. Please help.
Try to change your initGame method so it specifies null for the next participant (to let Play Game services find a player for auto-matching):
public void initGame(TurnBasedMatch match) {
String initialise = "initialised";
Games.TurnBasedMultiplayer.takeTurn(
mGoogleApiClient,
match.getMatchId(),
initialise.getBytes(Charset.forName("UTF-16")),
null
).setResultCallback(this);
}
Also make sure to use two different google+ accounts on the two devices.
I tried your code and both devices said "Player1" and "Not automatching"(!). After changing to null, first device said "Player1" and "Still automatching" and second device said "Player2 [B#41b08830"
I think your problem is due to the way invitations as well as auto matching is handled by Play Game services. When hooking up participants to a TurnBasedMultiplayer match, invitations are sent to participants one by one. When you call takeTurn in the initGame method, you must specify the next participant to receive an invitation. When that participant has accepted the invitation, he must call takeTurn and specify the next participant to receive an invitation and so on. If you specify null, it means the next invitation goes to an automatched player.
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);
}
}
});
}