【问题标题】:JAVA: tweaking SMS character countdownJAVA:调整短信字符倒计时
【发布时间】:2018-12-03 01:44:36
【问题描述】:

我正在用 JavaFX8 开发一个 SMS 发送应用程序。 我需要帮助来调整我的短信计数器功能。

一些背景信息:

一条短信可以包含 160 个字符。如果超过 160 个字符,则它变为多部分 SMS。所以第二条短信可以包含 146 个字符,第三条短信可以包含 153 个字符。从第三条短信开始,每条短信可以包含 153 个字符。

所以它会像 160 -> 146 -> 153 -> 153 -> 153 ...

现在我想从 160 倒数到 0,然后从 146 倒数到 0,然后从 153 倒数到 0。

这是我目前所拥有的:

smsComposeArea.textProperty().addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
        //Replace all multiple whitspaces with one whitespace
        smsComposeArea.setText(smsComposeArea.getText().replaceAll("[^\\S\\r|\\n|\\r\\n]+", " "));
        //GSM 03.38 Extended charset ^{}\[~]|€ take up 2 characters - count them as 2 chars. Replace multiple tabs, newlines, whitespaces with one.
        int charCount = smsComposeArea.getText().replaceAll("[\\^{}\\\\\\[~\\]|€]{1}", "$0$0").replaceAll("(\\r|\\n|\\r\\n|\\s)+", " ").length();

        int countDown;
        if(smsComposeArea.getText() == null && smsComposeArea.getText().trim().isEmpty()) {
            lblCharCounter.setText("160");
        }
        else if(charCount >= 1 && charCount <= 160) {
            countDown = 160 - charCount;
            lblCharCounter.setText(Integer.toString(countDown));
        }
        else if(charCount >= 160 && charCount <= 306) {
            countDown = 146 - (charCount - 160);
            lblCharCounter.setText(String.format("2 SMS %s", Integer.toString(countDown)));
        }
        else if(charCount >= 306 && charCount <= 459) {
            countDown = 153 - (charCount - 306);
            lblCharCounter.setText(String.format("3 SMS %s", Integer.toString(countDown)));
        }
        else if(charCount >= 459 && charCount <= 612) {
            countDown = 153 - (charCount - 459);
            lblCharCounter.setText(String.format("4 SMS %s", Integer.toString(countDown)));
        }
        else if(charCount >= 612 && charCount <= 765) {
            countDown = 153 - (charCount - 612);
            lblCharCounter.setText(String.format("5 SMS %s", Integer.toString(countDown)));
        }
        else if(charCount >= 765 && charCount <= 918) {
            countDown = 153 - (charCount - 765);
            lblCharCounter.setText(String.format("6 SMS %s", Integer.toString(countDown)));
        }
        else if(charCount >= 918 && charCount <= 1071) {
            countDown = 153 - (charCount - 918);
            lblCharCounter.setText(String.format("7 SMS %s", Integer.toString(countDown)));
        }
        else if(charCount >= 1071 && charCount <= 1224) {
            countDown = 153 - (charCount - 1071);
            lblCharCounter.setText(String.format("8 SMS %s", Integer.toString(countDown)));
        }
        else if(charCount >= 1224 && charCount <= 1377) {
            countDown = 153 - (charCount - 1224);
            lblCharCounter.setText(String.format("9 SMS %s", Integer.toString(countDown)));
        }
        else if(charCount >= 1377 && charCount <= 1530) {
            countDown = 153 - (charCount - 1377);
            lblCharCounter.setText(String.format("10 SMS %s", Integer.toString(countDown)));
        }


    }
);

它按预期工作,但我认为应该有更复杂或动态的方式来显示倒计时。在我看来,IF 语句太多了。

感谢任何帮助!

【问题讨论】:

  • 那应该是 GSM 吗?因为如果是这样,它要么是一条 160 bytes 的消息,要么包括第一个消息部分在内的每个消息部分都变成 154 bytes,因为它们都有一个等长的 6 字节 UDH。或 153 表示扩展 ID UDH。
  • 我从这里举了一个如何计算短信长度的例子:dashboard.messente.com/sms/calculator
  • 嗯,他们说的和我刚才说的一样。

标签: java string javafx sms countdown


