You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Java开发:Telegram命令重复回复问题求助

问题根源分析

你的代码持续重复回复的核心原因是没有正确标记已处理的Telegram更新消息:

  • 调用getUpdates时使用了offset=-1,这个参数仅能获取最新的1条更新,但Telegram服务器不会自动标记这条消息为已处理。
  • 每次执行respondToCommand都会重新拉取这条未被标记的/start消息,导致重复触发回复逻辑。
  • 如果你的代码是通过定时任务或重复触发(比如按钮循环调用)这个方法,会进一步加剧重复发送的问题。
正确实现方式

1. 核心改进思路

维护一个变量记录最后处理过的update_id,每次调用getUpdates时将offset设为lastUpdateId + 1,这样Telegram会返回比这个ID更大的新消息,彻底避免重复处理旧消息。

2. 修改后的核心代码示例

// 全局变量,记录最后处理的update_id,初始值设为0
private long lastUpdateId = 0;

private void respondToCommand() {
    // 建议在onCreate中初始化EditText实例,避免重复findViewById
    botTokens = (EditText) findViewById(R.id.botToken);
    chatId = (EditText) findViewById(R.id.chatId);
    String botTokenStr = botTokens.getText().toString();
    String chatIdStr = chatId.getText().toString();

    if (botTokenStr.isEmpty()){
        Toast.makeText(getApplicationContext(), "bot token is empty!", Toast.LENGTH_LONG).show();
        return;
    }

    // 使用lastUpdateId+1作为offset,只拉取未处理的新消息
    String telegramApiUrl = "https://api.telegram.org/bot" + botTokenStr + "/getUpdates?limit=100&offset=" + (lastUpdateId + 1);

    JsonObjectRequest request = new JsonObjectRequest(com.android.volley.Request.Method.GET, telegramApiUrl, null, 
        new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                try {
                    JSONArray resultArr = response.getJSONArray("result");
                    if (resultArr.length() == 0) {
                        Toast.makeText(getApplicationContext(), "No new messages.", Toast.LENGTH_SHORT).show();
                        return;
                    }

                    for (int i = 0; i < resultArr.length(); i++) {
                        JSONObject updateObj = resultArr.getJSONObject(i);
                        // 更新lastUpdateId为当前消息的ID,确保后续只处理新消息
                        long currentUpdateId = updateObj.getLong("update_id");
                        if (currentUpdateId > lastUpdateId) {
                            lastUpdateId = currentUpdateId;
                        }

                        JSONObject messageObj = updateObj.getJSONObject("message");
                        String msgText = messageObj.getString("text");
                        JSONObject chatObj = messageObj.getJSONObject("chat");
                        String currentChatId = chatObj.getString("id");

                        if(currentChatId.equals(chatIdStr)) {
                            if(msgText.equals("/start")){
                                new RetrieveFeedTask().execute(botTokenStr, chatIdStr, "Started"+ UUID.randomUUID());
                                resultToken.setText("reply to command : "+msgText);
                            } else {
                                resultToken.setText("it's a message : "+msgText);
                            }
                        } else {
                            resultToken.setText("not target chat");
                        }
                    }

                } catch (Exception e) {
                    Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_LONG).show();
                }
            }
        }, 
        new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Toast.makeText(getApplicationContext(), volleyError.toString(), Toast.LENGTH_LONG).show();
            }
        });

    Volley.newRequestQueue(this).add(request);
}

3. 额外优化建议

  • 采用长轮询替代频繁调用:给getUpdates添加timeout=30参数,服务器会在有新消息时立即返回,无消息则等待超时,减少无效请求。
  • 不要每次调用都重新获取EditText实例,建议在onCreate中初始化一次。
  • 直接解析chat对象,无需通过Gson转换自定义类,简化代码逻辑。

内容的提问来源于stack exchange,提问作者Progromatic World

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 09:00:19