I want to use cloud storage for my game for 3 platforms. So you can play on the web, then continue on your mobile for example.
I am looking at the API documentation, and I can only see support for getting snapshots. I want to create a new snapshot and then save it. It shows how to do this for mobiles but not web?
Surely the service doesn't limit you in this way. It would destroy the user experience.
Thanks,
Shaun.
Unfortunately as you know there is no API to write a Saved Game using the web API. If you want to support web and mobile game saving, you'll have to implement it yourself. An easy way to do that is to use the Application Data Folder for Google Drive. This allows your application to store data in a hidden directory on the player's drive account. This API is also available on Android (https://developers.google.com/drive/android/appfolder) and even iOS (https://developers.google.com/drive/ios/).
What you miss out on by not using the Play Game Services is primarily some caching logic on the client and the user interface for selecting the snapshot. If you eliminate the caching logic, you also eliminate the need for complex conflict resolution (assuming you use a 'last write wins' approach)
At a high level the steps would be:
Create a new application on the Google API console for the platforms you want to support.
Implement login in your game (this would be the same as if you are using Saved Games via Play Game Services.
Use the specific client Id for the correct platform to access the app data for your application.
Implement a UI to select an existing snapshot or create a new one.
Here, you create the savegame by name if not exists:
Snapshots.OpenSnapshotResult open = Games.Snapshots.open(
mGoogleApiClient, name, create).await();
if (!open.getStatus().isSuccess()) {
throw new RuntimeException("or whatever");
}
Snapshot snapshot = open.getSnapshot();
snapshot.getSnapshotContents().writeBytes(mySaveGame);
create is a boolean telling you want to create a new one when it does not exist.
name is the savegame name.
mySaveGame is my binary blob to be stored.
As I understand your question, there are the following scenarios possible in your example
Player playing on mobile, saved the game, accessed the game next time on mobile
Player playing on mobile, saved the game, accessed the game next time on Web
Player playing on Web, saved the game, accessed the game next time on mobile
Player playing on Web, saved the game, accessed the game next time on Web
I am assuming your game has complex logic requiring client-server implementation. And given the discussion above, I am assuming you want to save the game in Google Play Game Services (as opposed to your own web Server).
In this case, for scenario 1 and 3 above, you will retrieve the Snapshot as demonstrated in the answer by eduyano earlier.
Snapshots.OpenSnapshotResult open = Games.Snapshots.open(
mGoogleApiClient, name, create).await();
if (!open.getStatus().isSuccess()) {
throw new RuntimeException("or whatever");
}
Snapshot snapshot = open.getSnapshot();
snapshot.getSnapshotContents().writeBytes(mySaveGame);
However, for scenario 2 and 4 above, you will need to use the REST API services for 'Play Games Services for Web'.
So first you will have to make the HTTP request to get the Player ID
GET https://www.googleapis.com/games/v1/players/playerId
Subsequently, you will need to know the Snapshot IDs saved against this Player. So make another HTTP request
GET https://www.googleapis.com/games/v1/players/playerId/snapshots
For the Snapshot ID retrieved, make the HTTP request to retrieve the relevant Snapshot. It will need authorisation. At this point a JSON object corresponding to the saved Snapshot will be returned.
I hope this helps... And I am assuming you will know how to load the snapshot once the JSON object is returned. Feel free to ask for further clarification.
More details at https://developers.google.com/games/services/web/api/snapshots
Related
I have a storybook kind of app, when people bought extra story i need somehow to download the extra content as a additional download. can some one elaborate how can i do that from unity (cause i'm using unity to build the app). how to bundle the assets and how to make it as a extra download.
Let's say you have a button that is greyed out for not containing the data.
That button contains a script checking if there is data at a location.
The user purchases the item and then starts the download. The data are stored at the location where the button will search for most likely at Application.persistentDataPath.
The actual data are stored on your server at a url. Most likely a secured url requiring a login system (could be Azure or AWS).
Next time the button is started it will look at the location and find the data. It is now active.
Downloading could be made easy with AssetBundle so you can download a whole scene into it.
https://docs.unity3d.com/Manual/AssetBundlesIntro.html
I am creating one Google Fit compatible App. My objective is to store Google Fit data using HistoryApi, and provide kind of Back Up- Restore functionality to user. If user buys new Android devices then he/she should be able to BackUp(sync) old data using his/her account.
I need to use Custom Data Type, as Public Data Types doesn't meet my requirements.
Everything works perfect, I am able to insert data and read data using History Api.
But When I try to read data from Another Android device using same Google Account then data is not available to read there.
My problem seems similar to this Custom DataTypes not synching between devices
This statement from Google Fit Document is not clear to me.
Custom data types are not available to use in other apps. Only the app
that creates a custom fitness data type can use it
source : CustomDataType
Q-1) What does it really means ? If I have an app GoogleFitDemo installed on multiple Android devices, then is it possible to sync data between this same app between multiple Android devices ?
Q-2)Is it improper way to store and backup data using Google fit ?
Update:
Finally, I found that Custom Data Type can also be synced normally, same as other Public Data Types. I had the sync issue as mentioned by #Ifor. Sync functionality is still buggy. In some scenarios sync stops working, and sometimes synced data is inconsistent across multiple devices.
1). My understanding is that same app same account but different devices it should work. Having said that sync is notoriously slow (hours days...) and has been buggy so it may be hard to tell if you have it right or not.
2) There are better backup methods... But if the data fits in with the rest of the stuff Google Fit is about and is not too big then it's probably ok.
Hi I'm using the Google Drive Api to store a database using the AppDataFolder facility. I have a test app running successfully on one device. I am able to upload/update/delete/download the database file and reintegrate it into the program with no problems.
The issue I'm having is when I want to share this database with another device running the same app, then things don't work as expected. Example device A I upload the database, device B - I want to download the database but no file is found (this delay can vary greatly from seconds to hours). Reason for this - when using the Api it decides when it wants to 'sync' data, as it is queued rather than being instantaneously uploaded. So when used on one device this is not a problem because it takes either the 'synced' file from the cloud storage, or file waiting to be synced.
I have tried various things like trying to list all AppDataFolder files or retrieving metadata through a query with searchable filters before making a request to update/delete etc.. However I can't get it to work as desired fundamentally it chooses when to sync.
So my actual question is: How can I force Google Drive to sync my file when I want it to i.e. every time a request is made, so that synchronisation is achieved across multiple devices using the same app. There must be an answer as I would think this is quite a fundamental reason why you would use the AppDataFolder is the first place.
Thanks in advance
EDIT/UPDATE:
I have been able to find an option in the Api to 'sync' the drive content using this code:
// try to sync
Drive.DriveApi.requestSync(mGoogleApiClient).setResultCallback(new ResultCallback<com.google.android.gms.common.api.Status>() {
#Override
public void onResult(com.google.android.gms.common.api.Status status) {
if (!status.getStatus().isSuccess()) {
Log.e("SYNCING", "ERROR" + status.getStatusMessage());
} else {
Log.e("SYNCING", "SUCCESS");
// execute async task to list AppFolderContents
new AppFolderContentsAsyncTask(getActivity()).execute();
}
}
});
This works well for 3/4 attempts in quick succession, however I reach a syncing limit and status message:
ERRORSync request rate limit exceeded.
Is there any way to increase the request rate as this is not really desirable if I have to have a app that prompts the user 'please try again later to sync - not sure how long you'll have to wait until you can though!'
SOLUTION - OF SORTS, AND MY THOUGHTS (for what its worth)
The solution that I am going for (after emailing a app dev whose published a drive app that synchronizes without problems) is to use the Drive REST Api, rather than the newer (and Google preferred) Drive API. I tried limiting the 'requestSync' to only when the user navigated to a fragment with the Drive options (rather than every file transaction). However this would probably solve the requestSync rate limit for the most part, but it still could hit that limit. Also if multiple devices are running the app, and linked to the same Drive account were both syncing/uploading/deleting files at the same time in the app then there is a possibility of losing synchronization - maybe a rare scenario, but still possible. I don't feel that making a user wait to sync files is a viable option in terms of user experience or app design.
Curious though - The actual Drive app lets you refresh (requestSync?) as many times as you like. I created 20 folders on the web interface in quick succession, after each folder was created I refreshed the Drive app on my phone and it synced all 20 times. It seems Google understands the importance of synchronization, but chooses to make this quite difficult ensure this in their new Drive API. As already stated uploading files to the cloud storage happens usually instantly (it is queued, however if you have connectivity it happens almost straight away). I would have thought that this is the costly transaction in terms of moving data/updating drive contents, rather than just querying for synchronization of files. However you can keep adding files to your your drive app one at a time, and it uploads them one at a time almost instantly - where as you request sync more than 4 times in 30 seconds and it then fails and you have to 'cool off' for a while.
I'm very new to programming/Android in general - as soon as I learn something new, I realize how little I actually know, so if their is a better solution out there using the Drive API (rather than REST API) I'd very much welcome it.
DriveApi#requestSync will let you request a "sync down" from the server to the device. This way, on the second device you should be able to see the content uploaded from the first device. However, the calls to request sync are rate limited (per-device) to avoid abuse and guarantee a reasonable amount of data usage by the Drive API. You should ideally call request sync only when you need to. There's no way to increase the rate limit.
Regarding upload completion, after committing an upload, you shouldn't use request sync since that won't help you (it only syncs down but not up). The actual upload will happen as soon as possible (based on the device's connectivity and the preferences specified by your app through DrivePreferencesApi, which by default are unrestricted).
If you want to know when the actual upload happened, you can use CompletionEvents. This way you can test your app with more insights on what's actually going on.
According to the GPGS website-
Use the client libraries. The mobile client libraries employ a number
of strategies to reduce the calls you make to the service. For
instance, achievement and leaderboard data is cached, so a user can
view their achievements as often as they'd like without requiring the
service to make multiple calls. Both the Android and iOS client
libraries will know not to send a player's score to the server if
your score isn't as good as one you recently submitted. The Android
library also automatically combines frequent achievement increment
calls when it detects that you are being rate limited.
I'm specifically interested in 'viewing achievements without requiring the service to make multiple calls'. As far as I can see, the best way to do this would be to use the OnAchievementsLoadedListener and get a reference to the achievementBuffer.
Will that buffer be updated when an achievement state is changed and is it okay not to close that buffer immediately? If not, the OnAchievementsUpdatedListener does not pass a buffer or even and indiviudal achievement reference so how would I get the updated collection of achievements?
I found my answer here:
https://developer.android.com/reference/com/google/android/gms/games/GamesClient.html#loadAchievements%28com.google.android.gms.games.achievement.OnAchievementsLoadedListener,%20boolean%29
Set forceReload argument to false to gain the advantages of data-caching :)
I'd like to have an android app that would allow a given number of users to be "logged in" either as a player or ref. The players would just be able to increment their score, while the ref would have a screen that shows all player scores and alerts the ref with a tone/vibration when a player reaches a target score.
I have no android dev experience and in a perfect world I would just find an app that does something similar to this that I can just tweak. I'm not sure if this kind of functionality would depend on having a server or at all where to begin on learning the knowledge that would be necessary to create such an app.
Kind of a vague question... you will however need a server to keep track of all the scores - for example you can have an SQL database that contains all the users/scores and all the Android app is tell the server which user's count to increment.
Another alternative would be to use the Google Drive APIs - you can probably use forms or something to increment counts while the "ref" would have full access to the document.