ฉันได้ติดตั้ง GCM CCS ใหม่สำหรับข้อความแบบสองทิศทางระหว่างแอปพลิเคชัน Android และเว็บเซิร์ฟเวอร์ ข้อความดาวน์สตรีม (อุปกรณ์เว็บ) ทำงานได้อย่างสมบูรณ์ ขออภัย ไม่ได้รับข้อความอัปสตรีม (อุปกรณ์-เว็บ) บนเซิร์ฟเวอร์ ดูเหมือนว่าจะถูกส่งทางฝั่งไคลเอ็นต์ (ดูข้อความบันทึกแอป Android ด้านล่าง) แต่ไม่ได้รับสิ่งใดบนเซิร์ฟเวอร์
D/GCM﹕ GcmService start Intent { act=com.google.android.gcm.intent.SEND flg=0x10 pkg=com.google.android.gms cmp=com.google.android.gms/.gcm.GcmService (has extras) } com.google.android.gcm.intent.SEND
ฉันคิดว่าไม่มีอะไรผิดปกติในฝั่ง Android แต่อยู่ที่ฝั่งเซิร์ฟเวอร์ ประเด็นก็คือ ฉันไม่สามารถเข้าใจได้ว่ามีอะไรผิดปกติ เนื่องจากการเชื่อมต่อยังคงมีอยู่ และฉันได้รับข้อความบางส่วนจากเซิร์ฟเวอร์ GCM เช่น ACK เหตุใดจึงไม่ได้รับข้อความปกติ ไม่มีใครมีความคิดใด ๆ ?
รายละเอียดอื่น ๆ ที่ควรกล่าวถึงคือเว็บเซิร์ฟเวอร์ที่ใช้คือ Glassfish และฉันเริ่มการเชื่อมต่อ XMPP ภายใน Servlet ตัวอย่างบางส่วนด้านล่าง
แก้ไข: ดังที่ฉันได้ระบุไว้ในคำตอบ ปัญหาหลักที่ทำให้ไม่สามารถรับข้อความ ใด ๆ บนเซิร์ฟเวอร์ได้รับการแก้ไขแล้ว อย่างไรก็ตาม ยังไม่ได้รับข้อความจำนวนมาก (ประมาณ 50%)
ตัวอย่างเช่น ฉันกำลังส่งข้อความ 2 ข้อความติดต่อกันบนเธรดพื้นหลัง ทุกครั้งที่ผู้ใช้ทำการเปลี่ยนแปลงในแอป Android (กดปุ่ม ดังนั้นจะมีเวลาสองสามวินาทีขั้นต่ำระหว่างทุก ๆ 2 ชุด) บางครั้งฉันได้รับข้อความทั้งสองบนเซิร์ฟเวอร์ บางครั้งฉันได้รับเพียงข้อความเดียว บางครั้งไม่มีอะไรเกิดขึ้น... นี่เป็นปัญหาร้ายแรง โดยเฉพาะอย่างยิ่งสำหรับแอปที่ใช้เทคโนโลยีนี้เป็นหลัก ใครสามารถให้ความช่วยเหลือเพิ่มเติมเพื่อแก้ไขปัญหานี้ได้หรือไม่
ข้อมูลเพิ่มเติม: ฉันค่อนข้างแน่ใจว่านี่ ไม่ เกี่ยวข้องกับลูกค้า เนื่องจากทุกข้อความถูกส่งไป เหมือนที่คุณเห็นในบันทึก logcat ด้านบน และฉันยังได้รับ "เหตุการณ์" :sent" ออกอากาศ GCM หลังจากนั้นไม่นาน (แต่ไม่ใช่ทันที อาจประมาณ 5 นาที) ดังนั้นจึงต้องเป็นแบบ GCM หรือแบบเซิร์ฟเวอร์
public class CcsServlet extends HttpServlet
{
private static Logger logger = Logger.getLogger(CcsServlet.class.getName());
public void init(ServletConfig config) throws ServletException
{
CcsManager ccsManager = CcsManager.getInstance();
try
{
ccsManager.connect();
}
catch (Exception e)
{
logger.warning("Cannot connect to CCS server.");
e.printStackTrace();
}
}
}
public class CcsManager
{
private static XMPPConnection connection;
private static Logger logger = Logger.getLogger(CcsManager.class.getName());
public static final String GCM_SERVER = "gcm.googleapis.com";
public static final int GCM_PORT = 5235;
private static CcsManager sInstance = null;
private static final String USERNAME = "xxxxxxxxxx" + "@gcm.googleapis.com";
private static final String PASSWORD = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
public CcsManager()
{
// Add GcmPacketExtension
ProviderManager.getInstance().addExtensionProvider(
GcmPacketExtension.GCM_ELEMENT_NAME,
GcmPacketExtension.GCM_NAMESPACE, new PacketExtensionProvider()
{
public PacketExtension parseExtension(XmlPullParser parser) throws Exception
{
String json = parser.nextText();
return new GcmPacketExtension(json);
}
});
}
public static CcsManager getInstance()
{
if (sInstance == null)
sInstance = new CcsManager();
return sInstance;
}
/**
* Connects to GCM Cloud Connection Server
*/
public void connect() throws IOException, XMPPException
{
ConnectionConfiguration config = new ConnectionConfiguration(GCM_SERVER, GCM_PORT);
config.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled);
config.setReconnectionAllowed(true);
config.setRosterLoadedAtLogin(false);
config.setSendPresence(false);
config.setSocketFactory(SSLSocketFactory.getDefault());
config.setDebuggerEnabled(false);
connection = new XMPPConnection(config);
connection.connect();
connection.addConnectionListener(new ConnectionListener()
{
public void reconnectionSuccessful()
{
logger.info("Reconnecting..");
}
public void reconnectionFailed(Exception e)
{
logger.log(Level.INFO, "Reconnection failed.. ", e);
}
public void reconnectingIn(int seconds)
{
logger.log(Level.INFO, "Reconnecting in %s secs", seconds);
}
public void connectionClosedOnError(Exception e)
{
logger.info("Connection closed on error.");
}
public void connectionClosed()
{
logger.info("Connection closed.");
}
});
// Handle incoming packets
connection.addPacketListener(new PacketListener()
{
public void processPacket(Packet packet)
{
logger.log(Level.INFO, "Received: " + packet.toXML());
Message incomingMessage = (Message) packet;
GcmPacketExtension gcmPacket =
(GcmPacketExtension) incomingMessage.getExtension(GcmPacketExtension.GCM_NAMESPACE);
String json = gcmPacket.getJson();
try
{
@SuppressWarnings("unchecked")
Map<String, Object> jsonObject =
(Map<String, Object>) JSONValue.parseWithException(json);
// present for "ack"/"nack", null otherwise
Object messageType = jsonObject.get("message_type");
if (messageType == null)
{
// Normal upstream data message
handleIncomingDataMessage(jsonObject);
// Send ACK to CCS
String messageId = jsonObject.get("message_id").toString();
String from = jsonObject.get("from").toString();
String ack = createJsonAck(from, messageId);
send(ack);
}
else if ("ack".equals(messageType.toString()))
{
// Process Ack
handleAckReceipt(jsonObject);
}
else if ("nack".equals(messageType.toString()))
{
// Process Nack
handleNackReceipt(jsonObject);
}
else
{
logger.log(Level.WARNING, "Unrecognized message type (%s)",
messageType.toString());
}
}
catch (ParseException e)
{
logger.log(Level.SEVERE, "Error parsing JSON " + json, e);
}
catch (Exception e)
{
logger.log(Level.SEVERE, "Couldn't send echo.", e);
}
}
}, new PacketTypeFilter(Message.class));
// Log all outgoing packets
connection.addPacketInterceptor(new PacketInterceptor()
{
public void interceptPacket(Packet packet)
{
logger.log(Level.INFO, "Sent: {0}", packet.toXML());
}
}, new PacketTypeFilter(Message.class));
connection.login(USERNAME, PASSWORD);
}
}