com.google.cloud.solutions.cloudadventure.GameScoresFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.google.cloud.solutions.cloudadventure.GameScoresFragment.java

Source

/*
 * Copyright 2013 Google Inc. All Rights Reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

package com.google.cloud.solutions.cloudadventure;

import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.json.gson.GsonFactory;
import com.appspot.myapp.cloudadventure.*;
import com.appspot.myapp.cloudadventure.model.*;
import com.google.cloud.solutions.cloudadventure.util.CloudEndpointUtils;

import android.app.Activity;
import android.app.Fragment;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

import java.io.IOException;
import java.util.List;

/**
 * This takes place post-game and shows player scores as individual games finish.
 *
 */
public class GameScoresFragment extends Fragment {

    /*
     * Endpoint service.
     */
    private Cloudadventure mService;

    private String mCurrentHandle;

    /*
     * View components.
     */
    private Button mHomeButton;
    private TableLayout mScoresTable;
    private ProgressDialog mProgressDialog;

    private static final String PLAYER_TAG_SUFFIX = "-player";
    private static final String GEMS_TAG_SUFFIX = "-gems";
    private static final String MOBS_TAG_SUFFIX = "-mobs_killed";
    private static final String DEATHS_TAG_SUFFIX = "-deaths";

    /*
     * Callback to GameActivity.
     */
    private OnGameScoresClickListener callback;

    /**
     * Receives messages for player end-game statistics.
     */
    private BroadcastReceiver mStatsMsgReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i("GameScoresActivity", "Got a player scores message via broadcast.");
            Player player = new Player();
            player.setHandle(intent.getStringExtra(GCMIntentService.GCM_PAYLOAD_FROM_USER_HANDLE));
            player.setGemsCollected(Long.parseLong(intent.getStringExtra("gems")));
            player.setMobsKilled(Long.parseLong(intent.getStringExtra("mobs_killed")));
            player.setNumDeaths(Long.parseLong(intent.getStringExtra("deaths")));
            addPlayerScore(player);
            mProgressDialog.dismiss();
        }
    };

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // Set the callback activity to use
        try {
            callback = (OnGameScoresClickListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnGameScoresClickListener");
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d("GameScoresFragment State", "onCreateView");

        // Set component views
        final View v = inflater.inflate(R.layout.fragment_game_scores, container, false);
        mProgressDialog = new ProgressDialog(getActivity());
        mProgressDialog.setCanceledOnTouchOutside(false);
        mScoresTable = (TableLayout) v.findViewById(R.id.player_end_scores_table);
        mHomeButton = (Button) v.findViewById(R.id.return_home_button);
        mHomeButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                returnHome();
            }
        });

        // Register the broadcast receivers from GCMIntentService
        LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mStatsMsgReceiver,
                new IntentFilter(GCMIntentService.BROADCAST_ON_MESSAGE_PLAYER_END_STATS));

        // Build the endpoint service
        Cloudadventure.Builder builder = new Cloudadventure.Builder(AndroidHttp.newCompatibleTransport(),
                new GsonFactory(), null);
        CloudEndpointUtils.updateBuilder(builder);
        mService = builder.build();

        mProgressDialog.show();

        return v;
    }

    @Override
    public void onPause() {
        new RemovePlayerAndCleanUp().execute(mCurrentHandle);
        super.onPause();
    }

    @Override
    public void onDestroy() {
        Log.d("GameScoresFragment State", "onDestroy");
        LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mStatsMsgReceiver);
        super.onDestroy();
    }

    /**
     * A listener interface meant for GameActivity, process the action this player makes.
     *
     */
    public interface OnGameScoresClickListener {
        public void returnHome();
    }

    /**
     * Used by GameActivity to update the state of this Fragment.
     */
    public void setCurrentUserHandle(String handle) {
        this.mCurrentHandle = handle;
    }

    /**
     * Used by GameActivity to update the state of this Fragment.
     * <p>
     * This should be called each time the {@link Tile} that the {@link Player} is standing on is
     * updated, in order to ensure that the information and views are properly updated.
     */
    public void reportRetrievalIssue() {
        getView().findViewById(R.id.scores_retrieval_issue).setVisibility(View.VISIBLE);
        getView().findViewById(R.id.player_end_scores_table).setVisibility(View.INVISIBLE);
    }

    /**
     * Used by GameActivity to update the state of this Fragment. The list of players is taken from
     * all players that were currently listed in the Datastore as being in the game at end game.
     * Only update the player if the player hasn't been recorded in this table yet; if the player
     * is already in the table, it means a ping has been received containing the most updated info.
     * <p>
     * Adds the scores of a list of players.
     */
    public void addPlayersScores(List<Player> players) {
        for (Player player : players) {
            if (getView().findViewWithTag(player.getHandle()) == null) {
                updateScoresTable(player);
            }
        }
    }

    /**
     * Adds the scores of this player. This method is called through a ping from a receiver.
     * The ping is always the most updated information, so always update.
     */
    private void addPlayerScore(Player player) {
        String handle = player.getHandle();
        if (getView().findViewWithTag(handle) == null) {
            updateScoresTable(player);
        } else {
            TextView text = (TextView) getView().findViewWithTag(handle + GEMS_TAG_SUFFIX);
            text.setText(Long.toString(player.getGemsCollected()));
            text = (TextView) getView().findViewWithTag(handle + MOBS_TAG_SUFFIX);
            text.setText(Long.toString(player.getMobsKilled()));
            text = (TextView) getView().findViewWithTag(handle + DEATHS_TAG_SUFFIX);
            text.setText(Long.toString(player.getNumDeaths()));
        }
    }

    /**
     * Updates the View for showing the player scores.
     *
     * @param player the player whose scores have been updated
     */
    private void updateScoresTable(Player player) {
        String handle = player.getHandle();
        TableRow row = new TableRow(getActivity());
        row.setTag(handle);
        TextView text = new TextView(getActivity());
        text.setTag(handle + PLAYER_TAG_SUFFIX);
        text.setGravity(Gravity.CENTER);
        text.setText(handle);
        row.addView(text);
        text = new TextView(getActivity());
        text.setTag(handle + GEMS_TAG_SUFFIX);
        text.setGravity(Gravity.CENTER);
        text.setText(Long.toString(player.getGemsCollected()));
        row.addView(text);
        text = new TextView(getActivity());
        text.setTag(handle + MOBS_TAG_SUFFIX);
        text.setGravity(Gravity.CENTER);
        text.setText(Long.toString(player.getMobsKilled()));
        row.addView(text);
        text = new TextView(getActivity());
        text.setTag(handle + DEATHS_TAG_SUFFIX);
        text.setGravity(Gravity.CENTER);
        text.setText(Long.toString(player.getNumDeaths()));
        row.addView(text);
        mScoresTable.addView(row);
    }

    /**
     * Returns the user to the main screen.
     */
    private void returnHome() {
        callback.returnHome();
    }

    /*
     * AsyncTasks.
     */

    private class RemovePlayerAndCleanUp extends AsyncTask<String, Void, Void> {
        @Override
        protected Void doInBackground(String... handles) {
            try {
                mService.players().remove(handles[0]).execute();
            } catch (IOException e) {
                Log.e("ProfileActivity", "RemovePlayerAndCleanUp error: " + e.getMessage(), e);
            }
            return null;
        }
    }
}