Saya telah menerapkan GCM CCS baru untuk pesan dua arah antara aplikasi Android dan server web. Pesan hilir (perangkat web) berfungsi dengan sempurna. Sayangnya, pesan upstream (web perangkat) tidak diterima di server. Mereka tampaknya dikirim pada sisi klien (lihat pesan log aplikasi Android di bawah), namun tidak ada yang diterima di server.
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
Saya kira tidak ada yang salah di sisi Android, melainkan di sisi server. Masalahnya adalah, saya tidak dapat mencari tahu apa yang salah, karena koneksi masih aktif dan saya menerima beberapa pesan dari server GCM, seperti ACK. Jadi mengapa pesan normal tidak diterima? Apakah ada yang tahu?
Beberapa detail lain yang perlu disebutkan adalah bahwa server web yang digunakan adalah Glassfish dan saya memulai koneksi XMPP di dalam Servlet. Beberapa cuplikan di bawah ini.
EDIT: Seperti yang telah saya nyatakan dalam jawaban, masalah besar yang mencegah setiap pesan diterima di server telah teratasi. Namun cukup banyak pesan yang masih belum diterima (sekitar 50%).
Misalnya, saya mengirim 2 pesan sekaligus satu demi satu di thread latar belakang, setiap kali pengguna membuat perubahan di aplikasi Android (menekan tombol, jadi ada jeda minimal beberapa detik di antara setiap kumpulan 2 pesan). Terkadang saya menerima kedua pesan di server, terkadang saya hanya menerima 1 pesan, terkadang bahkan tidak terjadi apa-apa... Ini adalah masalah serius, terutama untuk aplikasi yang mengandalkan teknologi ini pada intinya. Adakah yang bisa membantu lebih lanjut untuk memecahkan masalah ini?
Info lebih lanjut: Saya cukup yakin ini tidak terkait dengan klien, karena setiap pesan dikirim, seperti yang Anda lihat di log logcat di atas dan saya juga menerima "peristiwa : terkirim" GCM disiarkan setelah beberapa saat (meskipun tidak segera, mungkin sekitar 5 menit). Jadi itu harus berbasis GCM atau berbasis server.
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);
}
}