Reputation: 675
I am developing an Android game which uses Google Play Game Services.
When a player reach for example 10000 points an achievement gets unlocked. So when the player reaches 10000 points I call
Games.Achievements.unlock(...)
The question is what to do when the user reaches 10000 points again in another game. Do I have to check if this achievement is already unlocked or can I just call unlock() again?
I know that the Play Services popup is diplayed only when the achievement gets first unlocked. But I am concerned about the quota of api calls. If I for example store the achievement unlock from shared preferences then I would do something like this:
if(myAchievementIsLocked){
Games.Achievements.unlock(...)
}
What are the best practices? I was looking at some samples but didn't find the answers which I was looking for.
Upvotes: 3
Views: 4429
Reputation: 18978
As far as I can tell, unlock()
will check with the local Play Games app first to see if the achievement is already unlocked, and only if it is not will it send the request to the server. This means that calling unlock()
on an already unlocked achievement should not affect any quotas apart from the first time it is called on a device - since the device's instance of the Play Games may not have synced that achievement from the server yet.
On the other hand, it is possible to check the state of all achievements after signing-in and keeping a local copy of their states - which indeed you should do if the player is NOT signed-in (so that you can unlock any achievements earned at the next sign-in). This process is not documented well anywhere except for the API documentation but there are no full examples, so I will give you one here :)
Ensure that you run this method asynchronously (using AsyncTask
or a separate thread) as it will take some time to complete (waiting for responses from the server). Also, do this only when the player is signed in successfully - onSignInSucceeded()
is a good place for it.
Update for Play Service Games 11.8.0
public void loadAchievements() {
mAchievementsClient.load(true).addOnCompleteListener(new OnCompleteListener<AnnotatedData<AchievementBuffer>>() {
@Override
public void onComplete(@NonNull Task<AnnotatedData<AchievementBuffer>> task) {
AchievementBuffer buff = task.getResult().get();
Log.d("BUFF", "onComplete: ");
int bufSize = buff.getCount();
for (int i=0; i < bufSize; i++) {
Achievement ach = buff.get(i);
String id = ach.getAchievementId();
boolean unlocked = ach.getState() == Achievement.STATE_UNLOCKED;
}
buff.release();
}
});
Older Play Service Games
public void loadAchievements() {
boolean fullLoad = false; // set to 'true' to reload all achievements (ignoring cache)
float waitTime = 60.0f; // seconds to wait for achievements to load before timing out
// load achievements
PendingResult p = Games.Achievements.load( playHelper.getApiClient(), fullLoad );
Achievements.LoadAchievementsResult r = (Achievements.LoadAchievementsResult)p.await( waitTime, TimeUnit.SECONDS );
int status = r.getStatus().getStatusCode();
if ( status != GamesStatusCodes.STATUS_OK ) {
r.release();
return; // Error Occured
}
// cache the loaded achievements
AchievementBuffer buf = r.getAchievements();
int bufSize = buf.getCount();
for ( int i = 0; i < bufSize; i++ ) {
Achievement ach = buf.get( i );
// here you now have access to the achievement's data
String id = ach.getAchievementId(); // the achievement ID string
boolean unlocked = ach.getState == Achievement.STATE_UNLOCKED; // is unlocked
boolean incremental = ach.getType() == Achievement.TYPE_INCREMENTAL; // is incremental
if ( incremental )
int steps = ach.getCurrentSteps(); // current incremental steps
}
buf.close();
r.release();
}
See the API documentation for more info on these processes.
So using this method you could create a local copy of the achievements (just alter the internals of the for loop to save the achievement values to some local structure) and refer to it as needed.
Upvotes: 8
Reputation: 769
Calling .unlock(...) on an already unlocked achievement shouldn't be a problem. My guess is there is already some sort of "check if unlocked" handling in the .unlock(...) method.
Upvotes: 1