Google GCM XMPP 代码示例

2023-12-30

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

每当我想查看实施情况时,我都会将此答案添加为书签对 Google GCM XMPP 感到困惑 https://stackoverflow.com/questions/24863303/confused-about-google-gcm-xmpp/24864958#24864958

但该答案中链接的所有内容都消失了。谷歌删除了它们。

但现在,他们删除了所有内容,并添加了一个仅解释其功能的页面。当然可以,但是示例 java 代码就更好了。我尝试访问他们链接到的 github 上的示例网站https://github.com/google/gcm https://github.com/google/gcm

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

有人可以给我指一个工作代码示例吗?或者是否有一个库可以与 c# 一起使用?如果没有的话,我也会选择java版本。

Thanks.


这是我为类示例编写的一个(删除了一些非 XMPP 部分以使其足够小,以便我可以发布代码,但完整的服务器位于http://people.eku.edu/styere/GcmPushServer.java 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--)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Google GCM XMPP 代码示例 的相关文章

  • 为什么在将 String 与 null 进行比较时会出现 NullPointerException?

    我的代码在以下行中出现空指针异常 if stringVariable equals null 在此语句之前 我声明了 stringVariable 并将其设置为数据库字段 在这个声明中 我试图检测该字段是否有null值 但不幸的是它坏了 有
  • 在 Android 中加密/解密字符串的简单方法

    我的问题是如何加密String String AndroidId Override public void onCreate Bundle savedInstanceState super onCreate savedInstanceSta
  • 为什么解析这个 JSON 会抛出错误?

    我正在尝试解析这个 JSONObject query yahoo count 1 results rate Name USD INR id USDINR Time 12 19pm Date 10 31 2015 Bid 65 405 Ask
  • 如何使用双重调度来分析图形基元的交集?

    我正在分析图形基元 矩形 直线 圆形等 的交互并计算重叠 相对方向 合并等 这被引用为双重调度的一个主要示例 例如维基百科 http en wikipedia org wiki Double dispatch 自适应碰撞算法通常要求 不同的
  • 如何在Android模拟器中隐藏应用程序图标?

    我有一个应用程序在启动完成后自动启动 但应用程序图标显示在android模拟器中 现在我想向用户隐藏该图标 这样用户就无法知道应用程序已启动 并且他们无法启动该应用程序手动申请 在您的 AndroidManifest xml 文件中 您可能
  • UseCompressedOops JVM 标志有什么作用以及何时应该使用它?

    HotSpot JVM 标志是什么 XX UseCompressedOops我应该做什么以及什么时候使用它 在 64 位 Java 实例上使用它 与不使用它 时 我会看到什么样的性能和内存使用差异 去年大多数 HotSpot JVM 都默认
  • 如何使用 Jersey 将嵌套列表封送为 JSON?我得到一个空数组或一个包含数组的单元素字典数组

    我正在开发一个使用 Jersey 将对象转换为 JSON 的项目 我希望能够写出嵌套列表 如下所示 data one two three a b c 我想要转换的对象首先将数据表示为 gt gt 我认为 Jersey 会做正确的事情 以上输
  • 活动加载缓慢

    我的应用程序中有大约 50 个活动 但其中一个活动非常慢 我的意思是当我按下按钮进入该活动时 需要很长时间 有时会出现黑屏 在该活动中 我有一个按钮 如果我单击该按钮 则需要很长时间才能执行 代码很轻 只有一个Button EditText
  • Tomcat 6 未从 WEB-INF/lib 加载 jar

    我正在尝试找出我的 tomcat 环境中的配置问题 我们的生产服务器正在运行 tomcat 安装并从共享 NFS 挂载读取战争 然而 当我尝试使用独立的盒子 及其配置 进行同样的战争时 我收到下面发布的错误 有趣的是 如果我将 WEB IN
  • Expresso 的 Android 测试首选项片段

    我在通过 Expresso 测试我的代码时遇到问题 我写了这段代码 public class SettingsActivity extends Activity Override protected void onCreate Bundle
  • 即使禁用安全性,OAuth 令牌 API 也无法在 Elastic Search 中工作

    我是 Elastic search 新手 使用 Elastic search 版本 7 7 1 我想通过以下方式生成 OAuth 令牌弹性搜索文档 https www elastic co guide en elasticsearch re
  • 通过 Gradle 和 Android Studio 构建和运行应用程序比通过 Eclipse 慢

    我有一个多项目 10 个模块 每次构建大约需要 20 30 秒 当我在 Android Studio 中按 运行 时 每次都必须等待才能重建应用程序 这非常慢 是否可以在 Android Studio 中自动化构建过程 或者您对如何加快此过
  • Selenium 单击在 Internet Explorer 11 上不起作用

    我尝试在 Internet Explorer 上单击 selenium 但它不起作用 我努力了element click moveToElement element click build perform javascript没事了 事实上
  • Android 从通知刷新 Activity

    我有一个程序 我在其中调用通知 如果您将其下拉 该通知将启动一个新活动 mNotificationManager NotificationManager getSystemService ns int icon R drawable sta
  • Android AppWidgetManager 方法 updateAppWidget 无法设置意图、加载数据。而且它是随机发生的

    我的小部件由 2 个按钮和一个显示数据的列表视图组成 大多数时候 当调用小部件提供程序的 onUpdate 方法时 一切都会正常加载 每个人都很高兴 但是我注意到有时在调用更新方法后 小部件完全无法加载其数据 列表视图为空 所有按钮均无响应
  • 在数组列表中过滤 Filterable 不取消之前的过滤

    我看过过滤器方法文档 其中显示调用过滤器会取消所有先前未执行的过滤请求 并发布一个稍后将执行的新过滤请求 但我收到的实际回调有些不同 在我的实现中 它不会取消先前的过滤器请求并调用publishResults 最近一次搜索条件后的上一次搜索
  • 如何让 Firebase 与 Java 后端配合使用

    首先 如果这个问题过于抽象或不适合本网站 我想表示歉意 我真的不知道还能去哪里问 目前我已经在 iOS 和 Android 上开发了应用程序 他们将所有状态保存在 Firebase 中 因此所有内容都会立即保存到 Firebase 实时数据
  • Spring 作为 JNDI 提供者?

    我想使用 Spring 作为 JNDI 提供程序 这意味着我想在 Spring 上下文中配置一个 bean 可以通过 JNDI 访问该 bean 这看起来像这样
  • 设置 TreeSet 的大小

    有没有办法像数组一样对 Java 集合中的 TreeSet 进行大小限制 例如我们在数组中 anArray new int 10 数组具有固定长度 在创建数组时必须指定该长度 A TreeSet当您向其中添加元素时会自动增长 您无法设置其大
  • GAE 无法部署到 App Engine

    我正在尝试从 Eclipse 发布 Web 应用程序 我在 GAE 上创建了四个项目 可以通过登录我的帐户并查看控制台来查看它们 我已经改变了appengine web xml到项目的应用程序 ID 如果我将其更改为 GAE 上第一个创建的

随机推荐