Google Play Services - Sending A Rematch Request - google-play-services

After a multiplayer game is over, is there any possibility of sending a rematch request to the same participants?
Note that this is not provided by the Google API, I am wondering if people have any ideas on implementing such a system.
Thanks,
Rajat

If you just want a solution to inviting all the same people from the previous game.. this works for the player that initiated that initiated the game:
When you get back the Intent from selecting the players.. just save it:
// Handle the result of the "Select players UI" we launched when the user clicked the
// "Invite friends" button. We react by creating a room with those players.
private void handleSelectPlayersResult(int response, Intent data) {
if (response != Activity.RESULT_OK) {
Log.w(TAG, "*** select players UI cancelled, " + response);
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
mGHInterface.onBackedOut();
}
});
return;
}
Log.d(TAG, "Select players UI succeeded.");
previousMatch = data;
// get the invitee list ...(etc, etc)
Then, whatever way you want to activate the next bit of code works:
#Override
public void sendOutRematch() {
handleSelectPlayersResult(Activity.RESULT_OK, previousMatch);
}
Now, for players that are invited to the room... need to look at the Room object for them, and get the invited player id's from that object.. and save that list of players so it can be used in the Room Creation process with something like this to grab the ids :
ArrayList<String> playerIDs;
for (Participant p : room.getParticipants()) {
playerIDs.add(p.getPlayer().getPlayerId());
}
then use that list in your room creation process.

Related

Issue with syncing data between watch and phone

