1

我正在编写一个 Android APK 来通过 SMS 管理 GPS 跟踪器。我的软件有一个特殊的通知部分,可以解码设备通过 SMS 消息发送的所有警报。问题是一些电话公司对 SMS 长度使用不同的限制,所以我的代码由于消息被截断而失败。我测试了三个不同的本地公司,其中一些使用 140 个字符,而另一些使用 70 个字符。我的问题...是否有任何可靠的方法来获取该参数?我已经阅读了所有 SDK 文档,除了明显的常量 MAX_USER_DATA_BYTES 之外没有发现任何类似的东西。

4

1 回答 1

2

由于这是一个非常复杂的问题,需要将标准和协议的不同部分拼凑在一起,我决定将我找到的所有信息发布给像我这样需要解决这个问题的人。

所有检查都应直接在 PDU 数据中完成,访问位和字节,在 SmsMessage 中使用getPdu()或直接从SMSPDU中的 Bundle 访问数组。onReceive()BroadcastReceiver

首先,我们需要检查两件事来检测多部分短信:

  1. 的存在IDH,位 6 inPDU_TYPE
  2. 中存在多部分指示符,信息IDH的第二个字节UDH

在检测到多部分消息后,我们需要通过检查 CSMS 标识符、部分数量和部分索引来识别属于同一多部分的消息。

/**
 * EXAMPLE OF A PDU 
 *
 * 07 length of SMSC info in bytes
 * 91 type of address
 * 551218317600 SMSC address (variable size)
 * 04 PDU_TYPE to check for IDH embedded test bit 6  0=not UDH  1=has UDH
 * 0B address length in nibbles, here is 11 nibbles so its 6 bytes
 * 81 address type
 * 1089920478F1 sender number (variable size)
 * 00 TP-PID
 * 08 TP-DCS
 * 31105161225188  TP-SCTS  timestamp
 * 38  TP-UDL user data length
 * [USER DATA STARTS HERE] When UDH info is embedded, starts in first
 *                         bytes of user data
 * 
 * EXAMPLE OF UDH for 8 bit CSMS reference (unique number, indicates
 * parts belong to same message)
 *
 * 05 UDH length in bytes
 * 00 For multipart 8 bits CSMS it is 00, for 16bits CSMS it is 08
 * 03 length of header
 * 48 CSMS reference number, this identify SMSs that belong
 *                           to same multi-part
 * 02 total parts of this sequence (in this case, 2 parts)
 * 02 sequence number (in this case, 2 of 2)
 *
 *
 * EXAMPLE OF UDH for 16 bit CSMS reference (unique number, indicates
 * parts belong to same message)
 *
 * 06 UDH length in bytes
 * 00 For multipart 8 bits CSMS it is 00, for 16bits CSMS it is 08
 * 04 length of header
 * 4823 16 bits CSMS reference number, this identify SMSs that belong
 *                                     to the same multi-part
 * 02 total parts of this sequence (in this case, 2 parts)
 * 01 sequence number (in this case, 1 of 2)
 * 
 */

// SOME HELPERS TO CHECK FOR MULTIPART INSIDE PDU

private final byte UDH_BITMASK = 0x60;
private final byte MULTIPART_8BITSEQ = 0x00;
private final byte MULTIPART_16BITSEQ = 0x08;

private final int TP_ADDLENGTH_LEN=1;
private final int TP_ADDTYPE_LEN=1;
private final int TP_PID_LEN=1;
private final int TP_DCS_LEN=1;
private final int TP_SCTS_LEN=7;
private final int TP_UDL_LEN=1;

/**
 * Check if this PDU message is multi part
 * @param pdu
 * @return
 */
private boolean isMultiPart(byte[] pdu)
{
    // get length of first part+1 SMSC index to PDU type
    int idx= pdu[0]+TP_ADDLENGTH_LEN;

    if((pdu[idx] & UDH_BITMASK) != 0) // has UDH ??
    {
        // 00=length of UDH  01=type
        int udataidx = getUserDataIndex(pdu);
        if( (pdu[udataidx+1] == MULTIPART_8BITSEQ)
         || (pdu[udataidx+1] == MULTIPART_16BITSEQ))
            return true;
    }

    return false;
}


/**
 * Return index for user data part. Used to retrieve UDH info
 * @param pdu
 * @return
 */
private int getUserDataIndex(byte[] pdu)
{
    // get index to  ADDRESS length
    int idx=pdu[0]+ TP_ADDLENGTH_LEN + TP_ADDTYPE_LEN;

    // get length in nibbles
    int oalength = pdu[idx];

    // convert to bytes with padding for odd values
    int oalengthinbytes = (oalength + 1) / 2;
    return(idx + TP_ADDLENGTH_LEN + TP_ADDTYPE_LEN + oalengthinbytes +
            TP_PID_LEN + TP_DCS_LEN +  TP_SCTS_LEN + TP_UDL_LEN);
}
于 2013-01-16T14:50:48.200 回答