Android:获取短信发送时间

Android:获取短信发送时间,第1张

概述我已经开发了一个用于发送SMS消息的应用程序,它使用BroadcastReceivers成功地发送和(未)发送了消息.在邮件的接收方中,我想获取时间,以便将邮件发送给目标接收方.由于发送和接收设备有时都可能会关闭,因此我认为将接收广播的时间视为实际的发送时间是不正确的.有没有办法在我的广

我已经开发了一个用于发送SMS消息的应用程序,它使用broadcastReceivers成功地发送和(未)发送了消息.

在邮件的接收方中,我想获取时间,以便将邮件发送给目标接收方.由于发送和接收设备有时都可能会关闭,因此我认为将接收广播的时间视为实际的发送时间是不正确的.

有没有办法在我的广播接收器中获得正确的传送时间?
谢谢.

解决方法:

这是一个可行的解决方案.

通过研究com.android.internal.telephony.gsm.SmsMessage类(AndroID的内部类,用于解析GSM / 3GPP网络上的SMS PDU)的源代码,我发现SMS-STATUS-REPORTS(=“交付报告”)包含第二个时间戳值,即“放电”时间”.不幸的是,公共SmsMessage类未公开此值,它是您想要的传送时间(由传送网络基础结构感知).

使用下面的类,您可以通过调用getdischargeTime()获得此值.

getServiceCenterTimeStamp()方法返回的值与您从SmsMessage#getTimestampMillis()获得的值相同,即SMS服务中心接收原始消息的时间.

导入androID.telephony.PhoneNumberUtils;
    导入androID.text.format.Time;