【解决方案1】:

假设您使用 8 位 SMS 编码,其中每个字符占用一个字节,会发生以下情况:

  • 如果消息的长度最多(包括)160 个字符,则您只有一条消息。您剩余的字符数为 160 - n,其中 n 是键入的字符数。
  • 如果消息的长度超过 160 个字符(161 及以上),则给定 7 个字节的扩展 UDH,每个段的长度为 153 个字符。这意味着⌈n/153⌉段。并且到当前段结束的字符数是⌈n/153⌉×153-n。

这意味着你根本不应该有很多“if”语句:

if ( charCount <= 160 ) {
    nSegments = 1;
    countDown = 160 - charCount;
} else if ( charCount % 153 == 0 ) {
    nSegments = charCount / 153;
    countDown = 0;
} else {
    nSegments = charCount / 153 + 1;
    countDown = nSegments * 153 - charCount;
}
lblCharCounter.setText(String.format("%d SMS %d", nSegments, countDown) );

【讨论】:

    【解决方案2】:

    https://github.com/messente/sms-length-calculator 提供免费的 SMS 长度计算库,它可以检测编码并处理多部分 SMS 中扩展 gsm 7 位字符集的尾随转义字符。

    您还可以在http://messente.com/documentation/sms-length-calculator 学习和体验在线短信长度计算器

    【讨论】:

      【解决方案3】:

      我对 SMS 协议一无所知,但假设您的背景信息正确,您可以这样做:

      IntegerBinding textLength = Bindings.length(smsComposeArea.textProperty());
      
      IntegerBinding numberOfSms = Bindings.createIntegerBinding(() -> {
          if (textLength.get() <= 160) {
              return 1 ;
          } else if (textLength.get() <= 306) {
              return 2 ;
          } else {
              return 3 + (textLength.get() - 307) / 153 ;
          }
      }, textLength);
      
      IntegerBinding remainingChars = Bindings.createIntegerBinding(() -> {
          if (numberOfSms.get() == 1) {
              return 160 - textLength.get() ;
          } else if (numberOfSms.get() == 2) {
              return 306 - textLength.get() ;
          } else {
              return 306 + (numberOfSms.get() - 2) * 153 - textLength.get() ;
          }
      }, numberOfSms, textLength);
      
      lblCharCounter.textProperty().bind(Bindings.format("%d SMS %d", numberOfSms, remainingChars));
      

      如果@RealSkeptic 的答案中的计算是正确的,那么你可以这样做

      IntegerBinding textLength = Bindings.length(smsComposeArea.textProperty());
      
      IntegerBinding numberOfSms = Bindings.createIntegerBinding(() -> {
          if (textLength.get() <= 160) {
              return 1 ;
          } else {
              return 1 + (textLength.get() - 1) / 153 ;
          }
      }, textLength);
      
      IntegerBinding remainingChars = Bindings.createIntegerBinding(() -> {
          if (numberOfSms.get() == 1) {
              return 160 - textLength.get() ;
          } else {
              return numberOfSms.get() * 153 - textLength.get() ;
          }
      }, numberOfSms, textLength);
      
      lblCharCounter.textProperty().bind(Bindings.format("%d SMS %d", numberOfSms, remainingChars));
      

      或者也许(总共零个if 语句)

      IntegerBinding textLength = Bindings.length(smsComposeArea.textProperty());
      
      BooleanBinding singleSMS = textLength.lessThanOrEqualTo(160);
      
      IntegerBinding numberOfSms = Bindings.when(singleSMS).then(1).otherwise(
          textLength.subtract(1).divide(153).add(1));
      IntegerBinding remainingChars = Bindings.when(singleSMS).then(textLength.subtract(160).multiply(-1)).otherwise(
          numberOfSms.multiply(153).subtract(textLength));
      
      lblCharCounter.textProperty().bind(Bindings.format("%d SMS %d", numberOfSms, remainingChars));
      

      取决于你喜欢的风格。

      【讨论】:

      • 感谢您的考虑!这段代码效果很好!
      猜你喜欢
      • 1970-01-01
      • 2011-08-14
      • 1970-01-01
      • 1970-01-01
      • 2015-04-04
      • 1970-01-01
      • 2015-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多