Google GCM XMPP代码示例 [英] Google GCM XMPP code samples

查看:181
本文介绍了Google GCM XMPP代码示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,Google曾经有一个很好的页面,他们提供了关于如何在此页面上实施GCM Xmpp服务器的代码示例:
https://developers.google.com/cloud-messaging/ccs



我已将此答案加入书签任何时候我想要查看实现
对Google GCM XMPP的困惑 a>



但是那个答案中的所有东西都没有了。谷歌删除了它们。



但是现在,他们已经删除了所有内容,并添加了一个页面来解释它的功能。当然,但是示例java代码会很好。我试图去github上的示例站点,他们链接到
https://github.com/ google / gcm



但它仅提供HTTP GCM服务器版本的示例。

请有人指点我一个有效的代码示例吗?或者有没有一个库可以在C#中工作?如果不是的话,我也只会解决Java版本。



谢谢。

解决方案

下面是我为一个类示例编写的一个示例(删除了一些非XMPP部分以保持足够小,发布代码,但在 http://people.eku.edu/styere/GcmPushServer拥有完整的服务器.java ):

  //派生自https://developer.android.com/google/gcm/ ccs.html 

import javax.swing。*;
import java.awt。*;
import java.awt.event。*;
// import javax.swing.JScrollPane;
// import javax.swing.SwingUtilities;

导入org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketInterceptor;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
导入org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.DefaultPacketExtension;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.util.StringUtils;
import org.json.simple.JSONValue;
import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;
import org.xmlpull.v1.XmlPullParser;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Random;
导入java.net。*;
import java.io. *;
import java.util。*;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.HttpsURLConnection;

//所有用户和相关设备的列表
class UserList {
//(--deleted--)

//构造函数/读现有数据来自文件
public UserList(){
//(--deleted--)
}

//向现有用户添加新设备(从网络线程调用)
//重复的ID被安静地接受
public synchronized void addDevice(String uname,String newRegToken){
//(--deleted--)
}

//生成组地址/通知键
// !!!!!!!!!!!!!!!警告 !!!!!!!!!!!!!!!
//如果组地址/通知键丢失,它当前不能被恢复/重建
public String createNotificationKey(String nKeyName,String addr){
String [] idset = new String [ 1];
idset [0] = addr;

String newGroupAddr;

尝试{
//创建https连接以创建notification_key
网址url =新网址(https://android.googleapis.com/gcm/notification) ;
HttpsURLConnection conn =(HttpsURLConnection)url.openConnection();

//作为POST请求发送
conn.setRequestMethod(POST);

//添加请求参数
conn.addRequestProperty(project_id,+ GcmPushServer.senderId);
conn.addRequestProperty(Authorization,key =+ GcmPushServer.password);
//使用set,因为这可能已经存在
conn.setRequestProperty(Content-Type,application / json);

//创建要发送的数据
Map< String,Object> sendData = new HashMap<>();

//创建一个新的通知键
sendData.put(operation,create);
sendData.put(notification_key_name,(--deleted--));
sendData.put(registration_ids,(--deleted--));

String strData = JSONValue.toJSONString(sendData);

//发送帖子请求
conn.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(strData);
wr.flush();
wr.close();

//成功了吗?
int rc = conn.getResponseCode();
//System.out.println(\"ResponseCode =+ rc);

//读取响应
扫描仪输入=新扫描仪(conn.getInputStream());
String resp =;

//读取/显示行
while(input.hasNextLine()){
String s = input.nextLine();
resp + = s;
}

//System.out.println(\"Response content:+ resp);

if(rc == HttpsURLConnection.HTTP_OK){
JSONObject obj =(JSONObject)JSONValue.parse(resp);

newGroupAddr =(String)obj.get(notification_key);
//System.out.println(new notification_key:+ newGroupAddr);
返回newGroupAddr;
} else {

}
} catch(Exception e){
//System.out.println(\"-- Exception:+ e.getMessage( ));
}

返回null;
}

//向通知键添加/删除单个地址
//(如果doAdd为true,则添加,否则删除)
//删除最终地址将静静地删除键
public static void modifyNotificationKey(String nKeyName,String nKey,
String addr,boolean doAdd){
String [] idset = new String [1];
idset [0] = addr;

尝试{
//创建https连接以创建notification_key
网址url =新网址(https://android.googleapis.com/gcm/notification) ;
HttpsURLConnection conn =(HttpsURLConnection)url.openConnection();

//作为POST请求发送
conn.setRequestMethod(POST);

//添加请求参数
conn.addRequestProperty(project_id,+ GcmPushServer.senderId);
conn.addRequestProperty(Authorization,key =+ GcmPushServer.password);
//使用set,因为这可能已经存在
conn.setRequestProperty(Content-Type,application / json);

//创建要发送的数据
Map< String,Object> sendData = new HashMap<>();

//创建一个新的通知键
sendData.put(operation,doAdd?add:remove); //添加或删除密钥?
sendData.put(notification_key_name,(--deleted--));
sendData.put(notification_key,(--deleted--));
sendData.put(registration_ids,(--deleted--));

String strData = JSONValue.toJSONString(sendData);
//System.out.println(\"genGroupAddress POST data:+ strData);

//发送帖子请求
conn.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(strData);
wr.flush();
wr.close();

//conn.openConnection();

//成功了吗?
int rc = conn.getResponseCode();
//System.out.println(\"ResponseCode =+ rc);

扫描仪输入=新扫描仪(conn.getInputStream());

//读取/显示行
while(input.hasNextLine()){
System.out.println(Response content:);
String s = input.nextLine();
System.out.println(s);
}
} catch(Exception e){
// do nothing
}
}
}

// text日志消息的区域
class LogTextArea扩展JTextArea {
//用指定消息更新log
public void logMessage(String msg){
//(--deleted - )
}
}

class CcsServer {
private static final String GCM_SERVER =gcm.googleapis.com;
private static final int GCM_PORT = 5235;

private static final String GCM_ELEMENT_NAME =gcm;
private static final String GCM_NAMESPACE =google:mobile:data;

//显示/记录区域
LogTextArea logArea;
UserList用户;

CcsServer(LogTextArea lta,UserList u){
logArea = lta;
users = u;

$ b $ {
ProviderManager.addExtensionProvider(GCM_ELEMENT_NAME,GCM_NAMESPACE,
new PacketExtensionProvider(){
@Override
public PacketExtension parseExtension( XmlPullParser解析器)抛出
异常{
字符串json = parser.nextText();
返回新的GcmPacketExtension(json);
}
});
}

私有XMPPConnection连接;

/ **
*表示连接是否处于排空状态,这意味着
*不会接受任何新的下游消息。
* /
保护volatile boolean connectionDraining = false;

/ **
*向GCM发送下游消息。
*
* @如果邮件已成功发送,则返回true。
* /
public boolean sendDownstreamMessage(String jsonRequest)throws
NotConnectedException {
if(!connectionDraining){
send(jsonRequest);
返回true;
}
logArea.logMessage(由于连接正在耗尽而丢弃下游消息);
返回false;
}

/ **
*返回一个随机消息ID来唯一标识一条消息。
*
*< p>注意:这是由伪随机数生成器生成的,用于
*插图的目的,并不保证是唯一的。
* /
public String nextMessageId(){
returnm-+ UUID.randomUUID()。toString();
}

/ **
*发送包含所提供内容的数据包。
* /
protected void send(String jsonRequest)throws NotConnectedException {
数据包请求= new GcmPacketExtension(jsonRequest).toPacket();
connection.sendPacket(request);
}

/ **
*处理来自设备应用程序的上游数据消息。
*
*< p>此示例回显服务器将回显消息发送回设备。
*子类应该重写此方法以正确处理上游消息。
* /
protected void handleUpstreamMessage(Map< String,Object> jsonObject){
//发送此消息的应用程序的PackageName。
String category =(String)jsonObject.get(category);
String from =(String)jsonObject.get(from);
@SuppressWarnings(unchecked)
Map< String,String> payload =(Map< String,String>)jsonObject.get(data);

//这是什么类型的上游信息?
if(!payload.containsKey(my_action))
{
//嗯 - 这不应该发生!
logArea.logMessage(handleUpstreamMessage - 传入消息缺少my_action);
//只是忽略消息
return;
}

//他们想要什么动作?
String my_action =(String)payload.get(my_action);
if(my_action.equals(edu.eku.styere.gcmpushclient.REGISTER)){
//注册请求
字符串username =(String)payload.get(username) ;

logArea.logMessage(Registration request:user =+ username +,ID / Token =+ from);

//保存信息
users.addDevice(username,from);

return;
} else {
//采取默认回应消息的动作
payload.put(ECHO,Application:+ category);

//发送一个ECHO回应
String echo = createJsonMessage(from,nextMessageId(),payload,
echo:CollapseKey,null,false);

尝试{
sendDownstreamMessage(echo);
} catch(NotConnectedException e){
logArea.logMessage(不再连接,echo消息不发送:+ e.getMessage());
}
}
}

/ **
*处理ACK。
*
*< p>记录一条INFO消息,但子类可以覆盖它为
*正确处理ACK。
* /
protected void handleAckReceipt(Map< String,Object> jsonObject){
String messageId =(String)jsonObject.get(message_id);
String from =(String)jsonObject.get(from);
logArea.logMessage(handleAckReceipt()from:+ from +,messageId:+ messageId);
}

/ **
*处理一个NACK。
*
*< p>记录一条INFO消息,但是子类可以覆盖它到
*正确处理NACK。
* /
protected void handleNackReceipt(Map< String,Object> jsonObject){
String messageId =(String)jsonObject.get(message_id);
String from =(String)jsonObject.get(from);
logArea.logMessage(handleNackReceipt()from:+ from +,messageId:+ messageId);

$ b $ protected void handleControlMessage(Map< String,Object> jsonObject){
logArea.logMessage(handleControlMessage():+ jsonObject);
String controlType =(String)jsonObject.get(control_type);
if(CONNECTION_DRAINING.equals(controlType)){
connectionDraining = true;
} else {
logArea.logMessage(无法识别的控制类型:+ controlType +。如果新功能+添加到CCS协议中,可能会发生+
。 );
}
}

/ **
*创建一个JSON编码的GCM消息。
*
* @param到目标设备的RegistrationId(必需)。
* @param messageId CCS发送
*ack / nack唯一的messageId(必需)。
* @param payload用于应用程序的消息内容。 (可选的)。
* @param collapseKey GCM collapse_key参数(可选)。
* @param timeToLive GCM time_to_live参数(可选)。
* @param delayWhileIdle GCM delay_while_idle参数(可选)。
* @返回JSON编码的GCM消息。
* /
public static String createJsonMessage(String to,String messageId,
Map< String,String> payload,String collapseKey,Long timeToLive,
Boolean delayWhileIdle){
Map< String,Object> message = new HashMap< String,Object>();
message.put(to,to);
if(collapseKey!= null){
message.put(collapse_key,collapseKey);

if(timeToLive!= null){
message.put(time_to_live,timeToLive);

if(delayWhileIdle!= null&& delayWhileIdle){
message.put(delay_while_idle,true);
}
message.put(message_id,messageId);
message.put(data,payload);
return JSONValue.toJSONString(message);
}

/ **
*为来自应用程序的上游消息
*创建JSON编码的ACK消息。
*
* @param发送给发送上行消息的设备的RegistrationId。
* @param messageId要向CCS确认的上游消息的messageId。
* @return JSON编码的ack。
* /
protected String createJsonAck(String to,String messageId){
Map< String,Object> message = new HashMap< String,Object>();
message.put(message_type,ack);
message.put(to,to);
message.put(message_id,messageId);
return JSONValue.toJSONString(message);
}

/ **
*使用提供的凭证连接到GCM云连接服务器。
*
* @param senderId您的GCM项目编号
* @param apiKey您项目的API密钥
* /
public void connect(long senderId,String apiKey)
抛出XMPPException,IOException,SmackException {
ConnectionConfiguration config =
new ConnectionConfiguration(GCM_SERVER,GCM_PORT);
config.setSecurityMode(SecurityMode.enabled);
config.setReconnectionAllowed(true);
config.setRosterLoadedAtLogin(false);
config.setSendPresence(false);
config.setSocketFactory(SSLSocketFactory.getDefault());

connection = new XMPPTCPConnection(config);
connection.connect();

connection.addConnectionListener(new LoggingConnectionListener());

//处理传入数据包
connection.addPacketListener(new PacketListener(){

@Override
public void processPacket(Packet packet){
logArea.logMessage(Received:+ packet.toXML());
Message incomingMessage =(Message)包;
GcmPacketExtension gcmPacket =
(GcmPacketExtension)incomingMessage。
getExtension(GCM_NAMESPACE);
String json = gcmPacket.getJson();
try {
@SuppressWarnings(unchecked)
Map< String,Object> jsonObject =
(Map< String,Object>)JSONValue。
parseWithException(json);

//表示ack/nack,否则为null
Object messageType = jsonObject获得(message_t YPE);

if(messageType == null){
//正常上游数据消息
handleUpstreamMessage(jsonObject);

//发送ACK到CCS
字符串messageId =(String)jsonObject.get(message_id);
String from =(String)jsonObject.get(from);
String ack = createJsonAck(from,messageId);
send(ack);
} else if(ack.equals(messageType.toString())){
//进程确认
handleAckReceipt(jsonObject);
} else if(nack.equals(messageType.toString())){
// Process Nack
handleNackReceipt(jsonObject);
} else if(control.equals(messageType.toString())){
//过程控制消息
handleControlMessage(jsonObject);
} else {
logArea.logMessage(Unrecognized message type:+
messageType.toString());

} catch(ParseException e){
logArea.logMessage(Error parsing JSON+ json);
} catch(Exception e){
logArea.logMessage(无法处理数据包);
}
}
},新的PacketTypeFilter(Message.class));

//记录所有传出数据包
connection.addPacketInterceptor(new PacketInterceptor(){
@Override
public void interceptPacket(Packet packet){
logArea .logMessage(Sent:+ packet.toXML());
}
},new PacketTypeFilter(Message.class));

connection.login(senderId +@ gcm.googleapis.com,apiKey);
}

// ----------支持类----------

/ ** $ b GCM云连接服务器的$ b * XMPP数据包扩展。
* /
private static class GcmPacketExtension extends DefaultPacketExtension {

private final String json;

public GcmPacketExtension(String json){
super(GCM_ELEMENT_NAME,GCM_NAMESPACE);
this.json = json;
}

public String getJson(){
return json;
}

@Override
public String toXML(){
return String.format(<%s xmlns = \%s \> ;%s< /%s>,
GCM_ELEMENT_NAME,GCM_NAMESPACE,
StringUtils.escapeForXML(json),GCM_ELEMENT_NAME);


public Packet toPacket(){
Message message = new Message();
message.addExtension(this);
返回消息;



类LoggingConnectionListener实现ConnectionListener {

@Override
public void connected(XMPPConnection xmppConnection){
logArea .logMessage(连接。);
}

@Override
public void authenticated(XMPPConnection xmppConnection){
logArea.logMessage(Authenticated。);
}

@Override
public void reconnectionSuccessful(){
logArea.logMessage(Reconnecting ..);
}

@Override
public void reconnectionFailed(Exception e){
logArea.logMessage(Reconnection failed ..+ e.getMessage());
}

@Override
public void reconnectingIn(int seconds){
logArea.logMessage(Reconnecting in+ seconds +secs);
}

@Override
public void connectionClosedOnError(Exception e){
logArea.logMessage(Connection on error。);
}

@Override
public void connectionClosed(){
logArea.logMessage(Connection closed。);
}
}
}

//目标地址的不可编辑组合(下拉框)
类DestComboBox扩展JComboBox< String> {
//(删除以节省空间)
}

//用于发送消息的屏幕面板$ b $ class SendMessagePanel扩展JPanel实现ActionListener,ItemListener {
//消息类型
protected final int MSGTYPE_NOTIFICATION = 1;
protected final int MSGTYPE_NOTIFICATION_DATA = 2;
protected final int MSGTYPE_DATA_COLLAPSE = 3;
protected final int MSGTYPE_DATA_NONCOLLAPSE = 4;

//日志窗口
LogTextArea消息;

//服务器类
CcsServer ccsServer;

//构造函数
SendMessagePanel(UserList u,LogTextArea m,CcsServer c){
//(删除以节省空间)
}

//响应按钮
@Override
public void actionPerformed(ActionEvent e){
String toAddr =zzzzzz; //目标地址
//可能是设备,通知密钥或主题地址
ttl = 2419200; //秒钟生存时间

//什么类型的消息?
int msgTypeIndex =(--deleted--);

//创建消息
Map< String,Object> message = new HashMap< String,Object>();
message.put(to,toAddr);

if(msgTypeIndex == MSGTYPE_NOTIFICATION ||
msgTypeIndex == MSGTYPE_NOTIFICATION_DATA ||
msgTypeIndex == MSGTYPE_DATA_COLLAPSE){
//创建折叠键
message.put(collapse_key,ck+ msgTypeIndex);
}

message.put(time_to_live,ttl);
message.put(message_id,ccsServer.nextMessageId());

//包含通知?
if(msgTypeIndex == MSGTYPE_NOTIFICATION ||
msgTypeIndex == MSGTYPE_NOTIFICATION_DATA){

//创建通知负载
HashMap< String,String> notePayload = new HashMap<>();
notePayload.put(title,Gcm Push Message Example);
notePayload.put(body,(--deleted--));
//标识哪些通知应该替换旧版本
notePayload.put(tag,ntag+ msgTypeIndex);
notePayload.put(icon,@ drawable / new_picture); //通知图标

//额外的东西,如果我们也有数据
if(msgTypeIndex == MSGTYPE_NOTIFICATION_DATA){
//用户打开通知时的操作
notePayload.put(click_action,OPEN_MAIN_ACTIVITY);
}
message.put(notification,notePayload);
}

//包含数据?
if(msgTypeIndex == MSGTYPE_NOTIFICATION_DATA ||
msgTypeIndex == MSGTYPE_DATA_COLLAPSE ||
msgTypeIndex == MSGTYPE_DATA_NONCOLLAPSE){
HashMap< String,String> dataPayload = new HashMap<>();

dataPayload.put(contents,(--deleted--));

message.put(data,dataPayload);
}

//实际发送消息
try {
ccsServer.sendDownstreamMessage(JSONValue.toJSONString(message));
} catch(NotConnectedException enc){
msgs.logMessage(不再连接,echo消息不发送:+ enc.getMessage());
}
}
}

class BorderPanel扩展JPanel {
//(--deleted--)
}

public class GcmPushServer
{
//(--deleted--)
}


So, Google used to have a nice page where they gave code sample on how to implement a GCM Xmpp server on this page: https://developers.google.com/cloud-messaging/ccs

I had bookmarked this answer anytime I wanted to view the implementation Confused about Google GCM XMPP

But everything linked from in that answer is gone. Google deleted them.

But now, they have removed everything, and added a page that just explains what it does. Sure, but the sample java code would be nice. I tried to go to the sample site on github that they link to https://github.com/google/gcm

but it only provides samples of HTTP GCM server version.

Can somebody point me to a working code sample please? Or Is there a library out there that would work with c# at all? if not, I would just settle with the java version too.

Thanks.

解决方案

Here is one I wrote for a class example (with some non-XMPP parts deleted to keep it small enough so I can post the code, but have the full server at http://people.eku.edu/styere/GcmPushServer.java):

// derived from https://developer.android.com/google/gcm/ccs.html

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
//import javax.swing.JScrollPane;
//import javax.swing.SwingUtilities;

import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketInterceptor;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.DefaultPacketExtension;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.util.StringUtils;
import org.json.simple.JSONValue;
import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;
import org.xmlpull.v1.XmlPullParser;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Random;
import java.net.*;
import java.io.*;
import java.util.*;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.HttpsURLConnection;

// list of all users and associated devices
class UserList {
    // (--deleted--)

    // constructor/read existing data from file
    public UserList() {
        // (--deleted--)
    }

    // add a new device to an existing user (called from networking thread)
    // duplicate IDs are quietly accepted
    public synchronized void addDevice( String uname, String newRegToken ) {
        // (--deleted--)
    }

    // generate a group address/notification key
    // !!!!!!!!!!!!!!! W A R N I N G !!!!!!!!!!!!!!!
    //   If the group addr/notification key is lost, it currently CANNOT be recovered/rebuilt
    public String createNotificationKey( String nKeyName, String addr ) {
        String[] idset = new String[1];
        idset[0] = addr;

        String newGroupAddr;

        try {
            // create a https connection to create the notification_key
            URL url = new URL( "https://android.googleapis.com/gcm/notification" );
            HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();

            // send as a POST request
            conn.setRequestMethod("POST");

            // add request parameters
            conn.addRequestProperty( "project_id", ""+GcmPushServer.senderId );
            conn.addRequestProperty( "Authorization", "key="+GcmPushServer.password );
            // use "set" since this may already exist
            conn.setRequestProperty( "Content-Type", "application/json" );

            // create data to send with request
            Map<String,Object> sendData = new HashMap<>();

            // create a new notification key
            sendData.put( "operation", "create" );
            sendData.put( "notification_key_name", (--deleted--) );
            sendData.put( "registration_ids", (--deleted--) );

            String strData = JSONValue.toJSONString(sendData);

            // Send post request
            conn.setDoOutput(true);
            DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
            wr.writeBytes( strData );
            wr.flush();
            wr.close();

            // successful?
            int rc = conn.getResponseCode();
            //System.out.println("ResponseCode = " + rc );

            // read the response
            Scanner input = new Scanner( conn.getInputStream() );
            String resp="";

            // read/display lines
            while( input.hasNextLine() ) {
                String s = input.nextLine();
                resp += s;
            }

            //System.out.println("Response content: " + resp);

            if ( rc == HttpsURLConnection.HTTP_OK ) {
                JSONObject obj = (JSONObject) JSONValue.parse(resp);

                newGroupAddr = (String) obj.get( "notification_key" );
                //System.out.println(" new notification_key: " + newGroupAddr );
                return newGroupAddr;
            } else {

            }
        } catch ( Exception e ) {
            //System.out.println("-- Exception: " + e.getMessage() );
        }

        return null;
    }

    // add/delete a single address to/from a notification key
    //  (add if doAdd is true, delete otherwise)
    // removing final address will quietly delete the key
    public static void modifyNotificationKey( String nKeyName, String nKey,
                    String addr, boolean doAdd ) {
        String[] idset = new String[1];
        idset[0] = addr;

        try {
            // create a https connection to create the notification_key
            URL url = new URL( "https://android.googleapis.com/gcm/notification" );
            HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();

            // send as a POST request
            conn.setRequestMethod("POST");

            // add request parameters
            conn.addRequestProperty( "project_id", ""+GcmPushServer.senderId );
            conn.addRequestProperty( "Authorization", "key="+GcmPushServer.password );
            // use "set" since this may already exist
            conn.setRequestProperty( "Content-Type", "application/json" );

            // create data to send with request
            Map<String,Object> sendData = new HashMap<>();

            // create a new notification key
            sendData.put( "operation", doAdd? "add" : "remove" );       // add or delete key?
            sendData.put( "notification_key_name", (--deleted--) );
            sendData.put( "notification_key", (--deleted--) );
            sendData.put( "registration_ids", (--deleted--) );

            String strData = JSONValue.toJSONString(sendData);
            //System.out.println("genGroupAddress POST data: " + strData );

            // Send post request
            conn.setDoOutput(true);
            DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
            wr.writeBytes( strData );
            wr.flush();
            wr.close();

            //conn.openConnection();

            // successful?
            int rc = conn.getResponseCode();
            //System.out.println("ResponseCode = " + rc );

            Scanner input = new Scanner( conn.getInputStream() );

            // read/display lines
            while( input.hasNextLine() ) {
                System.out.println("Response content:");
                String s = input.nextLine();
                System.out.println( s );
            }
        } catch ( Exception e ) {
            // do nothing
        }
    }
}

// text area for log messages
class LogTextArea extends JTextArea {
    // update the "log" with the specified message
    public void logMessage( String msg ) {
        // (--deleted--)
    }
}

class CcsServer {
    private static final String GCM_SERVER = "gcm.googleapis.com";
    private static final int GCM_PORT = 5235;

    private static final String GCM_ELEMENT_NAME = "gcm";
    private static final String GCM_NAMESPACE = "google:mobile:data";

    // display/log area
    LogTextArea logArea;
    UserList users;

    CcsServer( LogTextArea lta, UserList u ) {
        logArea = lta;
        users = u;
    }

    static {
        ProviderManager.addExtensionProvider(GCM_ELEMENT_NAME, GCM_NAMESPACE,
            new PacketExtensionProvider() {
                @Override
                public PacketExtension parseExtension(XmlPullParser parser) throws
                        Exception {
                    String json = parser.nextText();
                    return new GcmPacketExtension(json);
                }
            });
    }

    private XMPPConnection connection;

    /**
     * Indicates whether the connection is in draining state, which means that it
     * will not accept any new downstream messages.
     */
    protected volatile boolean connectionDraining = false;

    /**
     * Sends a downstream message to GCM.
     *
     * @return true if the message has been successfully sent.
     */
    public boolean sendDownstreamMessage(String jsonRequest) throws
            NotConnectedException {
        if (!connectionDraining) {
            send(jsonRequest);
            return true;
        }
        logArea.logMessage("Dropping downstream message since the connection is draining");
        return false;
    }

    /**
     * Returns a random message id to uniquely identify a message.
     *
     * <p>Note: This is generated by a pseudo random number generator for
     * illustration purpose, and is not guaranteed to be unique.
     */
    public String nextMessageId() {
        return "m-" + UUID.randomUUID().toString();
    }

    /**
     * Sends a packet with contents provided.
     */
    protected void send(String jsonRequest) throws NotConnectedException {
        Packet request = new GcmPacketExtension(jsonRequest).toPacket();
        connection.sendPacket(request);
    }

    /**
     * Handles an upstream data message from a device application.
     *
     * <p>This sample echo server sends an echo message back to the device.
     * Subclasses should override this method to properly process upstream messages.
     */
    protected void handleUpstreamMessage(Map<String, Object> jsonObject) {
        // PackageName of the application that sent this message.
        String category = (String) jsonObject.get("category");
        String from = (String) jsonObject.get("from");
        @SuppressWarnings("unchecked")
        Map<String, String> payload = (Map<String, String>) jsonObject.get("data");

        // what type of upstream message is this?
        if ( ! payload.containsKey( "my_action" ) )
        {
            // Hmmm - this shouldn't happen!
            logArea.logMessage( "handleUpstreamMessage - incoming message is missing my_action" );
            // just ignore the  message
            return;
        }

        // what action do they want?
        String my_action = (String) payload.get( "my_action" );
        if ( my_action.equals( "edu.eku.styere.gcmpushclient.REGISTER" ) ) {
            // registration request
            String username = (String) payload.get( "username" );

            logArea.logMessage( "Registration request: user=" + username + ", ID/Token=" + from );

            // save the information
            users.addDevice( username, from );

            return;
        } else {
            // take default action of echoing the message       
            payload.put("ECHO", "Application: " + category);

            // Send an ECHO response back
            String echo = createJsonMessage(from, nextMessageId(), payload,
                    "echo:CollapseKey", null, false);

            try {
                sendDownstreamMessage(echo);
            } catch (NotConnectedException e) {
                logArea.logMessage( "Not connected anymore, echo message is not sent: " + e.getMessage() );
            }
        }
    }

    /**
     * Handles an ACK.
     *
     * <p>Logs a INFO message, but subclasses could override it to
     * properly handle ACKs.
     */
    protected void handleAckReceipt(Map<String, Object> jsonObject) {
        String messageId = (String) jsonObject.get("message_id");
        String from = (String) jsonObject.get("from");
        logArea.logMessage( "handleAckReceipt() from: " + from + ", messageId: " + messageId );
    }

    /**
     * Handles a NACK.
     *
     * <p>Logs a INFO message, but subclasses could override it to
     * properly handle NACKs.
     */
    protected void handleNackReceipt(Map<String, Object> jsonObject) {
        String messageId = (String) jsonObject.get("message_id");
        String from = (String) jsonObject.get("from");
        logArea.logMessage( "handleNackReceipt() from: " + from + ", messageId: " + messageId );
    }

    protected void handleControlMessage(Map<String, Object> jsonObject) {
        logArea.logMessage( "handleControlMessage(): " + jsonObject );
        String controlType = (String) jsonObject.get("control_type");
        if ("CONNECTION_DRAINING".equals(controlType)) {
            connectionDraining = true;
        } else {
            logArea.logMessage( "Unrecognised control type: " + controlType + ". This could "+
                    "happen if new features are " + "added to the CCS protocol." );
        }
    }

    /**
     * Creates a JSON encoded GCM message.
     *
     * @param to RegistrationId of the target device (Required).
     * @param messageId Unique messageId for which CCS sends an
     *         "ack/nack" (Required).
     * @param payload Message content intended for the application. (Optional).
     * @param collapseKey GCM collapse_key parameter (Optional).
     * @param timeToLive GCM time_to_live parameter (Optional).
     * @param delayWhileIdle GCM delay_while_idle parameter (Optional).
     * @return JSON encoded GCM message.
     */
    public static String createJsonMessage(String to, String messageId,
            Map<String, String> payload, String collapseKey, Long timeToLive,
            Boolean delayWhileIdle) {
        Map<String, Object> message = new HashMap<String, Object>();
        message.put("to", to);
        if (collapseKey != null) {
            message.put("collapse_key", collapseKey);
        }
        if (timeToLive != null) {
            message.put("time_to_live", timeToLive);
        }
        if (delayWhileIdle != null && delayWhileIdle) {
            message.put("delay_while_idle", true);
        }
      message.put("message_id", messageId);
      message.put("data", payload);
      return JSONValue.toJSONString(message);
    }

    /**
     * Creates a JSON encoded ACK message for an upstream message received
     * from an application.
     *
     * @param to RegistrationId of the device who sent the upstream message.
     * @param messageId messageId of the upstream message to be acknowledged to CCS.
     * @return JSON encoded ack.
     */
        protected static String createJsonAck(String to, String messageId) {
        Map<String, Object> message = new HashMap<String, Object>();
        message.put("message_type", "ack");
        message.put("to", to);
        message.put("message_id", messageId);
        return JSONValue.toJSONString(message);
    }

    /**
     * Connects to GCM Cloud Connection Server using the supplied credentials.
     *
     * @param senderId Your GCM project number
     * @param apiKey API Key of your project
     */
    public void connect(long senderId, String apiKey)
            throws XMPPException, IOException, SmackException {
        ConnectionConfiguration config =
                new ConnectionConfiguration(GCM_SERVER, GCM_PORT);
        config.setSecurityMode(SecurityMode.enabled);
        config.setReconnectionAllowed(true);
        config.setRosterLoadedAtLogin(false);
        config.setSendPresence(false);
        config.setSocketFactory(SSLSocketFactory.getDefault());

        connection = new XMPPTCPConnection(config);
        connection.connect();

        connection.addConnectionListener( new LoggingConnectionListener() );

        // Handle incoming packets
        connection.addPacketListener(new PacketListener() {

            @Override
            public void processPacket(Packet packet) {
                logArea.logMessage( "Received: " + packet.toXML() );
                Message incomingMessage = (Message) packet;
                GcmPacketExtension gcmPacket =
                        (GcmPacketExtension) incomingMessage.
                        getExtension(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
                        handleUpstreamMessage(jsonObject);

                        // Send ACK to CCS
                        String messageId = (String) jsonObject.get("message_id");
                        String from = (String) jsonObject.get("from");
                        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 if ("control".equals(messageType.toString())) {
                          // Process control message
                          handleControlMessage(jsonObject);
                    } else {
                          logArea.logMessage( "Unrecognised message type: " + 
                                  messageType.toString() );
                    }
                } catch (ParseException e) {
                    logArea.logMessage( "Error parsing JSON " + json );
                } catch (Exception e) {
                    logArea.logMessage( "Failed to process packet" );
                }
            }
        }, new PacketTypeFilter(Message.class));

        // Log all outgoing packets
        connection.addPacketInterceptor(new PacketInterceptor() {
            @Override
                public void interceptPacket(Packet packet) {
                    logArea.logMessage( "Sent: " + packet.toXML());
                }
            }, new PacketTypeFilter(Message.class));

        connection.login(senderId + "@gcm.googleapis.com", apiKey);
    }

    //---------- support classes ----------

    /**
    * XMPP Packet Extension for GCM Cloud Connection Server.
    */
    private static class GcmPacketExtension extends DefaultPacketExtension {

        private final String json;

        public GcmPacketExtension(String json) {
            super( GCM_ELEMENT_NAME, GCM_NAMESPACE);
            this.json = json;
        }

        public String getJson() {
            return json;
        }

        @Override
        public String toXML() {
            return String.format("<%s xmlns=\"%s\">%s</%s>",
                    GCM_ELEMENT_NAME, GCM_NAMESPACE,
                    StringUtils.escapeForXML(json), GCM_ELEMENT_NAME);
        }

        public Packet toPacket() {
            Message message = new Message();
            message.addExtension(this);
            return message;
        }
    }

    class LoggingConnectionListener implements ConnectionListener {

        @Override
        public void connected(XMPPConnection xmppConnection) {
            logArea.logMessage( "Connected." );
        }

        @Override
        public void authenticated(XMPPConnection xmppConnection) {
            logArea.logMessage( "Authenticated." );
        }

        @Override
        public void reconnectionSuccessful() {
            logArea.logMessage( "Reconnecting.." );
        }

        @Override
        public void reconnectionFailed(Exception e) {
            logArea.logMessage( "Reconnection failed.. " + e.getMessage() );
        }

        @Override
        public void reconnectingIn(int seconds) {
            logArea.logMessage( "Reconnecting in " + seconds + " secs" );
        }

        @Override
        public void connectionClosedOnError(Exception e) {
            logArea.logMessage( "Connection closed on error." );
        }

        @Override
        public void connectionClosed() {
            logArea.logMessage( "Connection closed." );
        }
    }
}

// a non-editable combo (drop-down) box for destination addresses
class DestComboBox extends JComboBox<String> {
    // (deleted to save space)
}

// screen panel for sending a message
class SendMessagePanel extends JPanel implements ActionListener, ItemListener {     
    // Message Types
    protected final int MSGTYPE_NOTIFICATION = 1;
    protected final int MSGTYPE_NOTIFICATION_DATA = 2;
    protected final int MSGTYPE_DATA_COLLAPSE = 3;
    protected final int MSGTYPE_DATA_NONCOLLAPSE = 4;

    // log window
    LogTextArea msgs;

    // server class
    CcsServer ccsServer;

    // constructor
    SendMessagePanel( UserList u, LogTextArea m, CcsServer c ) {
        // (deleted to save space)
    }

    // respond to the button
    @Override
    public void actionPerformed(ActionEvent e) {
        String toAddr = "zzzzzz";   // destination address
               // may be device, notification_key, or topic address
        ttl = 2419200;              // time-to-live in seconds

        // what type of message?
        int msgTypeIndex = (--deleted--);

        // create the message
        Map<String, Object> message = new HashMap<String, Object>();
        message.put("to", toAddr);

        if ( msgTypeIndex == MSGTYPE_NOTIFICATION ||
                    msgTypeIndex == MSGTYPE_NOTIFICATION_DATA ||
                    msgTypeIndex == MSGTYPE_DATA_COLLAPSE ) {
            // create a collapse key
            message.put("collapse_key", "ck"+msgTypeIndex );
        }

        message.put("time_to_live", ttl);   
        message.put("message_id", ccsServer.nextMessageId());

        // notification included?
        if ( msgTypeIndex == MSGTYPE_NOTIFICATION ||
                msgTypeIndex == MSGTYPE_NOTIFICATION_DATA ) {

            // create the notification payload
            HashMap<String, String> notePayload = new HashMap<>();
            notePayload.put( "title", "Gcm Push Message Example" );
            notePayload.put( "body", (--deleted--) );
            // identify which notifications should replace older versions
            notePayload.put( "tag", "ntag" + msgTypeIndex );
            notePayload.put( "icon", "@drawable/new_picture" );     // notification icon

            // additional stuff if we also have data
            if ( msgTypeIndex == MSGTYPE_NOTIFICATION_DATA ) {
                // what to do when the user opens the notification
                notePayload.put( "click_action", "OPEN_MAIN_ACTIVITY" );
            }
            message.put( "notification", notePayload );
        }

        // data included?
        if ( msgTypeIndex == MSGTYPE_NOTIFICATION_DATA ||
                    msgTypeIndex == MSGTYPE_DATA_COLLAPSE ||
                    msgTypeIndex == MSGTYPE_DATA_NONCOLLAPSE ) {
            HashMap<String, String> dataPayload = new HashMap<>();

            dataPayload.put( "contents", (--deleted--) );

            message.put("data", dataPayload);
        }

        // actually send the message
        try {
            ccsServer.sendDownstreamMessage( JSONValue.toJSONString(message) );
        } catch (NotConnectedException enc ) {
            msgs.logMessage( "Not connected anymore, echo message is not sent: " + enc.getMessage() );
        }
    }
}

class BorderPanel extends JPanel {
    // (--deleted--)
}

public class GcmPushServer
{
    // (--deleted--)
}

这篇关于Google GCM XMPP代码示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