/** * A helper class to parse (from pdu byte[]) and represent a GSM SMS-STATUS-REPORT message (= delivery report). *  * Only works for GSM/3GPP networks (not CDMA/3GPP2). *  * Based on the source code of the following AndroID classes: *  - com.androID.internal.telephony.gsm.SmsMessage (almost everything) *  - com.androID.internal.telephony.uicc.IccUtils (1 method) * All licensed under the Apache license, Version 2.0. * The code is taken from AndroID v5.1.0_r1 (+ 1 line from v4.2_r1). *  * @author mstevens */public class SMsstatusReport{    static final String LOG_TAG = SMsstatusReport.class.getSimplename();    /**     * TP-Message-Type-Indicator     * 9.2.3     */    private int mMti;    /**     *  TP-Status - status of a prevIoUsly submitted SMS.     *  This fIEld applIEs to SMS-STATUS-REPORT messages.  0 indicates success;     *  see TS 23.040, 9.2.3.15 for description of other possible values.     */    private int mStatus;    /**     *  TP-Status - status of a prevIoUsly submitted SMS.     *  This fIEld is true iff the message is a SMS-STATUS-REPORT message.     */    private boolean mIsstatusReportMessage = false;    /**     * TP-Service-Centre-Time-Stamp     */    private long serviceCenterTimeStamp;    /**     * TP-discharge-Time     */    private long dischargeTime;    /**     * Constructor     *      * @param pdu     */    public SMsstatusReport(byte[] pdu)    {        // Parse:        createFromPdu(pdu);        if(!mIsstatusReportMessage)            throw new IllegalArgumentException("This is not the pdu of a GSM SMS-STATUS-REPORT message");    }    /**     * TS 27.005 3.1, &lt;pdu&gt; deFinition "In the case of SMS: 3GPP TS 24.011 [6]     * SC address followed by 3GPP TS 23.040 [3] TPDU in hexadecimal format:     * ME/TA converts each octet of TP data unit into two IRA character long     * hex number (e.g. octet with integer value 42 is presented to TE as two     * characters 2A (IRA 50 and 65))" ...in the case of cell broadcast,     * something else...     *      * @param pdu     *      * @see Adapted from {@link com.androID.internal.telephony.gsm.SmsMessage#createFromPdu(byte[])} (originally static)     */    private voID createFromPdu(byte[] pdu)    {        PduParser p = new PduParser(pdu);        /*Object mScAddress = */p.getSCAddress();        // TP-Message-Type-Indicator        // 9.2.3        int firstByte = p.getByte();        mMti = firstByte & 0x3;        switch (mMti)        {            // TP-Message-Type-Indicator            // 9.2.3            case 0:            case 3: //GSM 03.40 9.2.3.1: MTI == 3 is Reserved.                    //This should be processed in the same way as MTI == 0 (Deliver)                //parseSmsDeliver(p, firstByte);                break;            case 1:                //parseSmssubmit(p, firstByte);                break;            case 2:                parseSmsstatusReport(p, firstByte);                break;            default:                throw new RuntimeException("Unsupported message type");        }    }    /**     * Parses a SMS-STATUS-REPORT message.     *     * @param p A PduParser, cued past the first byte.     * @param firstByte The first byte of the PDU, which contains MTI, etc.     */    private voID parseSmsstatusReport(PduParser p, int firstByte)    {        mIsstatusReportMessage = true;        // TP-Message-Reference        /*int mMessageRef = */p.getByte();        // TP-RecipIEnt-Address        /*Object mRecipIEntAddress = */p.getAddress();        // TP-Service-Centre-Time-Stamp        serviceCenterTimeStamp = p.getSCTimestampMillis();        // TP-discharge-Time (line taken from AndroID v4.2_r1)        dischargeTime = p.getSCTimestampMillis();        // TP-Status        mStatus = p.getByte();        // The following are optional fIElds that may or may not be present.        if (p.moreDataPresent())        {/*            // TP-Parameter-Indicator            int extraParams = p.getByte();            int moreExtraParams = extraParams;            while ((moreExtraParams & 0x80) != 0) {                // We only kNow how to parse a few extra parameters, all                // indicated in the first TP-PI octet, so skip over any                // additional TP-PI octets.                moreExtraParams = p.getByte();            }            // As per 3GPP 23.040 section 9.2.3.27 TP-Parameter-Indicator,            // only process the byte if the reserved bits (bits3 to 6) are zero.            if ((extraParams & 0x78) == 0) {                // TP-Protocol-IDentifIEr                if ((extraParams & 0x01) != 0) {                    mProtocolIDentifIEr = p.getByte();                }                // TP-Data-Coding-Scheme                if ((extraParams & 0x02) != 0) {                    mDataCodingScheme = p.getByte();                }                // TP-User-Data-Length (implIEs existence of TP-User-Data)                if ((extraParams & 0x04) != 0) {                    boolean hasUserDataheader = (firstByte & 0x40) == 0x40;                    parseUserData(p, hasUserDataheader);                }            }*/        }    }    /**     * @return whether or not the original message was received on the receiver handset     */    public boolean isReceived()    {        return mStatus == 0;    }    /**     * @return the serviceCenterTimeStamp     */    public long getServiceCenterTimeStamp()    {        return serviceCenterTimeStamp;    }    /**     * @return the dischargeTime     */    public long getdischargeTime()    {        return dischargeTime;    }    private static class PduParser    {        byte mPdu[];        int mCur;        PduParser(byte[] pdu)        {            mPdu = pdu;            mCur = 0;        }        /**         * Parse and return the SC address prepended to SMS messages coming via the TS 27.005 / AT interface.         * Returns null on invalID address         */        String getSCAddress()        {            int len;            String ret;            // length of SC Address            len = getByte();            if(len == 0)            {                // no SC address                ret = null;            }            else            {                // SC address                try                {                    ret = PhoneNumberUtils.calledPartyBCDToString(mPdu, mCur, len);                }                catch(RuntimeException tr)                {                    ret = null;                }            }            mCur += len;            return ret;        }        /**         * returns non-sign-extended byte value         */        int getByte()        {            return mPdu[mCur++] & 0xff;        }        /**         * Any address except the SC address (eg, originating address)         * See TS 23.040 9.1.2.5         *          * mstevens: Made NON-FUNCTIONAL to remove dependency on internal AndroID classes. Always returns null but skips right number of bytes.         */        Object/*GsmSmsAddress*/ getAddress()        {            //GsmSmsAddress ret;            // "The Address-Length fIEld is an integer representation of            // the number fIEld, i.e. excludes any semi-octet containing only            // fill bits."            // The TOA fIEld is not included as part of this            int addressLength = mPdu[mCur] & 0xff;            int lengthBytes = 2 + (addressLength + 1) / 2;            /*try {                ret = new GsmSmsAddress(mPdu, mCur, lengthBytes);            } catch (ParseException e) {                ret = null;                //This is caught by createFromPdu(byte[] pdu)                throw new RuntimeException(e.getMessage());            }*/            mCur += lengthBytes;            return null;//ret;        }        /**         * Parses an SC timestamp and returns a currentTimeMillis()-style timestamp         *          * @see http://en.wikipedia.org/wiki/GSM_03.40#Time_Format         */        long getSCTimestampMillis() {            // TP-Service-Centre-Time-Stamp            int year = gsmBcdBytetoInt(mPdu[mCur++]);            int month = gsmBcdBytetoInt(mPdu[mCur++]);            int day = gsmBcdBytetoInt(mPdu[mCur++]);            int hour = gsmBcdBytetoInt(mPdu[mCur++]);            int minute = gsmBcdBytetoInt(mPdu[mCur++]);            int second = gsmBcdBytetoInt(mPdu[mCur++]);            // For the timezone, the most significant bit of the            // least significant nibble is the sign byte            // (meaning the max range of this fIEld is 79 quarter-hours,            // which is more than enough)            byte tzByte = mPdu[mCur++];            // Mask out sign bit.            int timezoneOffset = gsmBcdBytetoInt((byte) (tzByte & (~0x08)));            timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset : -timezoneOffset;            Time time = new Time(Time.TIMEZONE_UTC);            // It's 2006.  Should I really support years < 2000?            time.year = year >= 90 ? year + 1900 : year + 2000;            time.month = month - 1;            time.monthDay = day;            time.hour = hour;            time.minute = minute;            time.second = second;            // Timezone offset is in quarter hours.            return time.toMillis(true) - (timezoneOffset * 15 * 60 * 1000);        }        /**         * Decodes a GSM-style BCD byte, returning an int ranging from 0-99.         *         * In GSM land, the least significant BCD digit is stored in the most         * significant nibble.         *         * Out-of-range digits are treated as 0 for the sake of the time stamp,         * because of this:         *         * TS 23.040 section 9.2.3.11         * "if the MS receives a non-integer value in the SCTS, it shall         * assume the digit is set to 0 but shall store the entire fIEld         * exactly as received"         *          * @see Taken from com.androID.internal.telephony.uicc.IccUtils         */        public static int gsmBcdBytetoInt(byte b)        {            int ret = 0;            // treat out-of-range BCD values as 0            if((b & 0xf0) <= 0x90)                ret = (b >> 4) & 0xf;            if((b & 0x0f) <= 0x09)                ret +=  (b & 0xf) * 10;            return ret;        }        public boolean moreDataPresent()        {            return (mPdu.length > mCur);        }    }}

一些免责声明:

>这仅适用于GSM / 3GPP网络,不适用于CDMA / 3GPP;
>因为它基于AndroID源代码,所以上面的代码是Apache license v2.0许可的.

总结

以上是内存溢出为你收集整理的Android:获取短信发送时间全部内容,希望文章能够帮你解决Android:获取短信发送时间所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1075760.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存