I was so excited to hear about the turn-based match in the new google game services but at the same time a bit disappointed to not see the "flow" of turn based game especially cards games will have hard time to fit the design into the "expected flow" by google turn base. One of the issues I found and I really hope that I missunderstood it in the documentation is updating the game state
According to the documentation, if a user takes a turn (lets say throw a an Ace of Heart) then this will information will be rendered only on the device of the next player. Is there no way to update this information on all the participants devices at the same time? Otherwise the 6th player will have to wait for 5 turns before seeing a movement on his screen!
Any idea?
From the Saving Game State guide:
Call takeTurn() and pass in your game state data as the matchData parameter.
If the call is successful, Play Games services notifies other participants in the match about the update and makes the match data available on all participant devices.
Your game can then call getData() to retrieve the updated game state.
So it appears all participants get the updated state.
I know this thread is old but anyway I'll put my two cents.
If you want be notified whenever any participant in the match takes a turn, attach a OnTurnBasedMatchUpdateReceivedListener to your activity. Whenever the match is updated following a player's turn, your listener is notified via the onTurnBasedMatchedReceived() callback.
You can attach a OnTurnBasedMatchUpdateReceivedListener like this.
public class TurnBasedActivity extends BaseGameActivity implements OnTurnBasedMatchUpdateReceivedListener{
#Override
public void onSignInSucceeded() {
Games.TurnBasedMultiplayer.registerMatchUpdateListener(getApiClient(), this);
}
#Override
public void onTurnBasedMatchReceived(TurnBasedMatch match) {
Toast.makeText(this, "A match was updated.", TOAST_DELAY).show();
}
#Override
public void onTurnBasedMatchRemoved(String matchId) {
Toast.makeText(this, "A match was removed.", TOAST_DELAY).show();
}
}
}
I took the information from here https://developers.google.com/games/services/android/turnbasedMultiplayer#taking_the_first_turn
Hope it helps somebody else.
Related
Updated to describe the requested code; the updates are at the end.
I'm trying to do something that seems like it should be simple but the Android Life Cycle doesn't seem to be working as described. I expect this is a misunderstanding on my part, not a bug in Android!
I am new to Android and am just getting familiar with the Android Life Cycle after developing Java apps for Windows so I'm still struggling with a lot of new ideas, especially the Life Cycle.
I have nearly finished my first app, which is based on a RecyclerView. It shows a bunch of sales records (each representing one sale) of a small company. Users can click on a FloatingActionButton to report a new sale or click on edit or remove icons on the individual records to change the details of a sale or delete it entirely. Each of these things has its own activity. Also, there is a SettingsActivity to show settings.
One of the settings lets the user select from amongst three different date formats for displaying the date of the sale. When I back out of Settings (by hitting the back button), I want to see the visible rows using the newly-changed date format immediately but this is NOT happening. Up until now, I would just click on the buttons to take me to one of the other activities, then click the cancel button when I get there; on returning to my main activity, I would see the new date format.
I don't feel my user should have to go to that other activity; simply returning from Settings should change the dates immediately. I started looking at the Android Life Cycle. As I read the documentation, I should be overriding the onResume() method and issuing a notifyDataChanged() to the Adapter that controls the RecyclerView to get it to rebind the visible rows, using the new date format.
Unfortunately, that has no effect whatever that I can see. Here's my onResume:
#Override
protected void onResume() {
super.onResume();
mAdapter.notifyDataSetChanged();
}
Am I doing the notifyDataSetChanged() in the wrong method? If not, why doesn't it work? If it is the wrong method, which method should I be overriding?
Is there any particularly good text or video tutorial explaining the Life Cycle that I should be reading or viewing?
Updates
The date format is set in my SettingsActivity, which is the default one provided in the SettingsActivity template, tailored to meet my needs. All I've touched is the General settings. I replaced all of the ones from the template with six of my own settings. One is called Date format and defaults to YYYY-MM-DD; there are two other choices.
My main activity, which is the one that invokes SettingsActivity via a menu option, gets the value of the date format from the default SharedPreferences. This is because I don't want to look up the value of the Date format once for every row in the ArrayList but just once for all the rows in the ArrayList. I pass the value of the Date format to the Adapter via its constructor. The format gets used in OnBindViewHolder() to control the appearance of the date on the various sales records.
Define a set method to your adapter,
public class MyAdapter extends RecyclerView.Adapter<AdapterContactList.ViewHolder> {
private String dateFormat;
.....
public void setDateFormat(String dateFormat) {
this.dateFormat = dateFormat;
}
}
After user change the dateformat; set it to your adapter, then notify datas for change. That means, you need set new dateformat before notifyDataSetChanged method; because adapter doesn't know the new value.
#Override
protected void onResume() {
super.onResume();
String newDateFormat = getFromSharedPreferencesOrInstantly();
mAdapter.setDateFormat(newDateFormat);
mAdapter.notifyDataSetChanged();
}
I'm exploring the new Google Awareness API, more precisely the "get weather" one.
https://developers.google.com/awareness/android-api/snapshot-get-data#get_weather
Is several days that I'm testing, and I noticed two issues:
int[] getConditions() always return a single element condition, instead of "a 2-element int array" like the documentation report;
The condition is often very inaccurate.
Of course I tried with different locations around the world (mocking my location), comparing it with other weather services, and the results are the same.
Is that because they just release it? Or is it because I'm doing something wrong? This is my code:
Awareness.SnapshotApi.getWeather(client)
.setResultCallback(new ResultCallback<WeatherResult>() {
#Override
public void onResult(#NonNull WeatherResult weatherResult) {
// weatherResult.getWeather().getConditions() contains the weather condition
}
});
The public method summary says that getConditions() method of Weather (quoting verbatim) "Returns the current weather conditions as an array of values that best describe the current conditions."
In the link for getConditions(), the reference to 2-element array is just an example case for what would be returned if both conditions rainy and windy were applicable. In general it is an array that can contain one or more elements.
It is not clear from the question whether the issue reported is just for getConditions() or for other aspects of the weather such as temperature etc. If the other fields are accurate, it is less likely a problem with the update of the weather.
I'm an early and very happy adopter of both Flux and React so much so that, recently, I ported Fluxxor into Android and it's been okay so far.
The issue I am having with it Flux is dealing with data for a Single Item or Details Page. Bear with me below. I will try to be as clear as I can.
The pattern I am using is.
On page load(componentWillMount/componentWillReceiveProps and onStart), I check if the id passed to the page (via url or bundle) matches the id of the item currently in the store and the page if the store is in a processing or success state.
If yes, I do nothing, else, I dispatch an action to load the data for that item.
componentWillMount: function () {
id = this.props.params.path.split("-")[0];
var artistData = this.props.state.artistData;
if(artistData.id != id)
this.getFlux().actions.artistActions.loadArtist(id);
else if (!artistData.artist && !artistData.loading)
this.getFlux().actions.artistActions.loadArtist(id);
this.getFlux().actions.userActions.fetchSuggestions();
}
protected void onStart() {
GenreSongsStore.State state = App.getFlux().getStore(GenreSongsStore.class).getState();
if(mId == state.Genre.getId()) {
if (state.HasMore)
App.getFlux().getActions().Genres.songs(mId, state.Page + 1);
}
else
App.getFlux().getActions().Genres.songs(mId, 1);
super.onStart();
}
In React this is fine since you use a single state on the root. I didn't bother too much until I started working with Android.
Here, I don't use a single state but query the relevant store and it totally smells
If you are not using that page, the data is still held in memory
Since the data is not shared it seems there is no benefit to doing it like this
Won't it simply be easier to load the data in the component/activity/fragment?
However, I get the benefit of maintaining the currently loading state. So the user can minimize and reopen the app and we continue (no need for saving an instance bundle).
I know by doing it like this, I lose the benefit of unidirectional data flow. But it seems to make more sense in the context of Android (pun intended).
Can I have your views on how you do this and if I'm simply worried about nothing.
NB: The data is not shared by any other stores at.
I've been playing with the Firebase Android Api and discovered this feature (that appears to me as inconsistency). I would like to solicit an opinion and/or a solution for a problem it causes in my scenario.
In the Android app, I establish a standard 'ChildEventListener' in this form:
new Firebase("https://[MYTEST].firebaseio.com/").addChildEventListener(
new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot data, String prev) {
Log.i("_", "add " + data);
}
#Override
public void onChildChanged(DataSnapshot data, String prev) {
Log.i("_", "chg " + data);
}
#Override
public void onChildRemoved(DataSnapshot data) {
Log.i("_", "del " + data);
}
#Override
public void onChildMoved(DataSnapshot data, String prev) {
Log.i("_", "mov " + data);
}
#Override
public void onCancelled(FirebaseError err) {
Log.i("_", "err " + err.getMessage());
}
}
);
Works like a charm, catching all events I can throw on it from the Firebase Dashboard.
Next:
Stop&kill my Android app and add a key (a few keys) through the dashboard.
Start the app and the 'onChildAdded()' catches up with everything that has been added. (actually gives me the full set - as specked and expected). I can easily figure out what's been added. So far so good.
I try the same with deletion. Stop&kill the app and delete a key (many keys) through the dashboard.
Start the app again and get the 'onChildAdded()' again with real amount of nodes left, OR NO EVENT IF THERE IS NO NODE LEFT.
This time, I RECEIVE NO 'onChildRemoved()' EVENT that would reflect what happened while the app was dead.
I understand that this behavior may be by design, but it presents a problem even if I keep a local list of nodes and simple differential may give me the set of deleted nodes. But the fact, that an empty list of nodes generates no 'onChildAdded()' event makes it difficult to place the code that would calculate deleted nodes.
I assume there is another way to get around this 'deletion while dead' problem, please nudge me in the right direction.
Summary: the Firebase database synchronizes state. Unlike message passing mechanisms it does not synchronize state changes.
When you start an app that has no data from the Firebase database cached, the Firebase API synchronizes the minimal data that your app needs to get synchronized with the stored information. So you'll get a child_added event for any data that exists on the server at that time.
If your app already has previous information from the database when it connects (such as when you've used Firebase's disk persistence or when your connection is restored without an app restart), the API will fire the events that are necessary to get the local version of the data up to date with the server. So in that case, you may see child_added, child_changed, child_moved and child_removed events.
There is no guarantee that state changes when your client was not connected are transmitted.
State synchronization in practice
An example of this:
go online
get all data
go offline
another user adds value A
another user removes value A
go online again
Your app will now not receive any indication that value A ever existed. This is simply the way state synchronization works.
Storing state changes, instead of state
If your app requires that each client knows of every state change, you should store the actual state changes in the database.
go online
get all data
go offline
another user writes record "add value A"
another user writes record "remove value A"
go online again
The client will now receive all state changes, because you stored those in the database.
Typically you'll also want to run a trusted process that aggregates all the state change records into a single "current state" again for faster access.
I managed to create an application that collects basic info from the device like android version,CPU,total RAM,free RAM,etc. Some of the data i need to collect is dynamic so i want my application to collect that data every minute.I also want my application to do so in the background. Here is how my code is setup:
public class Sniffer extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sniffer);
model_device=(TextView) findViewById(R.id.model1);
versiune_android=(TextView) findViewById(R.id.versiune1);
total_RAM=(TextView) findViewById(R.id.total_RAM1);
free_RAM=(TextView) findViewById(R.id.free_RAM1);
total_disk=(TextView) findViewById(R.id.total_disk1);
free_disk=(TextView) findViewById(R.id.free_disk1);
CPU=(TextView) findViewById(R.id.CPU1);
nivel_baterie=(TextView) findViewById(R.id.baterie1);
//get the requested data and set the corresponding text
getDeviceData();
}
Inside getDeviceData i read the /proc files and whatnot to obtain everything. Can i create a service that can run in the background and every x minutes update the data by calling getDeviceData again ? Let's take this scenario : start my app,check the data, leave app on, go check my email, listen to a song on youtube then i come back to my app (without closing it)and the collected data should have changed. How would i go about doing so using a service, i think this is the best solution. I need just a bump in the right direction, maybe a skeleton code on where my stuff should go. Thanks