I have developed an Android App which runs on both a smartphone and a smartwatch in parallel. On both devices, (let's say) it reads certain sensor data, processes that data (calculate its mean), and then store that results. The watch sends this result to the phone so all storing takes place on the phone. I used buffer writer to write a number into a text file every 5 seconds.
Now after every 320 data items exchanges from watch to the phone, my app on the phone gets killed and I get "the name of the app" is unfortunately stopped as a message. I can't figure it what why they stop exactly after this time? The app running on the watch continues to work fine. However, I cannot store its data because it cannot communicate to the phone version so I get this message "the app is unfortunately stopped as a message" every time the watch sends a number to phone for storing. The app has one activity which has a service (foreground).
Could it be that there is a limit on the amount of data being shared?
The code on watch:
// Create a data map and put data in it
private void increaseCounter() {
PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
putDataMapReq.getDataMap().putInt(COUNT_KEY, count++); // I add current time here as well
PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
PendingResult<DataApi.DataItemResult> pendingResult =
Wearable.DataApi.putDataItem(mGoogleApiClient, putDataReq);
}
Code on phone (possible problematic area):
#Override
public void onDataChanged(DataEventBuffer dataEvents) {
for (DataEvent event : dataEvents) {
if (event.getType() == DataEvent.TYPE_CHANGED) {
// DataItem changed
DataItem item = event.getDataItem();
if (item.getUri().getPath().compareTo("/count") == 0) {
DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
updateCount(dataMap.getInt(COUNT_KEY));
}
} else if (event.getType() == DataEvent.TYPE_DELETED) {
// DataItem deleted
}
}
}
You have to use Service with StartForeground notification to be sure app is always working.
and try to use START_STICKY flag while staring.
UPDATE
You have to dealloc memory of dataevent:
#Override
public void onDataChanged(DataEventBuffer dataEvents) {
try{
for(DataEvent dataEvent: dataEvents){
if(dataEvent.getType() != DataEvent.TYPE_CHANGED){
continue;
}
////... code
dataEvents.release();
}catch (Exception e){
Log.v("SunshineWatchFace",e.getMessage());
}
}

Open Android activity automatically on receiving notification

I have to launch the app on receiving notification. The following piece of code works fine when the app is killed and notification is received (i.e the code inside if condition). But when the app is running in foreground or background, multiple instances of the activity gets created(i.e snippet in else condition). It's not the MainActivity that has to be launched on receiving the notification, instead it's some other activity containing the broadcast Receiver.
I have added the following lines in the onMessage of GCMintentService class.
if (currentPackage.equalsIgnoreCase(context.getPackageName()
.toString())) {
broadcastMessage(context, message);
} else {
Intent mIntent = new Intent(context, MainActivity.class);
mIntent.setAction(Intent.ACTION_MAIN);
mIntent.addCategory(Intent.CATEGORY_LAUNCHER);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mIntent);
}
In the activity, under onReceive method of BroadcastReceiver, i am starting the activity again.
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
startActivity(getIntent().setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT));
}
};
I also had this requirement in one of my application. We can achieve it if we call
Intent mIntent = new Intent(context, MainActivity.class);
mIntent.setAction(Intent.ACTION_MAIN);
mIntent.addCategory(Intent.CATEGORY_LAUNCHER);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mIntent);
broadcastMessage(context, message);
In the main activity use the following in the broadcast receiver that would receive the broadcasted message above.
WakeLock wakeLock = null;
KeyguardManager kgMgr = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
boolean locked = kgMgr.inKeyguardRestrictedInputMode();
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
if (!pm.isScreenOn()) {
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP, "MyWakeLock");
wakeLock.acquire();
}
if (locked) {
Window mWindow = getWindow();
mWindow.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
mWindow.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
Personally I feel that this is not the best of the answers and also best of the ideas to open the app directly when received a notification as there will be many functions like onCreate onResume, will be triggered automatically, spoil the users work if they are in a really important work by opening another app directly, also we need to put a lot of flags or use any other method to manage the flow of the application, when user open the app, app comes from background, app opened due notification and all such cases. Avoid it as it spoils the whole user experience.

receive all connected players on google play services realtime multiplayer game

is there a way to get a list of all the ids of the players that are connected and near the user that is playing my realtime multiplayer game?
I already tried Games.Players.loadConnectedPlayers() method, but i donĀ“t know how to use its PendingResult
I wanna use public RoomConfig.Builder addPlayersToInvite (ArrayList playerIds)
to make the user play with only specific players
You can use result callback as follows:
Games.Players.loadConnectedPlayers(mHelper.getApiClient(), false).setResultCallback(
new ResultCallback<Players.LoadPlayersResult>() {
#Override
public void onResult(LoadPlayersResult arg0) {
// TODO Auto-generated method stub
}
});

LibGDX - Multiple actors receiving key events

I have more than one actor (for a local coop game) that need to receive key events (e.g. Player 1 uses arrow keys, Player 2 uses WASD etc...). If I just add Actors to a Stage, they don't receive key events through the InputListener, and if I do this:
stage.setKeyboardFocus(p1);
stage.setKeyboardFocus(p2);
Only Player 2 receives key events, of course. How can I have two (or more) actors receive key events?
You can use a Group or a Table which are actors that can contain other actors, and add the actors
Gdx.setInputProcessor(stage);
group = new Group();
group.addActor(actor1);
group.addActor(actor2);
group.addListener(new InputListener(){
#Override
public boolean keyDown(InputEvent event, int keycode){
if (keycode == Keys.A){
update(actor1)
}
if (keycode == Keys.LEFT{
update(actor2)
}
return true;
});
stage.addActor(group);
stage.setKeyboardFocus(group);
Libgdx Stage extends InputAdapter, which gives you access to the methods keyDown(int keyCode) and keyUp(int keyCode). If you set the Stage as your InputProcessor by using: Gdx.setInputProcessor(stage); you can handle key inputs in the Stage.
Some Pseudocode:
public boolean keyDown(int keyCode) {
switch (keyCode) {
case Input.Keys.A:
player2.moveLeft();
case Input.Keys.NUMPAD_4:
player1.moveLeft();
}
}
Hope it helps.
It's curious that nobody mentioned InputMultiplexer. Try it for your situation.
Figured it out. Instead of setting the keyboard focus to the individual Actors, set it to a common actor, and then just add a listener to that actor. E.G.:
public class Scene extends Stage
{
public Scene()
{
setKeyboardFocus(getRoot()); // getRoot() returns the parent actor group
addActor(new Player(1));
addActor(new Player(2));
}
}
public class Player extends Actor
{
public Player(Stage stage)
{
stage.getRoot().addListener(inputListener);
}
}

Asynchronous callback - gwt

I am using gwt and postgres for my project. On the front end i have few widgets whose data i am trying to save on to tables at the back-end when i click on "save project" button(this also takes the name for the created project).
In the asynchronous callback part i am setting more than one table. But it is not sending the data properly. I am getting the following error:
org.postgresql.util.PSQLException: ERROR: insert or update on table "entitytype" violates foreign key constraint "entitytype_pname_fkey"
Detail: Key (pname)=(Project Name) is not present in table "project".
But when i do the select statement on project table i can see that the project name is present.
Here is how the callback part looks like:
oksave.addClickHandler(new ClickHandler(){
#Override
public void onClick(ClickEvent event) {
if(erasync == null)
erasync = GWT.create(EntityRelationService.class);
AsyncCallback<Void> callback = new AsyncCallback<Void>(){
#Override
public void onFailure(Throwable caught) {
}
#Override
public void onSuccess(Void result){ }
};
erasync.setProjects(projectname, callback);
for(int i = 0; i < boundaryPanel.getWidgetCount(); i++){
top = new Integer(boundaryPanel.getWidget(i).getAbsoluteTop()).toString();
left = new Integer(boundaryPanel.getWidget(i).getAbsoluteLeft()).toString();
if(widgetTitle.startsWith("ATTR")){
type = "regular";
erasync.setEntityAttribute(name1, name, type, top, left, projectname, callback);
} else{
erasync.setEntityType(name, top, left, projectname, callback);
}
}
}
Question:
Is it wrong to set more than one in the asynchronous callback where all the other tables are dependent on a particular table?
when i say setProjects in the above code isn't it first completed and then moved on to the next one?
Please any input will be greatly appreciated.
Thank you.
With that foreign key constraint, you must make sure the erasync.setProjects(...) has completed before you insert the rest of the stuff.
I suggest doing the erasync.setEntityAttribute(...) magic in (or from) an onsuccess callback instead of jumping right to it.
You're firing several request in which (guessing from the error message) really should be called in sequence.
Any time you call more than one rpc call; try to think that you should be able to rearrange them in any order (because that's allmost what actually happens because they're asynchronous)... If running them in reverse order does not make sense; you cannot fire them sequentially!
Two ways to fix your problem:
Nesting:
service.callFirst(someData, new AsyncCallback<Void> callback = new AsyncCallback<Void>(){
#Override
public void onFailure(Throwable caught) {/*Handle errors*/}
#Override
public void onSuccess(Void result){
service.callSecond(someOtherData, new AsyncCallback<Void> callback = new AsyncCallback<Void>(){
/* onSuccess and onFailure for second callback here */
});
}
});
Or creating one service call that does both (Recommended):
service.callFirstAndSecond(someData, someOtherData, new AsyncCallback<Void> callback = new AsyncCallback<Void>(){
#Override
public void onFailure(Throwable caught) {/*Handle errors*/}
#Override
public void onSuccess(Void result){
/* Handle success */
}
});
The second option is most likely going to be much less messy, as several nested asynch callbacks quickly grows quite wide and confusing, also you make just one request.
Because of nature of Async, don't assume setProjects(...) method will be called on the server before setEntityAttribute or setEntityType.
Personally, I prefer to have a Project class which contains all necessary info, for example:
public class Project{
private String projectName;
private List attributes = new ArrayList();
.. other properties
// Getter & Setter methods
}
Then send to the server in one round trip:
Project project = new Project();
project.setProjectName(..);
// Set other properties
erasync.saveProjects(project, callback);