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
}
}
}
});
Related
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 implement Facebook sharing in my game using Unity 3D + Facebook Unity SDK. But when I tried testing to post to my wall, this error shows up: "We are Sorry, this post is no longer available. It may have been removed." Can anybody help me? Thanks in advance.
BTW, here's my code:
using UnityEngine;
using System.Collections;
public class FacebookController : MonoBehaviour {
public bool isUsingFacebook = true; //Are we using Facebook SDK? This variable is only
//Feed parameters.
private string link = "market://details?id=com.LaserCookie.Queue"; //The link that will show the user the game's google play store address
private string linkName = "Queue"; //The link name
private string linkCaption = "Wow this game is great! 10/10 must play!"; // The caption of the link
private string linkDescription = "I achieved the score of " + PlayerController.instance.score.ToString() + "! Try to beat me if you can!"; //The description of the link
private string picture = "http://www.drycreekequestriancenter.com/testImage.jpeg"; //This is the image / game icon for the link. For now, it's shamelessly got from a random source. Thank you, random citizen...
void Awake()
{
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
//Init FB
private void Init()
{
if (!FB.IsInitialized)
{
FB.Init(OnInitComplete, OnHideUnity);
}
}
//Callback that will be called when the initialization is completed
private void OnInitComplete()
{
Debug.Log("FB.Init completed: Is user logged in? " + FB.IsLoggedIn);
//Check if we are logged in.
//If not, we will log in.
//If we are, post status.
if (!FB.IsLoggedIn)
{
LoginWithPublish();
}
else
{
PostImpl();
}
}
//Callback that will be called when the game is shown / not
private void OnHideUnity(bool isGameShown)
{
Debug.Log("Is game showing? " + isGameShown);
}
//Post to Facebook. This is the only exposed method because we only use this to post to Facebook.
//The initialization and login will be called when needed.
//It will first detect whether or not we have been initialized. And will init if we haven't.
//Then it will check whether or not we have been logged in with publish. And will log in if not.
public void PostToFacebook()
{
//Are we using facebook SDK?
if (isUsingFacebook)
{
if (!FB.IsInitialized) //Check for initialization
{
Init();
}
else if (!FB.IsLoggedIn) //Check for login
{
LoginWithPublish();
}
else //Post if we are already initia;ized and logged in
{
PostImpl();
}
}
}
//The true implementation of the posting
private void PostImpl()
{
FB.Feed("",link, linkName,linkCaption,linkDescription,picture);
}
//Login to Facebook with publish
private void LoginWithPublish()
{
// It is generally good behavior to split asking for read and publish
// permissions rather than ask for them all at once.
//
// In your own game, consider postponing this call until the moment
// you actually need it.
FB.Login("publish_actions", LoginCallback);
}
//Login callback
void LoginCallback(FBResult result)
{
if (result.Error != null)
{
Debug.Log( "Error Response:\n" + result.Error );
//TODO: Retry login if we have error? Or do we display a pop up?
}
else if (!FB.IsLoggedIn)
{
Debug.Log( "Login cancelled by Player" );
//TODO: Do we display a pop up?
}
else
{
Debug.Log( "Login was successful!" );
PostImpl();
}
}
}
You need to add Key Hash for FB application.
Go to My Apps, select you application, open Setting tab, add platform for android, and add you key hash.
check this link out
Setting a Release Key Hash
I've fixed the issue. It turns out it's because I used my still in development google store address as the link. I thought it would be automatically recognized regardless of my app is live or not. Thank you anyway. :)
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);
}
}
});
}
I have some incremental achievements on my game and i want to check if one of them is already unlocked. How can i do that?
Originaly i used this method:
getGamesClient().incrementAchievement(achievement, increment);
Then i tried to use this:
mHelper.getGamesClient().incrementAchievementImmediate(new OnAchievementUpdatedListener()
{
#Override
public void onAchievementUpdated(int statusCode, String achievementId)
{
// TODO: Check if the achievement got unlocked
}
}, achievement, increment);
Is this the right way to do what i want? Is there a better way?
I only got two statusCode values on my tests.
Value: 5 = STATUS_NETWORK_ERROR_OPERATION_DEFERRED
Value: 0 = STATUS_OK
Can some one help me with this?
Thanks
Declare this inner class:
class AchievementClass implements ResultCallback<Achievements.LoadAchievementsResult> {
#Override
public void onResult(LoadAchievementsResult arg0) {
Achievement ach;
AchievementBuffer aBuffer = arg0.getAchievements();
Iterator<Achievement> aIterator = aBuffer.iterator();
while (aIterator.hasNext()) {
ach = aIterator.next();
if ("The Achievement Id you are checking".equals(ach.getAchievementId())) {
if (ach.getState() == Achievement.STATE_UNLOCKED) {
// it is unlocked
} else {
//it is not unlocked
}
aBuffer.close();
break;
}
}
}
}
And use it like so:
Games.Achievements.load(ApiClient, false).setResultCallback(new AchievementClass());
This will get achievement data for the currently signed in player, go through all the achievements, and when it reaches the achievement you're concerned with, it will check if it is unlocked.