简体   繁体   English

谷歌云消息传递-使用smack的xmpp服务器端不起作用

[英]google cloud messaging - xmpp server side using smack not working

when taking the code below for sending a message to a device with using smack libary 3.3.0 当使用下面的代码使用smack libary 3.3.0向设备发送消息时

Getting an error 遇到错误

SASL authentication PLAIN failed: text: 
    at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:342)
    at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:221)
    at org.jivesoftware.smack.Connection.login(Connection.java:366)
    at com.test.xmpp.SmackCcsClient.connect(SmackCcsClient.java:335)
    at com.test.xmpp.SmackCcsClient.main(SmackCcsClient.java:345)

When switching to HTTP server side, the messaging is working 切换到HTTP服务器端时,消息传递正常

/**
 * Sample Smack implementation of a client for GCM Cloud Connection Server.
 *
 * <p>For illustration purposes only.
 */
public class SmackCcsClient {

  Logger logger = Logger.getLogger("SmackCcsClient");

  public static final String GCM_SERVER = "gcm.googleapis.com";
  public static final int GCM_PORT = 5235;

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

  static Random random = new Random();
  XMPPConnection connection;
  ConnectionConfiguration config;

  /**
   * XMPP Packet Extension for GCM Cloud Connection Server.
   */
  class GcmPacketExtension extends DefaultPacketExtension {
    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, json, GCM_ELEMENT_NAME);
    }

    @SuppressWarnings("unused")
    public Packet toPacket() {
      return new Message() {
        // Must override toXML() because it includes a <body>
        @Override
        public String toXML() {

          StringBuilder buf = new StringBuilder();
          buf.append("<message");
          if (getXmlns() != null) {
            buf.append(" xmlns=\"").append(getXmlns()).append("\"");
          }
          if (getLanguage() != null) {
            buf.append(" xml:lang=\"").append(getLanguage()).append("\"");
          }
          if (getPacketID() != null) {
            buf.append(" id=\"").append(getPacketID()).append("\"");
          }
          if (getTo() != null) {
            buf.append(" to=\"").append(StringUtils.escapeForXML(getTo())).append("\"");
          }
          if (getFrom() != null) {
            buf.append(" from=\"").append(StringUtils.escapeForXML(getFrom())).append("\"");
          }
          buf.append(">");
          buf.append(GcmPacketExtension.this.toXML());
          buf.append("</message>");
          return buf.toString();
        }
      };
    }
  }

  public SmackCcsClient() {
    // Add GcmPacketExtension
    ProviderManager.getInstance().addExtensionProvider(GCM_ELEMENT_NAME,
        GCM_NAMESPACE, new PacketExtensionProvider() {

      @Override
      public PacketExtension parseExtension(XmlPullParser parser)
          throws Exception {
        String json = parser.nextText();
        GcmPacketExtension packet = new GcmPacketExtension(json);
        return packet;
      }
    });
  }

  /**
   * 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 getRandomMessageId() {
    return "m-" + Long.toString(random.nextLong());
  }

  /**
   * Sends a downstream GCM message.
   */
  public void send(String jsonRequest) {
    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 process an upstream message.
   */
  public void handleIncomingDataMessage(Map<String, Object> jsonObject) {
    String from = jsonObject.get("from").toString();

    // PackageName of the application that sent this message.
    String category = jsonObject.get("category").toString();

    // Use the packageName as the collapseKey in the echo packet
    String collapseKey = "echo:CollapseKey";
    @SuppressWarnings("unchecked")
    Map<String, String> payload = (Map<String, String>) jsonObject.get("data");
    payload.put("ECHO", "Application: " + category);

    // Send an ECHO response back
    String echo = createJsonMessage(from, getRandomMessageId(), payload, collapseKey, null, false);
    send(echo);
  }

  /**
   * Handles an ACK.
   *
   * <p>By default, it only logs a INFO message, but subclasses could override it to
   * properly handle ACKS.
   */
  public void handleAckReceipt(Map<String, Object> jsonObject) {
    String messageId = jsonObject.get("message_id").toString();
    String from = jsonObject.get("from").toString();
    logger.log(Level.INFO, "handleAckReceipt() from: " + from + ", messageId: " + messageId);
  }

  /**
   * Handles a NACK.
   *
   * <p>By default, it only logs a INFO message, but subclasses could override it to
   * properly handle NACKS.
   */
  public void handleNackReceipt(Map<String, Object> jsonObject) {
    String messageId = jsonObject.get("message_id").toString();
    String from = jsonObject.get("from").toString();
    logger.log(Level.INFO, "handleNackReceipt() from: " + from + ", messageId: " + messageId);
  }

  /**
   * Creates a JSON encoded GCM message.
   *
   * @param to RegistrationId of the target device (Required).
   * @param messageId Unique messageId for which CCS will send 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.
   */
  public 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 username GCM_SENDER_ID@gcm.googleapis.com
   * @param password API Key
   * @throws XMPPException
   */
  public void connect(String username, String password) throws XMPPException {
    config = new ConnectionConfiguration(GCM_SERVER, GCM_PORT);
    config.setSecurityMode(SecurityMode.enabled);
    config.setReconnectionAllowed(true);
    config.setRosterLoadedAtLogin(false);
    config.setSendPresence(false);
    config.setSocketFactory(SSLSocketFactory.getDefault());

    // NOTE: Set to true to launch a window with information about packets sent and received
    config.setDebuggerEnabled(true);

    // -Dsmack.debugEnabled=true
    XMPPConnection.DEBUG_ENABLED = true;

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

    connection.addConnectionListener(new ConnectionListener() {

      @Override
      public void reconnectionSuccessful() {
        logger.info("Reconnecting..");
      }

      @Override
      public void reconnectionFailed(Exception e) {
        logger.log(Level.INFO, "Reconnection failed.. ", e);
      }

      @Override
      public void reconnectingIn(int seconds) {
        logger.log(Level.INFO, "Reconnecting in %d secs", seconds);
      }

      @Override
      public void connectionClosedOnError(Exception e) {
        logger.log(Level.INFO, "Connection closed on error.");
      }

      @Override
      public void connectionClosed() {
        logger.info("Connection closed.");
      }
    });

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

      @Override
      public void processPacket(Packet packet) {
        logger.log(Level.INFO, "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
            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() {
      @Override
      public void interceptPacket(Packet packet) {
        logger.log(Level.INFO, "Sent: {0}",  packet.toXML());
      }
    }, new PacketTypeFilter(Message.class));

    connection.login(username, password);
  }

  public static void main(String [] args) {
    final String userName = "124079202908" + "@gcm.googleapis.com";
    final String password = "AIzaSyAMt1y_xILk72wiQybuqVEdiq7uGXBEUhQ";

    SmackCcsClient ccsClient = new SmackCcsClient();

    try {
      ccsClient.connect(userName, password);
    } catch (XMPPException e) {
      e.printStackTrace();
    }
  }
}

Also I submitted a request for using the API over a week ago and didn't recieve a reply yet. 另外,我在一周前提交了使用API​​的请求,但尚未收到回复。

The problem is resolved. 问题已解决。 The issue was indeed that the project wasn't registered. 问题确实是该项目尚未注册。 I received an email from Google 2 weeks after asking for the API receiving confirmation. 要求API收到确认后2周 ,我收到了Google的电子邮件。 The error in this case really should be improved and it would be nice if Google wrote approximately how long to receive the email. 这种情况下的错误确实应该得到改善,如果Google写了大约多长时间才能收到电子邮件,那就太好了。 Just wanted to update anyone else encountering the problem. 只是想更新遇到问题的其他任何人。

@user2679041 i guess you are saying right. @ user2679041我想你说的没错。 I have register my gcm project id just today and i haven't receive any confirmation email yet. 我只是在今天注册了我的gcm项目ID,但尚未收到任何确认电子邮件。 That's really annoying, who else is going to wait for a 2 weeks? 真的很烦人,还有谁还要等两个星期? I have saw few queries @ stackoverflow that people says there request approved by google after 3 months too. 我看到很少的@stackoverflow查询,人们说3个月后也有Google批准的请求 I have followed the this link 我已经关注了这个链接

and its has a note saying : 它有一个注释说:

After you have created your GCM enabled project in the API Console you must fill out this form and become a trial partner to use upstream messaging and user notifications via CCS. 在API控制台中创建启用GCM的项目后,您必须填写此表格并成为试用合作伙伴,以通过CCS使用上游消息传递和用户通知。 Access is limited to those that fill out the form. 访问仅限于填写表格的人员。 You will receive an email from Google informing you that you now have access; 您会收到来自Google的电子邮件,通知您现在可以访问; Google will also send you the address of an echo server that you can use to bounce messages back to your application. Google还将向您发送回显服务器的地址,您可以使用该地址将邮件退回给您的应用程序。

So we might say Google has released beta version with limited no. 因此,我们可以说Google发布了beta版本,但没有限制。 of access. 访问。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM