diff --git a/appengine/channel/src/main/java/com/example/appengine/channel/ChannelPresenceServlet.java b/appengine/channel/src/main/java/com/example/appengine/channel/ChannelPresenceServlet.java
new file mode 100644
index 00000000000..2aafb433e86
--- /dev/null
+++ b/appengine/channel/src/main/java/com/example/appengine/channel/ChannelPresenceServlet.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016 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.example.appengine.channel;
+
+import com.google.appengine.api.channel.ChannelPresence;
+import com.google.appengine.api.channel.ChannelService;
+import com.google.appengine.api.channel.ChannelServiceFactory;
+
+import java.io.IOException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class ChannelPresenceServlet extends HttpServlet {
+ @Override
+ public void doPost(HttpServletRequest req, HttpServletResponse resp)
+ throws IOException {
+ //[START channel_presence]
+ ChannelService channelService = ChannelServiceFactory.getChannelService();
+ ChannelPresence presence = channelService.parsePresence(req);
+ //[END channel_presence]
+
+ System.out.println("Client ID: " + presence.clientId()
+ + ", Connected: " + presence.isConnected());
+ resp.setStatus(HttpServletResponse.SC_OK);
+ }
+}
diff --git a/appengine/channel/src/main/java/com/example/appengine/channel/Game.java b/appengine/channel/src/main/java/com/example/appengine/channel/Game.java
index c35ac6a2429..81956d28755 100644
--- a/appengine/channel/src/main/java/com/example/appengine/channel/Game.java
+++ b/appengine/channel/src/main/java/com/example/appengine/channel/Game.java
@@ -115,8 +115,9 @@ public String getMessageString() {
return message.toString();
}
+ //[START send_updates]
public String getChannelKey(String user) {
- return user + id;
+ return user + "." + id;
}
private void sendUpdateToUser(String user) {
@@ -131,6 +132,7 @@ public void sendUpdateToClients() {
sendUpdateToUser(userX);
sendUpdateToUser(userO);
}
+ //[END send_updates]
public void checkWin() {
final Pattern[] wins;
@@ -152,6 +154,7 @@ public void checkWin() {
}
}
+ //[START make_move]
public boolean makeMove(int position, String user) {
String currentMovePlayer;
char value;
@@ -175,4 +178,5 @@ public boolean makeMove(int position, String user) {
return false;
}
+ //[END make_move]
}
diff --git a/appengine/channel/src/main/java/com/example/appengine/channel/TicTacToeServlet.java b/appengine/channel/src/main/java/com/example/appengine/channel/TicTacToeServlet.java
index 201d71c9910..c27c9744064 100644
--- a/appengine/channel/src/main/java/com/example/appengine/channel/TicTacToeServlet.java
+++ b/appengine/channel/src/main/java/com/example/appengine/channel/TicTacToeServlet.java
@@ -82,9 +82,15 @@ public void doGet(HttpServletRequest req, HttpServletResponse resp)
gameKey = game.getId();
}
+ //[START channel_service]
ChannelService channelService = ChannelServiceFactory.getChannelService();
+
+ // The 'Game' object exposes a method which creates a unique string based on the game's key
+ // and the user's id.
String token = channelService.createChannel(game.getChannelKey(userId));
+ //[END channel_service]
+
ofy.save().entity(game).now();
req.setAttribute("game_key", gameKey);
diff --git a/appengine/channel/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/channel/src/main/webapp/WEB-INF/appengine-web.xml
index e4b0ccdddd7..aaabe2237c9 100644
--- a/appengine/channel/src/main/webapp/WEB-INF/appengine-web.xml
+++ b/appengine/channel/src/main/webapp/WEB-INF/appengine-web.xml
@@ -23,5 +23,11 @@
+
+
+
+ channel_presence
+
+
diff --git a/appengine/channel/src/main/webapp/WEB-INF/view/index.jsp b/appengine/channel/src/main/webapp/WEB-INF/view/index.jsp
index 78e6ee6aa28..af33d85b7f9 100644
--- a/appengine/channel/src/main/webapp/WEB-INF/view/index.jsp
+++ b/appengine/channel/src/main/webapp/WEB-INF/view/index.jsp
@@ -154,6 +154,7 @@
return state.userX == state.me ? 'X' : 'O';
}
+ //[START send_message]
sendMessage = function(path, opt_param) {
path += '?gamekey=' + state.game_key;
if (opt_param) {
@@ -163,12 +164,15 @@
xhr.open('POST', path, true);
xhr.send();
};
+ //[END send_message]
+ //[START move_in_square]
moveInSquare = function(id) {
if (isMyMove() && state.board[id] == ' ') {
sendMessage('/move', 'i=' + id);
}
}
+ //[END move_in_square]
highlightSquare = function(id) {
if (state.winner != "") {
@@ -205,6 +209,7 @@
}
openChannel = function() {
+ //[START open_channel]
var token = '<%= request.getAttribute("token") %>';
var channel = new goog.appengine.Channel(token);
var handler = {
@@ -216,6 +221,7 @@
var socket = channel.open(handler);
socket.onopen = onOpened;
socket.onmessage = onMessage;
+ //[END open_channel]
}
initialize = function() {
diff --git a/appengine/channel/src/main/webapp/WEB-INF/web.xml b/appengine/channel/src/main/webapp/WEB-INF/web.xml
index 4e24e305c23..ea2d3e72f10 100644
--- a/appengine/channel/src/main/webapp/WEB-INF/web.xml
+++ b/appengine/channel/src/main/webapp/WEB-INF/web.xml
@@ -42,6 +42,18 @@ http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
MoveServlet
/move
+
+ ChannelPresenceServlet
+ com.example.appengine.channel.ChannelPresenceServlet
+
+
+ ChannelPresenceServlet
+ /_ah/channel/connected/
+
+
+ ChannelPresenceServlet
+ /_ah/channel/disconnected/
+
ObjectifyFilter