10 |
--------------------------------------------------------------------------------
/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 | #006090
3 | #53d5f5
4 | #90006090
5 | #9053d5f5
6 | #00000000
7 |
--------------------------------------------------------------------------------
/res/values-sw720dp-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | 128dp
8 |
9 |
--------------------------------------------------------------------------------
/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt:proguard-google-api-client.txt
12 |
13 | # Project target.
14 | target=android-17
15 |
--------------------------------------------------------------------------------
/res/layout/fragment_game_map.xml:
--------------------------------------------------------------------------------
1 |
7 |
13 |
18 |
19 |
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/proguard-google-api-client.txt:
--------------------------------------------------------------------------------
1 | # ProGuard Configuration file
2 | #
3 | # See http://proguard.sourceforge.net/index.html#manual/usage.html
4 |
5 | # Needed to keep generic types and @Key annotations accessed via reflection
6 |
7 | -keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
8 |
9 | -keepclassmembers class * {
10 | @com.google.api.client.util.Key ;
11 | }
12 |
13 | # Needed by Guava
14 | # See https://groups.google.com/forum/#!topic/guava-discuss/YCZzeCiIVoI
15 |
16 | -dontwarn sun.misc.Unsafe
17 | -dontwarn com.google.common.collect.MinMaxPriorityQueue
18 |
19 | # Needed by google-http-client-android when linking against an older platform version
20 |
21 | -dontwarn com.google.api.client.extensions.android.**
22 |
23 | # Needed by google-api-client-android when linking against an older platform version
24 |
25 | -dontwarn com.google.api.client.googleapis.extensions.android.**
26 |
--------------------------------------------------------------------------------
/src/com/google/cloud/solutions/cloudadventure/HowToPlayActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.solutions.cloudadventure;
18 |
19 | import android.app.Activity;
20 | import android.os.Bundle;
21 | import android.view.View;
22 | import android.view.Window;
23 |
24 | /**
25 | * Activity for the screen which shows static "About" page of the application.
26 | *
27 | */
28 | public class HowToPlayActivity extends Activity {
29 |
30 | @Override
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 |
34 | this.requestWindowFeature(Window.FEATURE_NO_TITLE);
35 | setContentView(R.layout.activity_how_to_play);
36 | }
37 |
38 | public void returnHome(View view) {
39 | finish();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/res/drawable/bold_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
11 |
12 |
17 |
18 |
19 |
20 |
22 |
27 |
28 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/res/layout/fragment_player_inventory.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
19 |
26 |
33 |
--------------------------------------------------------------------------------
/res/drawable/game_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
12 |
13 |
18 |
19 |
20 |
21 |
23 |
29 |
30 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/res/layout/activity_game.xml:
--------------------------------------------------------------------------------
1 |
11 |
18 |
26 |
32 |
39 |
--------------------------------------------------------------------------------
/res/layout/activity_customize_game.xml:
--------------------------------------------------------------------------------
1 |
11 |
17 |
26 |
32 |
38 |
44 |
--------------------------------------------------------------------------------
/res/layout/activity_account_selection.xml:
--------------------------------------------------------------------------------
1 |
10 |
16 |
26 |
33 |
40 |
47 |
--------------------------------------------------------------------------------
/res/layout/activity_how_to_play.xml:
--------------------------------------------------------------------------------
1 |
11 |
18 |
26 |
34 |
42 |
49 |
--------------------------------------------------------------------------------
/res/layout/fragment_player_navigation.xml:
--------------------------------------------------------------------------------
1 |
6 |
14 |
23 |
32 |
39 |
48 |
57 |
--------------------------------------------------------------------------------
/res/layout/fragment_pre_game.xml:
--------------------------------------------------------------------------------
1 |
12 |
18 |
26 |
34 |
42 |
49 |
56 |
--------------------------------------------------------------------------------
/res/layout/fragment_player_actions.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
19 |
27 |
36 |
45 |
54 |
62 |
--------------------------------------------------------------------------------
/src/com/google/cloud/solutions/cloudadventure/util/Constants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.solutions.cloudadventure.util;
18 |
19 | public class Constants {
20 |
21 | /*
22 | * SharedPreferences keys.
23 | */
24 | public static final String SHARED_PREFS_NAME = "USER_PREFS";
25 | public static final String USER_ACCT_SHARED_PREFS_KEY = "USER_ID";
26 | public static final String USER_HANDLE_SHARED_PREFS_KEY = "USER_HANDLE";
27 |
28 | /*
29 | * Intent extra keys.
30 | */
31 | public static final String USER_ACCT_INTENT_EXTRA_KEY =
32 | "com.google.cloud.solutions.cloudadventure.USER_ID";
33 | public static final String USER_HANDLE_INTENT_EXTRA_KEY =
34 | "com.google.cloud.solutions.cloudadventure.USER_HANDLE";
35 | public static final String OK_MESSAGE_INTENT_EXTRA_KEY =
36 | "com.google.cloud.solutions.cloudadventure.OK";
37 | public static final String SELECTED_MAPTYPE_INTENT_EXTRA_KEY =
38 | "com.google.cloud.solutions.cloudadventure.MAPTYPE";
39 | public static final String GAME_ID_INTENT_EXTRA_KEY =
40 | "com.google.cloud.solutions.cloudadventure.GAME_ID";
41 | public static final String INVITED_FRIENDS_INTENT_EXTRA_KEY =
42 | "com.google.cloud.solutions.cloudadventure.INVITED_FRIENDS";
43 | public static final String GAME_ENTRANCE_ACTION_INTENT_EXTRA_KEY =
44 | "com.google.cloud.solutions.cloudadventure.GAME_ENTRANCE_ACTION";
45 | public static final String GAME_SCORES_GEMS_COLLECTED_INTENT_EXTRA_KEY =
46 | "com.google.cloud.solutions.cloudadventure.SCORES_GEMS_COLLECTED";
47 | public static final String GAME_SCORES_DEATH_NUM_INTENT_EXTRA_KEY =
48 | "com.google.cloud.solutions.cloudadventure.SCORES_DEATH_NUM";
49 |
50 | /*
51 | * Activity request codes.
52 | */
53 | public static final int HANDLE_SELECTION_ACTIVITY_REQUEST_CODE = 1;
54 | public static final int GAME_ACTIVITY_REQUEST_CODE = 2;
55 | public static final int ACCOUNT_SELECTION_ACTIVITY_REQUEST_CODE = 3;
56 | public static final int PROFILE_ACTIVITY_REQUEST_CODE = 4;
57 |
58 | /*
59 | * Values for GAME_ENTRANCE_ACTION_INTENT_EXTRA_KEY.
60 | */
61 | public static final String GAME_ENTRANCE_ACTION_CREATOR = "AS_CREATOR";
62 | public static final String GAME_ENTRANCE_ACTION_NOTIFICATION = "BY_INVITE";
63 | public static final String GAME_ENTRANCE_ACTION_RESUME = "RESUME";
64 | }
65 |
--------------------------------------------------------------------------------
/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
11 |
18 |
26 |
33 |
34 |
41 |
48 |
55 |
62 |
69 |
70 |
--------------------------------------------------------------------------------
/src/com/google/cloud/solutions/cloudadventure/widget/OkDialogFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.solutions.cloudadventure.widget;
18 |
19 | import android.app.Activity;
20 | import android.app.AlertDialog;
21 | import android.app.Dialog;
22 | import android.app.DialogFragment;
23 | import android.content.DialogInterface;
24 | import android.os.Bundle;
25 | import android.util.Log;
26 | import android.view.LayoutInflater;
27 | import android.view.View;
28 | import android.view.ViewGroup;
29 |
30 | /**
31 | * This is a DialogFragment class to be used when a simple "OK" button is needed.
32 | *
33 | */
34 | public class OkDialogFragment extends DialogFragment {
35 | private int titleId;
36 | private String message;
37 |
38 | public interface OkDialogListener {
39 | public void onAck(DialogFragment dialog);
40 | }
41 |
42 | OkDialogListener mListener;
43 |
44 | public void setArguments(int titleId, String message) {
45 | this.titleId = titleId;
46 | this.message = message;
47 | }
48 |
49 | @Override
50 | public void onAttach(Activity activity) {
51 | Log.d("OkDialogFragment State", "onAttach");
52 | super.onAttach(activity);
53 | try {
54 | mListener = (OkDialogListener) activity;
55 | } catch (ClassCastException e) {
56 | throw new ClassCastException(activity.toString() + " must implement OkDialogListener");
57 | }
58 | }
59 |
60 | @Override
61 | public void onCreate(Bundle savedInstanceState) {
62 | Log.d("OkDialogFragment State", "onCreate");
63 | super.onCreate(savedInstanceState);
64 | }
65 |
66 | @Override
67 | public Dialog onCreateDialog(Bundle savedInstanceState) {
68 | Log.d("OkDialogFragment State", "onCreateDialog");
69 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
70 | builder.setTitle(titleId).setMessage(message)
71 | .setNeutralButton("OK", new DialogInterface.OnClickListener() {
72 | @Override
73 | public void onClick(DialogInterface dialog, int which) {
74 | mListener.onAck(OkDialogFragment.this);
75 | }
76 | });
77 | return builder.create();
78 | }
79 |
80 | @Override
81 | public View onCreateView(
82 | LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
83 | Log.d("OkDialogFragment State", "onCreateView");
84 | return super.onCreateView(inflater, container, savedInstanceState);
85 | }
86 |
87 | @Override
88 | public void onActivityCreated(Bundle savedInstanceState) {
89 | Log.d("OkDialogFragment State", "onActivityCreated");
90 | super.onActivityCreated(savedInstanceState);
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/res/layout/fragment_game_scores.xml:
--------------------------------------------------------------------------------
1 |
12 |
19 |
25 |
29 |
37 |
45 |
53 |
61 |
62 |
63 |
69 |
--------------------------------------------------------------------------------
/src/com/google/cloud/solutions/cloudadventure/PlayerInventoryFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.solutions.cloudadventure;
18 |
19 | import android.app.Activity;
20 | import android.app.Fragment;
21 | import android.os.Bundle;
22 | import android.view.LayoutInflater;
23 | import android.view.View;
24 | import android.view.View.OnClickListener;
25 | import android.view.ViewGroup;
26 | import android.widget.Button;
27 |
28 | /**
29 | * This Fragment belongs to GameActivity. This shows player inventory and statistics.
30 | *
31 | */
32 | public class PlayerInventoryFragment extends Fragment {
33 |
34 | /*
35 | * Callback to GameActivity
36 | */
37 | private OnPlayerViewListener callback;
38 |
39 | @Override
40 | public void onAttach(Activity activity) {
41 | super.onAttach(activity);
42 | // Set the callback activity to use
43 | try {
44 | callback = (OnPlayerViewListener) activity;
45 | } catch (ClassCastException e) {
46 | throw new ClassCastException(activity.toString() + " must implement OnPlayerViewListener");
47 | }
48 | }
49 |
50 | @Override
51 | public View onCreateView(
52 | LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
53 | View v = inflater.inflate(R.layout.fragment_player_inventory, container, false);
54 |
55 | // Set views and register the listeners
56 | instantiateLookButton(v, R.id.look_button);
57 | instantiateViewSelfButton(v, R.id.view_self_button);
58 | instantiateViewInventoryButton(v, R.id.view_inventory_button);
59 |
60 | return v;
61 | }
62 |
63 | /**
64 | * A listener interface for GameActivity to use to process the view requests this player makes.
65 | *
66 | */
67 | public interface OnPlayerViewListener {
68 | public void viewSurroundings();
69 | public void viewSelf();
70 | public void viewInventory();
71 | }
72 |
73 | private void instantiateLookButton(View v, int buttonId) {
74 | Button button = (Button) v.findViewById(buttonId);
75 | button.setOnClickListener(new OnClickListener() {
76 | @Override
77 | public void onClick(View v) {
78 | callback.viewSurroundings();
79 | }
80 | });
81 | }
82 |
83 | private void instantiateViewSelfButton(View v, int buttonId) {
84 | Button button = (Button) v.findViewById(buttonId);
85 | button.setOnClickListener(new OnClickListener() {
86 | @Override
87 | public void onClick(View v) {
88 | callback.viewSelf();
89 | }
90 | });
91 | }
92 |
93 | private void instantiateViewInventoryButton(View v, int buttonId) {
94 | Button button = (Button) v.findViewById(buttonId);
95 | button.setOnClickListener(new OnClickListener() {
96 | @Override
97 | public void onClick(View v) {
98 | callback.viewInventory();
99 | }
100 | });
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/com/google/cloud/solutions/cloudadventure/GameMapFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.solutions.cloudadventure;
18 |
19 | import android.app.Fragment;
20 | import android.os.Bundle;
21 | import android.view.LayoutInflater;
22 | import android.view.View;
23 | import android.view.ViewGroup;
24 | import android.widget.ScrollView;
25 | import android.widget.TextView;
26 |
27 | /**
28 | * This Fragment belongs to GameActivity. It displays the game world. The map is text-only, taking
29 | * after the classic idea of console-based text games.
30 | *
31 | */
32 | public class GameMapFragment extends Fragment {
33 |
34 | /*
35 | * View components.
36 | */
37 | private ScrollView mScroller;
38 | private TextView mConsole;
39 |
40 | private StringBuilder mConsoleHistory;
41 | private String mCurrentCommand;
42 |
43 | private static final String INPUT_CHAR = "> ";
44 | private static final String DOUBLE_NEWLINE = "\n\n";
45 |
46 | @Override
47 | public View onCreateView(
48 | LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
49 | View v = inflater.inflate(R.layout.fragment_game_map, container, false);
50 | mScroller = (ScrollView) v.findViewById(R.id.scroller);
51 | mConsole = (TextView) v.findViewById(R.id.game_terminal);
52 |
53 | mConsoleHistory = new StringBuilder(getString(R.string.start_action));
54 | mConsoleHistory.append(DOUBLE_NEWLINE);
55 | mConsoleHistory.append(INPUT_CHAR);
56 | updateConsoleHistory();
57 |
58 | return v;
59 | }
60 |
61 | /**
62 | * Updates the text history of the console TextView to the current {@code mConsoleHistory} and
63 | * sets the ScrollView.
64 | */
65 | private void updateConsoleHistory() {
66 | mConsole.setText(mConsoleHistory.toString());
67 | mScroller.post(new Runnable() {
68 | @Override
69 | public void run() {
70 | mScroller.fullScroll(ScrollView.FOCUS_DOWN);
71 | }
72 | });
73 | }
74 |
75 | /**
76 | * Used by GameActivity to update the state of this Fragment.
77 | *
78 | * Updates the current command entered in the "console".
79 | */
80 | public void updateCommand(String command) {
81 | mCurrentCommand = command;
82 | }
83 |
84 | /**
85 | * Used by GameActivity to update the state of this Fragment.
86 | *
87 | * Updates the console view with the current command and the expected result of the command.
88 | * Resets the current command to emtpy string after view update.
89 | */
90 | public void enterCurrentCommandWithResult(String commandResult) {
91 | mConsoleHistory.append(mCurrentCommand);
92 | mConsoleHistory.append(DOUBLE_NEWLINE);
93 | mConsoleHistory.append(commandResult);
94 | mConsoleHistory.append(DOUBLE_NEWLINE);
95 | mConsoleHistory.append(INPUT_CHAR);
96 | updateConsoleHistory();
97 | mCurrentCommand = "";
98 | }
99 |
100 | /**
101 | * Used by GameActivity to update the state of this Fragment.
102 | *
103 | * Directly appends to the console history.
104 | */
105 | public void appendToConsoleHistory(String newString) {
106 | mConsoleHistory.append(newString);
107 | updateConsoleHistory();
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/com/google/cloud/solutions/cloudadventure/util/CloudEndpointUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.solutions.cloudadventure.util;
18 |
19 | import com.google.api.client.googleapis.json.GoogleJsonError;
20 | import com.google.api.client.googleapis.json.GoogleJsonResponseException;
21 | import com.google.api.client.googleapis.services.AbstractGoogleClient;
22 | import com.google.api.client.googleapis.services.AbstractGoogleClientRequest;
23 | import com.google.api.client.googleapis.services.GoogleClientRequestInitializer;
24 |
25 | import android.app.Activity;
26 | import android.util.Log;
27 | import android.widget.Toast;
28 |
29 | import java.io.IOException;
30 |
31 | /**
32 | * Common utilities.
33 | */
34 | public class CloudEndpointUtils {
35 |
36 | public static final boolean LOCAL_ANDROID_RUN = false;
37 | private static final String LOCAL_APP_ENGINE_SERVER_URL = "http://10.0.2.2:8888";
38 |
39 | /**
40 | * Updates the Google client builder to connect the appropriate server based on whether
41 | * LOCAL_ANDROID_RUN is true or false.
42 | *
43 | * @param builder Google client builder
44 | * @return same Google client builder
45 | */
46 | public static B updateBuilder(B builder) {
47 | if (LOCAL_ANDROID_RUN) {
48 | builder.setRootUrl(LOCAL_APP_ENGINE_SERVER_URL + "/_ah/api/");
49 | }
50 |
51 | // only enable GZip when connecting to remote server
52 | final boolean enableGZip = builder.getRootUrl().startsWith("https:");
53 |
54 | builder.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
55 | public void initialize(AbstractGoogleClientRequest> request) throws IOException {
56 | if (!enableGZip) {
57 | request.setDisableGZipContent(true);
58 | }
59 | }
60 | });
61 |
62 | return builder;
63 | }
64 |
65 | /**
66 | * Logs the given message and shows an error alert dialog with it.
67 | *
68 | * @param activity activity
69 | * @param tag log tag to use
70 | * @param message message to log and show or {@code null} for none
71 | */
72 | public static void logAndShow(Activity activity, String tag, String message) {
73 | Log.e(tag, message);
74 | showError(activity, message);
75 | }
76 |
77 | /**
78 | * Logs the given throwable and shows an error alert dialog with its message.
79 | *
80 | * @param activity activity
81 | * @param tag log tag to use
82 | * @param t throwable to log and show
83 | */
84 | public static void logAndShow(Activity activity, String tag, Throwable t) {
85 | Log.e(tag, "Error", t);
86 | String message = t.getMessage();
87 | if (t instanceof GoogleJsonResponseException) {
88 | GoogleJsonError details = ((GoogleJsonResponseException) t).getDetails();
89 | if (details != null) {
90 | message = details.getMessage();
91 | }
92 | }
93 | showError(activity, message);
94 | }
95 |
96 | /**
97 | * Shows an error alert dialog with the given message.
98 | *
99 | * @param activity activity
100 | * @param message message to show or {@code null} for none
101 | */
102 | public static void showError(final Activity activity, String message) {
103 | final String errorMessage = message == null ? "Error" : "[Error ] " + message;
104 | activity.runOnUiThread(new Runnable() {
105 | public void run() {
106 | Toast.makeText(activity, errorMessage, Toast.LENGTH_LONG).show();
107 | }
108 | });
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/res/layout/activity_profile.xml:
--------------------------------------------------------------------------------
1 |
12 |
19 |
27 |
34 |
42 |
49 |
57 |
64 |
72 |
79 |
87 |
94 |
--------------------------------------------------------------------------------
/src/com/google/cloud/solutions/cloudadventure/widget/CustomArrayAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.solutions.cloudadventure.widget;
18 |
19 | import com.google.api.services.cloudadventure.model.Creature;
20 | import com.google.api.services.cloudadventure.model.Pickup;
21 |
22 | import android.content.Context;
23 | import android.util.Log;
24 | import android.view.LayoutInflater;
25 | import android.view.View;
26 | import android.view.ViewGroup;
27 | import android.widget.ArrayAdapter;
28 | import android.widget.TextView;
29 |
30 | import java.util.List;
31 |
32 | /**
33 | * This ArrayAdapter uses Creatures or Pickups as items, and displays the name property.
34 | *
35 | *
36 | * @param
37 | */
38 | public class CustomArrayAdapter extends ArrayAdapter {
39 |
40 | private int mFieldId = 0;
41 | private int mResource;
42 | private int mDropDownResource;
43 | private LayoutInflater mInflater;
44 |
45 | public CustomArrayAdapter(Context context, int textViewResourceId, List objects) {
46 | super(context, textViewResourceId, objects);
47 | mFieldId = 0;
48 | mResource = mDropDownResource = textViewResourceId;
49 | mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
50 | }
51 |
52 | @Override
53 | public View getView(int position, View convertView, ViewGroup parent) {
54 | View view;
55 | TextView text;
56 |
57 | if (convertView == null) {
58 | view = mInflater.inflate(mResource, parent, false);
59 | } else {
60 | view = convertView;
61 | }
62 |
63 | try {
64 | if (mFieldId == 0) {
65 | // If no custom field is assigned, assume the whole resource is a TextView
66 | text = (TextView) view;
67 | } else {
68 | // Otherwise, find the TextView field within the layout
69 | text = (TextView) view.findViewById(mFieldId);
70 | }
71 | } catch (ClassCastException e) {
72 | Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
73 | throw new IllegalStateException("ArrayAdapter requires the resource ID to be a TextView", e);
74 | }
75 |
76 | T item = getItem(position);
77 | if (item instanceof CharSequence) {
78 | text.setText((CharSequence) item);
79 | } else if (item instanceof Creature) {
80 | text.setText(((Creature) item).getName());
81 | } else if (item instanceof Pickup) {
82 | text.setText(((Pickup) item).getName());
83 | } else {
84 | text.setText(item.toString());
85 | }
86 |
87 | return view;
88 | }
89 |
90 | @Override
91 | public View getDropDownView(int position, View convertView, ViewGroup parent) {
92 | View view;
93 | TextView text;
94 |
95 | if (convertView == null) {
96 | view = mInflater.inflate(mResource, parent, false);
97 | } else {
98 | view = convertView;
99 | }
100 |
101 | try {
102 | if (mFieldId == 0) {
103 | // If no custom field is assigned, assume the whole resource is a TextView
104 | text = (TextView) view;
105 | } else {
106 | // Otherwise, find the TextView field within the layout
107 | text = (TextView) view.findViewById(mFieldId);
108 | }
109 | } catch (ClassCastException e) {
110 | Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
111 | throw new IllegalStateException("ArrayAdapter requires the resource ID to be a TextView", e);
112 | }
113 |
114 | T item = getItem(position);
115 | if (item instanceof CharSequence) {
116 | text.setText((CharSequence) item);
117 | } else if (item instanceof Creature) {
118 | text.setText(((Creature) item).getName());
119 | } else if (item instanceof Pickup) {
120 | text.setText(((Pickup) item).getName());
121 | } else {
122 | text.setText(item.toString());
123 | }
124 |
125 | return view;
126 | }
127 | }
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
45 |
46 |
47 |
48 |
49 |
50 |
55 |
58 |
59 |
62 |
65 |
66 |
70 |
73 |
74 |
78 |
81 |
82 |
85 |
88 |
89 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/src/com/google/cloud/solutions/cloudadventure/world/MapUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.solutions.cloudadventure.world;
18 |
19 | import com.google.api.services.cloudadventure.model.Player;
20 | import com.google.api.services.cloudadventure.model.Tile;
21 |
22 | import android.util.Log;
23 |
24 | import java.util.List;
25 |
26 | /**
27 | * Utility class to aid with map navigation in the game.
28 | */
29 | public class MapUtils {
30 | /**
31 | * This class enumerates the types of cardinal directions available. Note for developers: be very
32 | * careful when changing the order of declaration in this enum, since values() is called elsewhere
33 | * in this application.
34 | *
35 | * NOTE: Updates to this enum need to be reflected in the corresponding enum class in the backend
36 | */
37 | public enum Cardinal {
38 | NORTH, EAST, SOUTH, WEST
39 | }
40 |
41 | /**
42 | * This class maps the ever-changing relationships between the cardinal directions and the
43 | * relative directions of a {@link Player}. One of these mappers is instantiated for each
44 | * {@link Player} in the game, and is updated each time the player moves and changes direction.
45 | */
46 | public static class DirectionMapper {
47 | private Cardinal[] cardinalDirections = Cardinal.values();
48 |
49 | private Cardinal forward = Cardinal.NORTH;
50 | private Cardinal right = Cardinal.EAST;
51 | private Cardinal back = Cardinal.SOUTH;
52 | private Cardinal left = Cardinal.WEST;
53 |
54 | public DirectionMapper(final Cardinal initialFacing) {
55 | switch (initialFacing) {
56 | case NORTH:
57 | break;
58 | case EAST:
59 | turnRight();
60 | break;
61 | case SOUTH:
62 | turnAround();
63 | break;
64 | case WEST:
65 | turnLeft();
66 | break;
67 | }
68 | }
69 |
70 | public Cardinal getFrontCardinal() {
71 | return forward;
72 | }
73 |
74 | public Cardinal getRightCardinal() {
75 | return right;
76 | }
77 |
78 | public Cardinal getBehindCardinal() {
79 | return back;
80 | }
81 |
82 | public Cardinal getLeftCardinal() {
83 | return left;
84 | }
85 |
86 | public void turnRight() {
87 | forward = cardinalDirections[(forward.ordinal() + 1 + 4) % 4];
88 | right = cardinalDirections[(right.ordinal() + 1 + 4) % 4];
89 | back = cardinalDirections[(back.ordinal() + 1 + 4) % 4];
90 | left = cardinalDirections[(left.ordinal() + 1 + 4) % 4];
91 | }
92 |
93 | public void turnAround() {
94 | forward = cardinalDirections[(forward.ordinal() + 2 + 4) % 4];
95 | right = cardinalDirections[(right.ordinal() + 2 + 4) % 4];
96 | back = cardinalDirections[(back.ordinal() + 2 + 4) % 4];
97 | left = cardinalDirections[(left.ordinal() + 2 + 4) % 4];
98 | }
99 |
100 | public void turnLeft() {
101 | forward = cardinalDirections[(forward.ordinal() - 1 + 4) % 4];
102 | right = cardinalDirections[(right.ordinal() - 1 + 4) % 4];
103 | back = cardinalDirections[(back.ordinal() - 1 + 4) % 4];
104 | left = cardinalDirections[(left.ordinal() - 1 + 4) % 4];
105 | }
106 | }
107 |
108 | /**
109 | * Given a {@link Player} and cardinal direction, finds the next {@link Tile} in that direction.
110 | *
111 | * @param player a {@link Player} with a current {@link Tile} location
112 | * @param direction the direction in which to find the next tile
113 | * @return {@link Tile}
114 | */
115 | public static Tile getNextTile(Player player, Cardinal direction) {
116 | Tile currentTile = player.getCurrentTile();
117 | List> grid = player.getMaze().getGrid();
118 | try {
119 | switch (direction) {
120 | case NORTH:
121 | return grid.get(currentTile.getCoord().getX()).get(currentTile.getCoord().getY() + 1);
122 | case EAST:
123 | return grid.get(currentTile.getCoord().getX() + 1).get(currentTile.getCoord().getY());
124 | case SOUTH:
125 | return grid.get(currentTile.getCoord().getX()).get(currentTile.getCoord().getY() - 1);
126 | case WEST:
127 | return grid.get(currentTile.getCoord().getX() - 1).get(currentTile.getCoord().getY());
128 | }
129 | } catch (IndexOutOfBoundsException e) {
130 | Log.wtf("MapUtils", "Should not have been able to call this method with direction "
131 | + direction + ", because the UI should not have presented the player with the option.");
132 | }
133 | Log.wtf("MapUtils", "Why does an available direction exist such as " + direction + " here?");
134 | return currentTile;
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
15 |
16 |
17 |
30 |
31 |
35 |
36 |
40 |
41 |
45 |
46 |
50 |
51 |
57 |
58 |
64 |
65 |
68 |
69 |
74 |
75 |
80 |
81 |
88 |
89 |
98 |
99 |
102 |
103 |
106 |
107 |
110 |
111 |
114 |
115 |
118 |
119 |
123 |
124 |
--------------------------------------------------------------------------------
/src/com/google/cloud/solutions/cloudadventure/PlayerNavFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.solutions.cloudadventure;
18 |
19 | import com.google.api.services.cloudadventure.model.Tile;
20 | import com.google.cloud.solutions.cloudadventure.world.MapUtils.Cardinal;
21 | import com.google.cloud.solutions.cloudadventure.world.MapUtils.DirectionMapper;
22 |
23 | import android.app.Activity;
24 | import android.app.Fragment;
25 | import android.os.Bundle;
26 | import android.view.LayoutInflater;
27 | import android.view.View;
28 | import android.view.View.OnClickListener;
29 | import android.view.ViewGroup;
30 | import android.widget.Button;
31 |
32 | import java.util.List;
33 |
34 | /**
35 | * This Fragment belongs to GameActivity. It contains a user-interactive part of this screen,
36 | * allowing users to choose navigational directions.
37 | *
38 | *
39 | */
40 | public class PlayerNavFragment extends Fragment {
41 |
42 | private DirectionMapper mDirectionMapper;
43 |
44 | /*
45 | * View components.
46 | */
47 | private Button mForwardButton;
48 | private Button mRightButton;
49 | private Button mBackButton;
50 | private Button mLeftButton;
51 |
52 | /*
53 | * Callback to GameActivity
54 | */
55 | private OnPlayerNavClickListener callback;
56 |
57 | @Override
58 | public void onAttach(Activity activity) {
59 | super.onAttach(activity);
60 |
61 | // Set the callback activity to use
62 | try {
63 | callback = (OnPlayerNavClickListener) activity;
64 | } catch (ClassCastException e) {
65 | throw new ClassCastException(
66 | activity.toString() + " must implement OnPlayerNavClickListener");
67 | }
68 | }
69 |
70 | @Override
71 | public View onCreateView(
72 | LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
73 | View v = inflater.inflate(R.layout.fragment_player_navigation, container, false);
74 |
75 | // Set views and register the listeners
76 | instantiateGoForwardButton(v, R.id.go_forward_button);
77 | instantiateGoRightButton(v, R.id.go_right_button);
78 | instantiateGoBackButton(v, R.id.go_back_button);
79 | instantiateGoLeftButton(v, R.id.go_left_button);
80 |
81 | return v;
82 | }
83 |
84 | /**
85 | * A listener interface for GameActivity to use to process the navigations this player makes.
86 | *
87 | */
88 | public interface OnPlayerNavClickListener {
89 | public void move(Cardinal direction);
90 | }
91 |
92 | /**
93 | * Used by GameActivity to update the state of this Fragment.
94 | *
95 | * Sets a new {@link DirectionMapper} with an initial orientation.
96 | *
97 | * @param currentOrientation the cardinal direction of the initial orientation for the mapper
98 | */
99 | public void setNewDirectionMapper(final Cardinal currentOrientation) {
100 | mDirectionMapper = new DirectionMapper(currentOrientation);
101 | }
102 |
103 | /**
104 | * Used by GameActivity to update the state of this Fragment.
105 | *
106 | * Sets the current {@link Tile} and decides the navigation buttons to show based upon the
107 | * properties of the tile.
108 | *
109 | * This should be called each time the {@link Tile} that the {@link Player} is standing on is
110 | * updated, in order to ensure that the information and views are properly updated.
111 | *
112 | * @param tile the new current tile
113 | */
114 | public void setCurrentTile(Tile tile) {
115 | List openTo = tile.getOpenTo();
116 | mForwardButton.setEnabled(openTo.contains(mDirectionMapper.getFrontCardinal().toString()));
117 | mRightButton.setEnabled(openTo.contains(mDirectionMapper.getRightCardinal().toString()));
118 | mBackButton.setEnabled(openTo.contains(mDirectionMapper.getBehindCardinal().toString()));
119 | mLeftButton.setEnabled(openTo.contains(mDirectionMapper.getLeftCardinal().toString()));
120 | }
121 |
122 | /**
123 | * Used by GameActivityi to update the state of this fragment.
124 | *
125 | * Hides all but the back button. Used when there are dangerous creatures on the tile.
126 | */
127 | public void registerCreatureDanger() {
128 | mForwardButton.setEnabled(false);
129 | mRightButton.setEnabled(false);
130 | mLeftButton.setEnabled(false);
131 | }
132 |
133 | private void instantiateGoForwardButton(View v, int buttonId) {
134 | mForwardButton = (Button) v.findViewById(buttonId);
135 | mForwardButton.setOnClickListener(new OnClickListener() {
136 | @Override
137 | public void onClick(View v) {
138 | callback.move(mDirectionMapper.getFrontCardinal());
139 | }
140 | });
141 | }
142 |
143 | private void instantiateGoRightButton(View v, int buttonId) {
144 | mRightButton = (Button) v.findViewById(buttonId);
145 | mRightButton.setOnClickListener(new OnClickListener() {
146 | @Override
147 | public void onClick(View v) {
148 | mDirectionMapper.turnRight();
149 | callback.move(mDirectionMapper.getFrontCardinal()); // right is the new forward
150 | }
151 | });
152 | }
153 |
154 | private void instantiateGoBackButton(View v, int buttonId) {
155 | mBackButton = (Button) v.findViewById(buttonId);
156 | mBackButton.setOnClickListener(new OnClickListener() {
157 | @Override
158 | public void onClick(View v) {
159 | mDirectionMapper.turnAround();
160 | callback.move(mDirectionMapper.getFrontCardinal()); // back is the new forward
161 | }
162 | });
163 | }
164 |
165 | private void instantiateGoLeftButton(View v, int buttonId) {
166 | mLeftButton = (Button) v.findViewById(buttonId);
167 | mLeftButton.setOnClickListener(new OnClickListener() {
168 | @Override
169 | public void onClick(View v) {
170 | mDirectionMapper.turnLeft();
171 | callback.move(mDirectionMapper.getFrontCardinal()); // left is the new forward
172 | }
173 | });
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/src/com/google/cloud/solutions/cloudadventure/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.solutions.cloudadventure;
18 |
19 | import com.google.cloud.solutions.cloudadventure.util.Constants;
20 |
21 | import android.app.Activity;
22 | import android.app.ProgressDialog;
23 | import android.content.Context;
24 | import android.content.Intent;
25 | import android.content.SharedPreferences;
26 | import android.os.Bundle;
27 | import android.util.Log;
28 | import android.view.View;
29 | import android.view.Window;
30 | import android.widget.TextView;
31 |
32 | /**
33 | * This Activity is "Home" / "Main Menu". The launcher Activity for this app.
34 | *
35 | */
36 | public class MainActivity extends Activity {
37 |
38 | private String mCurrentUserHandle;
39 |
40 | /*
41 | * View components.
42 | */
43 | private ProgressDialog mProgressDialog;
44 | private TextView mUserHandleView;
45 |
46 | @Override
47 | protected void onCreate(Bundle savedInstanceState) {
48 | super.onCreate(savedInstanceState);
49 | Log.d("MainActivity State", "onCreate");
50 |
51 | // Set the components for this Activity
52 | this.requestWindowFeature(Window.FEATURE_NO_TITLE);
53 | setContentView(R.layout.activity_main);
54 | mProgressDialog = new ProgressDialog(this);
55 | mProgressDialog.setCanceledOnTouchOutside(false);
56 | mUserHandleView = (TextView) findViewById(R.id.user_handle_welcome_text);
57 | }
58 |
59 | @Override
60 | protected void onStart() {
61 | super.onStart();
62 | Log.d("MainActivity State", "onStart");
63 | }
64 |
65 | @Override
66 | protected void onPostCreate(Bundle savedInstanceState) {
67 | super.onPostCreate(savedInstanceState);
68 | Log.d("MainActivity State", "onPostCreate");
69 | }
70 |
71 | @Override
72 | protected void onResume() {
73 | super.onResume();
74 | Log.d("MainActivity State", "onResume");
75 |
76 | // handle user logic here
77 | handleUserSelectionLogic();
78 | }
79 |
80 | @Override
81 | protected void onPause() {
82 | super.onPause();
83 | Log.d("MainActivity State", "onPause");
84 | }
85 |
86 | @Override
87 | protected void onSaveInstanceState(Bundle instanceState) {
88 | super.onSaveInstanceState(instanceState);
89 | Log.d("MainActivity State", "onSaveInstanceState");
90 | }
91 |
92 | @Override
93 | protected void onStop() {
94 | super.onStop();
95 | Log.d("MainActivity State", "onStop");
96 | }
97 |
98 | @Override
99 | protected void onRestart() {
100 | super.onRestart();
101 | Log.d("MainActivity State", "onRestart");
102 | }
103 |
104 | @Override
105 | protected void onDestroy() {
106 | super.onDestroy();
107 | Log.d("MainActivity State", "onDestroy");
108 | }
109 |
110 | @Override
111 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
112 | Log.d("MainActivity State", "onActivityResult");
113 | if (resultCode != Activity.RESULT_OK) {
114 | return;
115 | }
116 | if (requestCode == Constants.ACCOUNT_SELECTION_ACTIVITY_REQUEST_CODE) {
117 | setCurrentUserHandle(data.getStringExtra(Constants.USER_HANDLE_INTENT_EXTRA_KEY));
118 | }
119 | }
120 |
121 | /**
122 | * Handles updating the current user to the most current state. If no current user is remembered
123 | * by the application, then the user may select an account to use from the phone.
124 | */
125 | private void handleUserSelectionLogic() {
126 | // Get what the current user handle should be
127 | SharedPreferences settings =
128 | getSharedPreferences(Constants.SHARED_PREFS_NAME, Context.MODE_PRIVATE);
129 | String userHandleFromSettings;
130 | if (settings != null) {
131 | userHandleFromSettings = settings.getString(Constants.USER_HANDLE_SHARED_PREFS_KEY, null);
132 | if (userHandleFromSettings != null) {
133 | setCurrentUserHandle(userHandleFromSettings);
134 | } else {
135 | selectAccount();
136 | }
137 | }
138 | }
139 |
140 | /**
141 | * Sets up the current user and performs a few data checks for user set up.
142 | */
143 | private void setCurrentUserHandle(String handle) {
144 | mCurrentUserHandle = handle;
145 | mUserHandleView.setText(getString(R.string.hello_prefix) + mCurrentUserHandle);
146 | writeHandleToSharedPrefs(mCurrentUserHandle);
147 | GCMIntentService.register(MainActivity.this, mCurrentUserHandle);
148 | }
149 |
150 | /**
151 | * Writes the user handle to SharedPreferences.
152 | */
153 | private void writeHandleToSharedPrefs(String handle) {
154 | SharedPreferences settings = getSharedPreferences(Constants.SHARED_PREFS_NAME,
155 | Context.MODE_PRIVATE);
156 | SharedPreferences.Editor editor = settings.edit();
157 | editor.putString(Constants.USER_HANDLE_SHARED_PREFS_KEY, handle);
158 | editor.commit();
159 | }
160 |
161 | /**
162 | * Starts the AccountSelectionActivity, where users can switch to a different account and/or
163 | * choose a unique username for a new account to use with this application.
164 | */
165 | private void selectAccount() {
166 | Intent intent = new Intent(this, AccountSelectionActivity.class);
167 | startActivityForResult(intent, Constants.ACCOUNT_SELECTION_ACTIVITY_REQUEST_CODE);
168 | }
169 |
170 | /*
171 | * Home menu button-triggered methods.
172 | */
173 |
174 | public void viewHowTo(View view) {
175 | Intent intent = new Intent(this, HowToPlayActivity.class);
176 | startActivity(intent);
177 | }
178 |
179 | public void customizeGame(View view) {
180 | Intent intent = new Intent(this, CustomizeGameActivity.class);
181 | intent.putExtra(Constants.USER_HANDLE_INTENT_EXTRA_KEY, mCurrentUserHandle);
182 | startActivity(intent);
183 | }
184 |
185 | public void viewStats(View view) {
186 | Intent intent = new Intent(this, ProfileActivity.class);
187 | intent.putExtra(Constants.USER_HANDLE_INTENT_EXTRA_KEY, mCurrentUserHandle);
188 | startActivityForResult(intent, Constants.PROFILE_ACTIVITY_REQUEST_CODE);
189 | }
190 |
191 | public void switchUser(View view) {
192 | selectAccount();
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Cloud Adventure!
6 | Settings
7 | Accept
8 | Decline
9 | "Hello, "
10 | You cannot haz
11 |
12 |
13 | Cloud Adventure!
14 | About
15 | Play!
16 | View Profile
17 | Switch User
18 | Friend Request
19 | In Game
20 | Rejoin
21 | Abandon
22 |
23 |
24 | Welcome to Cloud Adventure!
25 | Remember those awesome classic adventure games? This simple text-based adventure is an example of an application built purely on the Google Cloud Platform.
26 | Your goal in this game is to collect all the gems on your map. Be careful — there are dangerous creatures lurking about...
27 | You may invite friends to your game. You each get your own map, so you can\'t run into each other (yet!), but it\'s a race to collect all your gems first. At that time, the game is over for everyone, and you can compare scores. Who collected the most gems? Who got careless and died seven times?!
28 | Good luck.
29 |
30 |
31 | You do not have any Google accounts on this phone. Please go to Account Settings and add a Google account to use.
32 |
33 |
34 | "Choose an account to use:"
35 | new case-sensitive handle
36 | Select
37 |
38 |
39 | User Handle
40 | Total Games Played
41 | Total Gems Found
42 | Total Mobs Killed
43 | friends
44 | User Handle
45 | Request Friend
46 | Friend Request Sent
47 | Friend Request Failed
48 |
49 |
50 | Choose friends to play with:
51 | Choose your game map:
52 |
53 | TEST
54 | RANDOM
55 | LABYRINTH
56 |
57 | Create Game
58 | Game could not be created
59 |
60 |
61 | Players currently in the game:
62 | Waiting for host to start the game...
63 | Start
64 | Cancel
65 | Leave Game
66 | Game abandoned
67 |
68 |
69 | You have died!
70 | The game has ended
71 | You are now facing %s and on Tile %s. On this tile:
72 | You have %s/%s health.
73 | self
74 | inventory
75 | look
76 | "go "
77 | "examine "
78 | fight %s with %s
79 | "talk to "
80 | "take "
81 | "consume "
82 | "dance with "
83 | "save"
84 | "Save point successful."
85 | "Save point failed. Please try saving again."
86 |
87 |
88 | move
89 | F
90 | R
91 | B
92 | L
93 |
94 |
95 | interact
96 | Examine
97 | Eat
98 | Talk
99 | Fight
100 | Take
101 | Dance
102 | Save
103 | What do you want to examine?
104 | What do you want to consume?
105 | Who do you want to fight?
106 | What do you want to fight with?
107 | Who do you want to talk to?
108 | What do you want to pick up?
109 | Who do you want to dance with?
110 |
111 |
112 | You wake up in a dark, mysterious room. You are disoriented, but you discover that you can still look around and inspect the items you are carrying.
113 |
114 |
115 | view
116 | Surroundings
117 | Self
118 | Inventory
119 |
120 |
121 | Back To Home
122 |
123 | Gems
124 | Kills
125 | Deaths
126 | There was a problem retrieving some players\' scores. :(
127 |
128 |
--------------------------------------------------------------------------------
/src/com/google/cloud/solutions/cloudadventure/PreGameFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.solutions.cloudadventure;
18 |
19 | import com.google.cloud.solutions.cloudadventure.util.Constants;
20 |
21 | import android.app.Activity;
22 | import android.app.AlertDialog;
23 | import android.app.Fragment;
24 | import android.content.BroadcastReceiver;
25 | import android.content.Context;
26 | import android.content.DialogInterface;
27 | import android.content.Intent;
28 | import android.content.IntentFilter;
29 | import android.os.Bundle;
30 | import android.support.v4.content.LocalBroadcastManager;
31 | import android.util.Log;
32 | import android.view.LayoutInflater;
33 | import android.view.View;
34 | import android.view.View.OnClickListener;
35 | import android.view.ViewGroup;
36 | import android.widget.ArrayAdapter;
37 | import android.widget.Button;
38 | import android.widget.ListView;
39 | import android.widget.TextView;
40 |
41 | import java.util.ArrayList;
42 |
43 | /**
44 | * This Activity takes places before the game actually starts. Players who join the game can see who
45 | * else has joined, and the creator of the game can then hit the "start" button at any time. Players
46 | * may leave the game at any time. The creator may also cancel the game at any time.
47 | *
48 | */
49 | public class PreGameFragment extends Fragment {
50 |
51 | private ArrayList mCurrentHandles;
52 | private boolean mIsCreator;
53 |
54 | /*
55 | * View components.
56 | */
57 | private ListView mPlayersView;
58 | private TextView mStatusMessage;
59 | private Button mStartButton;
60 | private Button mCancelButton;
61 | private Button mLeaveButton;
62 |
63 | /*
64 | * Callback to GameActivity.
65 | */
66 | private OnPreGameClickListener callback;
67 |
68 | /**
69 | * Receives messages for players joining the game.
70 | */
71 | private BroadcastReceiver mJoinMsgReceiver = new BroadcastReceiver() {
72 | @Override
73 | public void onReceive(Context context, Intent intent) {
74 | Log.i("PreGameFragment", "Got a join message via broadcast.");
75 | String from = intent.getStringExtra(GCMIntentService.GCM_PAYLOAD_FROM_USER_HANDLE);
76 | addCurrentPlayer(from);
77 | }
78 | };
79 |
80 | /**
81 | * Receives messages for players leaving the game from this screen.
82 | */
83 | private BroadcastReceiver mLeaveMsgReceiver = new BroadcastReceiver() {
84 | @Override
85 | public void onReceive(Context context, Intent intent) {
86 | Log.i("PreGameFragment", "Got a leave message via broadcast.");
87 | String from = intent.getStringExtra(GCMIntentService.GCM_PAYLOAD_FROM_USER_HANDLE);
88 | removeCurrentPlayer(from);
89 | }
90 | };
91 |
92 | /**
93 | * Receives messages for the creator cancelling the game.
94 | */
95 | private BroadcastReceiver mDestroyMsgReceiver = new BroadcastReceiver() {
96 | @Override
97 | public void onReceive(Context context, Intent intent) {
98 | Log.i("PreGameFragment", "Got a destroy message via broadcast.");
99 | showGameDestroyDialog(intent.getStringExtra(GCMIntentService.GCM_PAYLOAD_MESSAGE));
100 | }
101 | };
102 |
103 | @Override
104 | public void onAttach(Activity activity) {
105 | super.onAttach(activity);
106 |
107 | // Set the callback activity to use
108 | try {
109 | callback = (OnPreGameClickListener) activity;
110 | } catch (ClassCastException e) {
111 | throw new ClassCastException(activity.toString() + " must implement OnPreGameClickListener");
112 | }
113 |
114 | // Handle entrance logic
115 | if (Constants.GAME_ENTRANCE_ACTION_CREATOR.equals(activity.getIntent().getStringExtra(
116 | Constants.GAME_ENTRANCE_ACTION_INTENT_EXTRA_KEY))) {
117 | mIsCreator = true;
118 | } else {
119 | mIsCreator = false;
120 | }
121 | }
122 |
123 | @Override
124 | public View onCreateView(
125 | LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
126 |
127 | // Set component views
128 | final View v = inflater.inflate(R.layout.fragment_pre_game, container, false);
129 | mPlayersView = (ListView) v.findViewById(R.id.game_players_list);
130 | mStatusMessage = (TextView) v.findViewById(R.id.game_waiting_text);
131 |
132 | instantiateStartButton(v, R.id.start_game_button);
133 | instantiateCancelButton(v, R.id.cancel_game_button);
134 | instantiateLeaveButton(v, R.id.leave_game_button);
135 |
136 | // Register the broadcast receivers from GCMIntentService
137 | LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mJoinMsgReceiver,
138 | new IntentFilter(GCMIntentService.BROADCAST_ON_MESSAGE_PLAYER_JOIN));
139 | LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mLeaveMsgReceiver,
140 | new IntentFilter(GCMIntentService.BROADCAST_ON_MESSAGE_PLAYER_LEAVE));
141 | LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mDestroyMsgReceiver,
142 | new IntentFilter(GCMIntentService.BROADCAST_ON_MESSAGE_GAME_DESTROY));
143 |
144 | return v;
145 | }
146 |
147 | @Override
148 | public void onDestroy() {
149 | Log.d("PreGameFragment State", "onDestroy");
150 | LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mJoinMsgReceiver);
151 | LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mLeaveMsgReceiver);
152 | LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mDestroyMsgReceiver);
153 |
154 | super.onDestroy();
155 | }
156 |
157 | /**
158 | * A listener interface for GameActivity to use to process the actions this player makes.
159 | *
160 | */
161 | public interface OnPreGameClickListener {
162 | public void startGame();
163 | public void cancelGame();
164 | public void leaveGame();
165 | }
166 |
167 | /**
168 | * Used by GameActivity to update the state of this Fragment.
169 | */
170 | public void addCurrentPlayers(ArrayList handles) {
171 | if (mCurrentHandles == null) {
172 | mCurrentHandles = new ArrayList();
173 | }
174 | mCurrentHandles.removeAll(handles);
175 | mCurrentHandles.addAll(handles);
176 | updatePlayersListView();
177 | }
178 |
179 | private void showGameDestroyDialog(String message) {
180 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
181 | builder.setTitle(R.string.game_abandoned_dialog_title).setMessage(message)
182 | .setNeutralButton("OK", new DialogInterface.OnClickListener() {
183 | @Override
184 | public void onClick(DialogInterface dialog, int which) {
185 | getActivity().finish();
186 | }
187 | });
188 | AlertDialog dialog = builder.create();
189 | dialog.show();
190 | }
191 |
192 | private void addCurrentPlayer(String handle) {
193 | if (mCurrentHandles == null) {
194 | mCurrentHandles = new ArrayList();
195 | }
196 | mCurrentHandles.remove(handle);
197 | mCurrentHandles.add(handle);
198 | updatePlayersListView();
199 | }
200 |
201 | private void removeCurrentPlayer(String handle) {
202 | if (mCurrentHandles != null) {
203 | mCurrentHandles.remove(handle);
204 | }
205 | updatePlayersListView();
206 | }
207 |
208 | private void updatePlayersListView() {
209 | mPlayersView.setAdapter(new ArrayAdapter(getActivity(),
210 | android.R.layout.simple_list_item_1, mCurrentHandles));
211 | if (mIsCreator) {
212 | mStartButton.setVisibility(View.VISIBLE);
213 | mCancelButton.setVisibility(View.VISIBLE);
214 | } else {
215 | mLeaveButton.setVisibility(View.VISIBLE);
216 | mStatusMessage.setVisibility(View.VISIBLE);
217 | }
218 | }
219 |
220 | private void instantiateStartButton(View v, int buttonId) {
221 | mStartButton = (Button) v.findViewById(buttonId);
222 | mStartButton.setOnClickListener(new OnClickListener() {
223 | @Override
224 | public void onClick(View v) {
225 | callback.startGame();
226 | }
227 | });
228 | }
229 |
230 | private void instantiateCancelButton(View v, int buttonId) {
231 | mCancelButton = (Button) v.findViewById(buttonId);
232 | mCancelButton.setOnClickListener(new OnClickListener() {
233 | @Override
234 | public void onClick(View v) {
235 | callback.cancelGame();
236 | }
237 | });
238 | }
239 |
240 | private void instantiateLeaveButton(View v, int buttonId) {
241 | mLeaveButton = (Button) v.findViewById(buttonId);
242 | mLeaveButton.setOnClickListener(new OnClickListener() {
243 | @Override
244 | public void onClick(View v) {
245 | callback.leaveGame();
246 | }
247 | });
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Cloud Adventure
2 | ===============
3 |
4 | Copyright
5 | ---------
6 |
7 | Copyright 2013 Google Inc. All Rights Reserved.
8 |
9 | Licensed under the Apache License, Version 2.0 (the "License");
10 | you may not use this file except in compliance with the License.
11 | You may obtain a copy of the License at
12 |
13 | [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
14 |
15 | Unless required by applicable law or agreed to in writing, software
16 | distributed under the License is distributed on an "AS IS" BASIS,
17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | See the License for the specific language governing permissions and
19 | limitations under the License.
20 |
21 |
22 | Disclaimer
23 | ----------
24 |
25 | This sample application is not an official Google product.
26 |
27 |
28 | Summary
29 | -------
30 | Cloud Adventure is a mobile game application built entirely upon Google’s Cloud Platform. This package includes the Android client code. The client code contains game logic, and it calls the endpoints provided by the server. The setup instructions in this README are the same as the ones you will find in the corresponding App Engine server package. You will need both packages for this sample to work.
31 |
32 | Supported Components
33 | --------------------
34 |
35 | Languages:
36 | Java
37 |
38 | Google Components:
39 | App Engine
40 | Cloud Endpoints
41 | Android
42 |
43 | Downloads
44 | ---------
45 |
46 | * Make sure you have Java installed.
47 | * Download and set up [Eclipse] (http://www.eclipse.org/downloads/). This sample application was built with Eclipse 3.8, but later versions are fine.
48 | * Download the [App Engine Java SDK] (http://googleappengine.googlecode.com/files/appengine-java-sdk-1.8.0.zip)
49 | * Download the [Google Plugin for Eclipse] (https://developers.google.com/eclipse/docs/getting_started) for your IDE version. Set it up using the instructions on that page.
50 | * Download the [ADT Plugin] (http://developer.android.com/tools/sdk/eclipse-adt.html). Set it up using the instructions on that page. Note: upon Eclipse restart, you may see a dialog saying that there is no Android SDK installed. If you cancel that dialog, you should see another one just below it that will prompt you to install the Android SDK.
51 |
52 | Download the following sample code:
53 | * [Android client zip file] (https://github.com/GoogleCloudPlatform/solutions-cloud-adventure-sample-android-client)
54 | * [App Engine backend zip file] (https://github.com/GoogleCloudPlatform/solutions-cloud-adventure-sample-backend-java)
55 |
56 |
57 | Creating and Setting up Projects
58 | --------------------------------
59 |
60 | #### App Engine
61 |
62 | Create a new application from the [App Engine] (https://appengine.google.com/) dashboard. If you have not developed applications using App Engine before, use the [Getting Started Guide] (https://developers.google.com/appengine/docs/java/gettingstarted/) as reference.
63 |
64 | #### API Project
65 |
66 | Create a new project from [the API console] (https://code.google.com/apis/console/). You may also use an existing project if you have one.
67 |
68 | Navigate to Services using the left-hand menu. Enable the following Services in your project:
69 |
70 | * Google Cloud Messaging for Android
71 |
72 | Navigate to API Access using the left-hand menu. Under "Simple API Access", create a new Server Key. This will generate an API key, which you will need for your application to use Google Cloud Messaging from this project. To reiterate: you need the Server Key, not the Android one. You can read more about API keys [here] (https://developers.google.com/console/help/#generatingdevkeys).
73 |
74 |
75 | Setting up Projects in Eclipse
76 | ------------------------------
77 |
78 | You should have downloaded both the client and server sample code. Extract those files.
79 |
80 | 1) You should have set up the ADT plugin (see Downloads section) prior to this point. Select Window → Android SDK Manager in Eclipse. The Android SDK Manager window will pop up.
81 |
82 | Select this version of Android:
83 | * Android 4.2.2 (API 17)
84 | Under Tools, select:
85 | * Android SDK Tools
86 | * Android SDK Platform-tools
87 | * Android SDK Build-tools (revision 17)
88 | Under Extras, select:
89 | * Android Support Library
90 | * Google Cloud Messaging for Android
91 |
92 | Install these packages. Note: you may use the latest versions beyond API 17, but be aware that this code sample was created using API 17. Also, Google Cloud Messaging for Android may show as deprecated if you use the newest version, since a new version was recently introduced.
93 |
94 | 2) Create the Android client project in Eclipse: select File → New → Project... and then select Android → Android Application Project. Input "CloudAdventure" as the Application Name. Input "com.google.cloud.solutions.cloudadventure" as the Package Name. Click through the rest of the setup, leaving the defaults as-is.
95 |
96 | 3) Create the App Engine backend project in Eclipse: right-click on the CloudAdventure project, and select Google → Generate App Engine Backend. You will need to enter in your API key and Project Number from the API project you created in the Creating and Setting up Projects section. Select App Engine version 1.8.1 or higher. This project was created using App Engine version 1.8.1.
97 |
98 | 4) In the newly-created Android client project:
99 | * Remove any pre-generated code under the src/ folder. Copy into the src/ folder the sample code from the downloaded CloudAdventure src/ folder.
100 | * Remove any pre-generated code under the res/ folder. Copy into the res/ folder the sample code from the downloaded CloudAdventure res/ folder.
101 | * Replace the root-level files with these 5 root-level files from the downloaded CloudAdventure code:
102 | > AndroidManifest.xml
103 | > ic_launcher-web.png
104 | > proguard-google-api-client.txt
105 | > proguard-project.txt
106 | > project.properties
107 | * Replacing the AndroidManifest.xml may cause Eclipse to prompt whether or not you want to accept the target changes. Select the "accept" or "OK" option.
108 |
109 | 5) In the newly-created App Engine project:
110 | * Remove any pre-generated code under the src/ folder. Copy into the src/ folder the sample code from the downloaded CloudAdventure-AppEngine src/ folder.
111 | * Leave the war/WEB-INF/ folder as it is, but remove the other pre-generated files under war/. Copy into the war/ folder the sample code from the downloaded CloudAdventure-Appengine war/ folder.
112 |
113 | 6) Generate your API library: right-click the App Engine project and select Google → Generate Cloud Endpoint Client Library. This will create an endpoint-libs/ folder in your Android client and add files there. If you run into any problems, check the Error Log View in Eclipse. Select Window → Show View → Error Log.
114 |
115 | Configuring the Sample
116 | ----------------------
117 |
118 | #### App Engine
119 |
120 | * com.google.cloud.solutions.cloudadventure.CloudMessenger.java: update the API_KEY string. This is your Server Key from the Creating and Setting up Projects section.
121 | * war/WEB-INF/appengine-web.xml: change the text in the tag to the Application Identifier of the App Engine application created in the Creating and Setting up Projects section.
122 | * Make sure your Eclipse is signed in with the same Google account that your App Engine application is created under. You can see the Google account in the lower right-hand corner of your Eclipse window. Right-click on the top-level of the project and select Google → Deploy to App Engine.
123 |
124 | #### API Project
125 |
126 | * com.google.cloud.solutions.cloudadventure.GCMIntentService.java: update the SENDER_ID string. This is the Project Number of your API project.
127 | * AndroidManifest.xml: if you used an Android API version that is higher than 17, change the text in android:targetSdkVersion to your API version.
128 | * If you want to do local testing on an emulator, you need to open CloudEndpointUtils.java and update the variable: LOCAL_ANDROID_RUN = true. Be sure to set it back to false when attempting to test on an Android device. This is not applicable to this particular code sample because it uses Google Accounts on your Android.
129 |
130 | Running the Android Application
131 | -------------------------------
132 |
133 | This mobile game uses Google Accounts from your phone to sign in. Make sure you have at least one Google Account on your phone by going to Settings → Accounts.
134 |
135 | Turn on Developer Options for your phone. This option should be in Settings, though toggling the option is a procedure that varies from phone to phone. Do a Google search for your phone on how to do this.
136 |
137 | Connect your Android phone to your computer via USB. Right-click on the top-level of the project and select Run As → Android Application. A window will pop up asking which Android device you would like to use. Select your phone from the list and run.
138 |
139 | Modifying the Code
140 | ------------------
141 |
142 | #### App Engine
143 |
144 | * Start by adding a couple fields to the data model. When you build the project (or if Build Automatically is turned on), you will find fresh .api and .discovery files in your WEB-INF directory. These files specify how your API should be generated.
145 | * You can also try adding a new API method. These are annotated with @ApiMethod and can be found the classes ending with “Endpoint.java”.
146 | * When you are done with modifying the sample data model, right-click on the top-level of this project and select Google → Generate Cloud Endpoint Library. This will take your api files and generate API Java files in your Android client under endpoint-libs/.
147 |
148 | #### API Project
149 |
150 | * You have new fields in your model, and perhaps new API methods! Use them in your Android client.
151 |
152 |
153 |
--------------------------------------------------------------------------------
/src/com/google/cloud/solutions/cloudadventure/GameScoresFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.solutions.cloudadventure;
18 |
19 | import com.google.api.client.extensions.android.http.AndroidHttp;
20 | import com.google.api.client.json.gson.GsonFactory;
21 | import com.google.api.services.cloudadventure.Cloudadventure;
22 | import com.google.api.services.cloudadventure.model.Player;
23 | import com.google.cloud.solutions.cloudadventure.util.CloudEndpointUtils;
24 |
25 | import android.app.Activity;
26 | import android.app.Fragment;
27 | import android.app.ProgressDialog;
28 | import android.content.BroadcastReceiver;
29 | import android.content.Context;
30 | import android.content.Intent;
31 | import android.content.IntentFilter;
32 | import android.os.AsyncTask;
33 | import android.os.Bundle;
34 | import android.support.v4.content.LocalBroadcastManager;
35 | import android.util.Log;
36 | import android.view.Gravity;
37 | import android.view.LayoutInflater;
38 | import android.view.View;
39 | import android.view.View.OnClickListener;
40 | import android.view.ViewGroup;
41 | import android.widget.Button;
42 | import android.widget.TableLayout;
43 | import android.widget.TableRow;
44 | import android.widget.TextView;
45 |
46 | import java.io.IOException;
47 | import java.util.List;
48 |
49 | /**
50 | * This takes place post-game and shows player scores as individual games finish.
51 | *
52 | */
53 | public class GameScoresFragment extends Fragment {
54 |
55 | /*
56 | * Endpoint service.
57 | */
58 | private Cloudadventure mService;
59 |
60 | private String mCurrentHandle;
61 |
62 | /*
63 | * View components.
64 | */
65 | private Button mHomeButton;
66 | private TableLayout mScoresTable;
67 | private ProgressDialog mProgressDialog;
68 |
69 | private static final String PLAYER_TAG_SUFFIX = "-player";
70 | private static final String GEMS_TAG_SUFFIX = "-gems";
71 | private static final String MOBS_TAG_SUFFIX = "-mobs_killed";
72 | private static final String DEATHS_TAG_SUFFIX = "-deaths";
73 |
74 | /*
75 | * Callback to GameActivity.
76 | */
77 | private OnGameScoresClickListener callback;
78 |
79 | /**
80 | * Receives messages for player end-game statistics.
81 | */
82 | private BroadcastReceiver mStatsMsgReceiver = new BroadcastReceiver() {
83 | @Override
84 | public void onReceive(Context context, Intent intent) {
85 | Log.i("GameScoresActivity", "Got a player scores message via broadcast.");
86 | Player player = new Player();
87 | player.setHandle(intent.getStringExtra(GCMIntentService.GCM_PAYLOAD_FROM_USER_HANDLE));
88 | player.setGemsCollected(Long.parseLong(intent.getStringExtra("gems")));
89 | player.setMobsKilled(Long.parseLong(intent.getStringExtra("mobs_killed")));
90 | player.setNumDeaths(Long.parseLong(intent.getStringExtra("deaths")));
91 | addPlayerScore(player);
92 | mProgressDialog.dismiss();
93 | }
94 | };
95 |
96 | @Override
97 | public void onAttach(Activity activity) {
98 | super.onAttach(activity);
99 |
100 | // Set the callback activity to use
101 | try {
102 | callback = (OnGameScoresClickListener) activity;
103 | } catch (ClassCastException e) {
104 | throw new ClassCastException(activity.toString()
105 | + " must implement OnGameScoresClickListener");
106 | }
107 | }
108 |
109 | @Override
110 | public View onCreateView(
111 | LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
112 | Log.d("GameScoresFragment State", "onCreateView");
113 |
114 | // Set component views
115 | final View v = inflater.inflate(R.layout.fragment_game_scores, container, false);
116 | mProgressDialog = new ProgressDialog(getActivity());
117 | mProgressDialog.setCanceledOnTouchOutside(false);
118 | mScoresTable = (TableLayout) v.findViewById(R.id.player_end_scores_table);
119 | mHomeButton = (Button) v.findViewById(R.id.return_home_button);
120 | mHomeButton.setOnClickListener(new OnClickListener() {
121 | @Override
122 | public void onClick(View v) {
123 | returnHome();
124 | }
125 | });
126 |
127 | // Register the broadcast receivers from GCMIntentService
128 | LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mStatsMsgReceiver,
129 | new IntentFilter(GCMIntentService.BROADCAST_ON_MESSAGE_PLAYER_END_STATS));
130 |
131 | // Build the endpoint service
132 | Cloudadventure.Builder builder =
133 | new Cloudadventure.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), null);
134 | CloudEndpointUtils.updateBuilder(builder);
135 | mService = builder.build();
136 |
137 | mProgressDialog.show();
138 |
139 | return v;
140 | }
141 |
142 | @Override
143 | public void onPause() {
144 | new RemovePlayerAndCleanUp().execute(mCurrentHandle);
145 | super.onPause();
146 | }
147 |
148 | @Override
149 | public void onDestroy() {
150 | Log.d("GameScoresFragment State", "onDestroy");
151 | LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mStatsMsgReceiver);
152 | super.onDestroy();
153 | }
154 |
155 | /**
156 | * A listener interface meant for GameActivity, process the action this player makes.
157 | *
158 | */
159 | public interface OnGameScoresClickListener {
160 | public void returnHome();
161 | }
162 |
163 | /**
164 | * Used by GameActivity to update the state of this Fragment.
165 | */
166 | public void setCurrentUserHandle(String handle) {
167 | this.mCurrentHandle = handle;
168 | }
169 |
170 | /**
171 | * Used by GameActivity to update the state of this Fragment.
172 | *
173 | * This should be called each time the {@link Tile} that the {@link Player} is standing on is
174 | * updated, in order to ensure that the information and views are properly updated.
175 | */
176 | public void reportRetrievalIssue() {
177 | getView().findViewById(R.id.scores_retrieval_issue).setVisibility(View.VISIBLE);
178 | getView().findViewById(R.id.player_end_scores_table).setVisibility(View.INVISIBLE);
179 | }
180 |
181 | /**
182 | * Used by GameActivity to update the state of this Fragment. The list of players is taken from
183 | * all players that were currently listed in the Datastore as being in the game at end game.
184 | * Only update the player if the player hasn't been recorded in this table yet; if the player
185 | * is already in the table, it means a ping has been received containing the most updated info.
186 | *
187 | * Adds the scores of a list of players.
188 | */
189 | public void addPlayersScores(List players) {
190 | for (Player player : players) {
191 | if (getView().findViewWithTag(player.getHandle()) == null) {
192 | updateScoresTable(player);
193 | }
194 | }
195 | }
196 |
197 | /**
198 | * Adds the scores of this player. This method is called through a ping from a receiver.
199 | * The ping is always the most updated information, so always update.
200 | */
201 | private void addPlayerScore(Player player) {
202 | String handle = player.getHandle();
203 | if (getView().findViewWithTag(handle) == null) {
204 | updateScoresTable(player);
205 | } else {
206 | TextView text = (TextView) getView().findViewWithTag(handle + GEMS_TAG_SUFFIX);
207 | text.setText(Long.toString(player.getGemsCollected()));
208 | text = (TextView) getView().findViewWithTag(handle + MOBS_TAG_SUFFIX);
209 | text.setText(Long.toString(player.getMobsKilled()));
210 | text = (TextView) getView().findViewWithTag(handle + DEATHS_TAG_SUFFIX);
211 | text.setText(Long.toString(player.getNumDeaths()));
212 | }
213 | }
214 |
215 | /**
216 | * Updates the View for showing the player scores.
217 | *
218 | * @param player the player whose scores have been updated
219 | */
220 | private void updateScoresTable(Player player) {
221 | String handle = player.getHandle();
222 | TableRow row = new TableRow(getActivity());
223 | row.setTag(handle);
224 | TextView text = new TextView(getActivity());
225 | text.setTag(handle + PLAYER_TAG_SUFFIX);
226 | text.setGravity(Gravity.CENTER);
227 | text.setText(handle);
228 | row.addView(text);
229 | text = new TextView(getActivity());
230 | text.setTag(handle + GEMS_TAG_SUFFIX);
231 | text.setGravity(Gravity.CENTER);
232 | text.setText(Long.toString(player.getGemsCollected()));
233 | row.addView(text);
234 | text = new TextView(getActivity());
235 | text.setTag(handle + MOBS_TAG_SUFFIX);
236 | text.setGravity(Gravity.CENTER);
237 | text.setText(Long.toString(player.getMobsKilled()));
238 | row.addView(text);
239 | text = new TextView(getActivity());
240 | text.setTag(handle + DEATHS_TAG_SUFFIX);
241 | text.setGravity(Gravity.CENTER);
242 | text.setText(Long.toString(player.getNumDeaths()));
243 | row.addView(text);
244 | mScoresTable.addView(row);
245 | }
246 |
247 | /**
248 | * Returns the user to the main screen.
249 | */
250 | private void returnHome() {
251 | callback.returnHome();
252 | }
253 |
254 | /*
255 | * AsyncTasks.
256 | */
257 |
258 | private class RemovePlayerAndCleanUp extends AsyncTask {
259 | @Override
260 | protected Void doInBackground(String... handles) {
261 | try {
262 | mService.players().remove(handles[0]).execute();
263 | } catch (IOException e) {
264 | Log.e("ProfileActivity", "RemovePlayerAndCleanUp error: " + e.getMessage(), e);
265 | }
266 | return null;
267 | }
268 | }
269 | }
270 |
--------------------------------------------------------------------------------
/src/com/google/cloud/solutions/cloudadventure/PlayerActionsFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.cloud.solutions.cloudadventure;
18 |
19 | import com.google.api.services.cloudadventure.model.Pickup;
20 | import com.google.api.services.cloudadventure.model.Tile;
21 | import com.google.cloud.solutions.cloudadventure.widget.CustomArrayAdapter;
22 |
23 | import android.app.Activity;
24 | import android.app.AlertDialog;
25 | import android.app.Fragment;
26 | import android.content.DialogInterface;
27 | import android.os.Bundle;
28 | import android.view.LayoutInflater;
29 | import android.view.View;
30 | import android.view.View.OnClickListener;
31 | import android.view.ViewGroup;
32 | import android.widget.Button;
33 |
34 | import java.util.ArrayList;
35 | import java.util.List;
36 |
37 | /**
38 | * This Fragment belongs to GameActivity and provides controls for user actions in the game.
39 | *
40 | */
41 | public class PlayerActionsFragment extends Fragment {
42 |
43 | private List