`

Android平台 短信接送流程剖析(含编码)

 
阅读更多

Android平台 短信接送流程剖析(含编码)

 

//框架层分析:
//GsmSMSDispatcher.java
    /** {@inheritDoc} */
    @Override
    protected int dispatchMessage(SmsMessageBase smsb) { //该函数的返回值会在handleMessage里进行判断是否为Activity.RESULT_OK。要注意该返回值不为Activity.RESULT_OK的情况。

        // If sms is null, means there was a parsing error.
        if (smsb == null) {
            return Intents.RESULT_SMS_GENERIC_ERROR;
        }
        SmsMessage sms = (SmsMessage) smsb;
        boolean handled = false;

        if (sms.isTypeZero()) { //0x0100 0000 Short Message Type 0 The MS does not indicate the receipt of the type 0 short message to the user,and the message is not stored in the(U)SIM or ME.
            // As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not be
            // Displayed/Stored/Notified. They should only be acknowledged.
            Log.d(TAG, "Received short message type 0, Don't display or store it. Send Ack");
            return Intents.RESULT_SMS_HANDLED;
        }

        if (mSmsReceiveDisabled) {
            // Device doesn't support SMS service,
            Log.d(TAG, "Received short message on device which doesn't support "
                    + "SMS service. Ignored.");
            return Intents.RESULT_SMS_HANDLED;
        }

        // Special case the message waiting indicator messages
        if (sms.isMWISetMessage()) {
            updateMessageWaitingIndicator(true);
            handled = sms.isMwiDontStore();
            if (Config.LOGD) {
                Log.d(TAG, "Received voice mail indicator set SMS shouldStore=" + !handled);
            }
        } else if (sms.isMWIClearMessage()) {
            updateMessageWaitingIndicator(false);
            handled = sms.isMwiDontStore();
            if (Config.LOGD) {
                Log.d(TAG, "Received voice mail indicator clear SMS shouldStore=" + !handled);
            }
        }

        if (handled) {
            return Intents.RESULT_SMS_HANDLED;
        }

        if (!mStorageAvailable && (sms.getMessageClass() != MessageClass.CLASS_0)) {
            // It's a storable message and there's no storage available.  Bail.
            // (See TS 23.038 for a description of class 0 messages.)
            return Intents.RESULT_SMS_OUT_OF_MEMORY;
        }

        SmsHeader smsHeader = sms.getUserDataHeader();
         // See if message is partial or port addressed.
        if ((smsHeader == null) || (smsHeader.concatRef == null)) {
            // Message is not partial (not part of concatenated sequence).
            byte[][] pdus = new byte[1][];
            pdus[0] = sms.getPdu();

            if (smsHeader != null && smsHeader.portAddrs != null) {
                if (smsHeader.portAddrs.destPort == SmsHeader.PORT_WAP_PUSH) {
                    return mWapPush.dispatchWapPdu(sms.getUserData());
                } else {
                    // The message was sent to a port, so concoct a URI for it.
                    dispatchPortAddressedPdus(pdus, smsHeader.portAddrs.destPort);
                }
            } else {
                // Normal short and non-port-addressed message, dispatch it.
                dispatchPdus(pdus);  //注意该处
            }
            return Activity.RESULT_OK;
        } else {
            // Process the message part.
            return processMessagePart(sms, smsHeader.concatRef, smsHeader.portAddrs);
        }
}

//SMSDispatcher.java
protected void dispatchPdus(byte[][] pdus) {
        Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION);
        intent.putExtra("pdus", pdus);  //pdu数据
        intent.putExtra("encoding", getEncoding());
        dispatch(intent, "android.permission.RECEIVE_SMS");
    }



//应用层分析:
<!-- Require sender permissions to prevent SMS spoofing -->
        <receiver android:name=".transaction.PrivilegedSmsReceiver"
            android:permission="android.permission.BROADCAST_SMS">
            <intent-filter>
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>
//PrivilegedSmsReceiver类从SmsReceiver派生。在SmsReceiver(extends BroadcastReceiver)类中的onReceiveWithPrivilege 会将服务SmsReceiverService启动,然后在handleSmsReceived函数中对接收的消息进行处理。

//SmsReceiverService.java
//入口
  private void handleSmsReceived(Intent intent, int error) {
SmsMessage[] msgs = Intents.getMessagesFromIntent(intent); //解析intent,获取SmsMessage转①分析
    Uri messageUri = insertMessage(this, msgs, error); //插入数据 转②分析
        if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
            SmsMessage sms = msgs[0];
            Log.v(TAG, "handleSmsReceived" + (sms.isReplace() ? "(replace)" : "") +
                    " messageUri: " + messageUri +
                    ", address: " + sms.getOriginatingAddress() +
                    ", body: " + sms.getMessageBody());
        }

        if (messageUri != null) {
            // Called off of the UI thread so ok to block.
            MessagingNotification.blockingUpdateNewMessageIndicator(this, true, false);
        }
}


//①分析
//Telephony.java
public static final SmsMessage[] getMessagesFromIntent(Intent intent) {
Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
byte[][] pduObjs = new byte[messages.length][];

int encoding = intent.getIntExtra("encoding", -1);

for (int i = 0; i < messages.length; i++) {
                    pduObjs[i] = (byte[]) messages[i];
                }
                byte[][] pdus = new byte[pduObjs.length][];
                int pduCount = pdus.length;
                SmsMessage[] msgs = new SmsMessage[pduCount];
                for (int i = 0; i < pduCount; i++) {
                    pdus[i] = pduObjs[i];
                    if (-1 != encoding) {
                        msgs[i] = SmsMessage.createFromPdu(pdus[i], encoding);
                    } else {
                        msgs[i] = SmsMessage.createFromPdu(pdus[i]);  //创建PDU
                    }
                }
                return msgs;
            }
        }

//②分析:
private Uri insertMessage(Context context, SmsMessage[] msgs, int error) {
        // Build the helper classes to parse the messages.
        SmsMessage sms = msgs[0];

        if (sms.getMessageClass() == SmsMessage.MessageClass.CLASS_0) {
            displayClassZeroMessage(context, sms); //直接显示
            return null;
        } else if (sms.isReplace()) {
            return replaceMessage(context, msgs, error);  
        } else {
            return storeMessage(context, msgs, error);//存储短信 转③分析
        }
    }

//③分析
  private Uri storeMessage(Context context, SmsMessage[] msgs, int error) {
        SmsMessage sms = msgs[0];

        // Store the message in the content provider.
        ContentValues values = extractContentValues(sms); //提取信息
        values.put(Sms.ERROR_CODE, error);
        int pduCount = msgs.length;

        if (pduCount == 1) {
            // There is only one part, so grab the body directly.
            values.put(Inbox.BODY, replaceFormFeeds(sms.getDisplayMessageBody()));
        } else {
            // Build up the body from the parts.
            StringBuilder body = new StringBuilder();
            for (int i = 0; i < pduCount; i++) {
                sms = msgs[i];
                body.append(sms.getDisplayMessageBody());
            }
            values.put(Inbox.BODY, replaceFormFeeds(body.toString()));
        }

        // Make sure we've got a thread id so after the insert we'll be able to delete
        // excess messages.
        Long threadId = values.getAsLong(Sms.THREAD_ID);
        String address = values.getAsString(Sms.ADDRESS);  //注意对地址的处理
        if (!TextUtils.isEmpty(address)) {
            Contact cacheContact = Contact.get(address,true);
            if (cacheContact != null) {
                address = cacheContact.getNumber();
            }
        } else {
            address = getString(R.string.unknown_sender);
            values.put(Sms.ADDRESS, address);
        }

        if (((threadId == null) || (threadId == 0)) && (address != null)) {
            threadId = Threads.getOrCreateThreadId(context, address);
            values.put(Sms.THREAD_ID, threadId);
        }

        ContentResolver resolver = context.getContentResolver();

        Uri insertedUri = SqliteWrapper.insert(context, resolver, Inbox.CONTENT_URI, values);

        // Now make sure we're not over the limit in stored messages
        Recycler.getSmsRecycler().deleteOldMessagesByThreadId(getApplicationContext(), threadId);

        return insertedUri;
    }

 

  • 大小: 25 KB
分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    基于Android平台的校车管理系统设计与实现.docx

    ### 基于Android平台的校车管理系统设计与实现 #### 概述 本文主要探讨了一种基于Android平台的校车管理系统的设计与实现方案。该系统旨在解决当前高校多校区运营过程中遇到的交通问题,特别是在信息化管理方面...

    幼儿园接送管理系统

    幼儿园接送管理系统是一款专为幼教机构设计的高效、安全的管理工具,它将科技与教育相结合,旨在提升幼儿园的接送流程管理,确保孩子们的安全,同时减轻教师和家长的工作负担。这款系统以其形象、有趣、科学的特点,...

    幼儿固定接送人登记表.docx

    《幼儿固定接送人登记表》便是这一制度的重要组成部分,它不仅帮助幼儿园规范接送流程,更是保障幼儿安全的有效手段。 该登记表首先记录了幼儿的基本信息,包括姓名、性别、出生日期以及身份证号等。这些信息是幼儿...

    盛远校园安全幼儿接送系统

    “平安宝宝”幼儿学生接送管理系统由珠海盛远信息技术公司与多位知名幼教专家经过多年紧密合作潜心研发而成,该系统采用IC射频卡取代纸卡,利用接送机、控制主机与电脑管理软件组成一个智能接送管理系统,通过刷卡...

    多功能幼儿园安全进出接送管理系统

    【幼儿园安全进出接送管理系统】是一种专门针对幼儿园设计的高级安全管理系统,旨在确保幼儿接送过程的安全性和准确性。系统结合了多种身份验证技术,如刷卡、指纹、面部识别等,以确保只有授权的家长能够接送孩子。...

    接送(教育)APP

    这款应用结合了现代科技,如GPS定位技术、实时天气信息以及数据分析,以确保学生在上下学途中的安全,同时加强家长与学校的沟通。 首先,定位功能是接送APP的核心组成部分。通过集成GPS定位系统,应用能够准确追踪...

    迪安幼儿园接送系统 v8.0.1.zip

    迪安幼儿园接送系统提供全面的儿童信息记录,幼儿毕业、升级、调班、退学等过程信息可以得到完整的记录。 提供园长查询专栏,可查询幼儿接送记录、幼儿出勤率、日出勤月出勤统计, 可查询教师刷卡记录、日出勤、月...

    免费发送短信

    2. **免费短信平台**:一些网站和应用提供免费短信服务,这些服务可能由广告赞助,或者有发送数量限制,例如每天或每月可发送的短信数。 3. **验证码**:验证码(CAPTCHA)是一种自动识别计算机程序与人类的技术,...

    烟台威尔幼儿安全接送管理系统

    烟台威尔公司幼儿接送安全智能化管理系统,是为改善幼儿园安全环境而专门研发的产品。本系统针对幼儿园日常接送人员身份确认的盲点与当前局势下各种安全管理需求而设计,融合了安全接送、人员识别、语音呼叫、教师...

    幼儿园校车接送制度.doc

    《幼儿园校车接送制度》是确保幼儿安全出行的重要规定,旨在规范校车接送流程,保障孩子们的健康与安全。这份制度包含多个方面的内容,对于幼儿园的日常管理具有至关重要的作用。 首先,车辆接送老师需要严格遵守...

    新型幼儿接送系统解决方案

    加强幼儿接送安全管理是幼儿园管理的重中之重!

    幼儿园人脸识别接送安全系统.pdf

    【幼儿园人脸识别接送安全系统】是针对当前社会对幼儿教育安全日益增长的需求而设计的一种高科技解决方案。该系统结合了人脸识别技术和智能视频行为分析,旨在提升幼儿园的安全防范能力,加强家长与学校之间的互动,...

    行业文档-设计装置-一种接送货平台的开门、抬升及稳定联合机构.zip

    这份名为“行业文档-设计装置-一种接送货平台的开门、抬升及稳定联合机构.zip”的压缩包文件,显然包含了对一种创新设计的详细阐述,旨在优化货物的接送和搬运过程。该设计的核心在于一个综合了开门、抬升以及稳定...

    接送学生车辆安全预案精选.doc

    接送学生车辆安全,是社会普遍关注的话题。家长关心孩子的出行安全,学校关心学生的整体福祉,而政府则关注社会的稳定与和谐。因此,一份详尽周到的《接送学生车辆安全预案》的制定,显得尤为重要。 该预案的指导...

    信息化接送制度的利用.doc

    《幼安宝》系统能够详细记录每一次的接送情况,学校管理者通过数据分析,可以清晰掌握接送的高峰时段,进而合理安排人员和资源,优化校门管理流程。同时,系统还可以对异常接送行为进行预警,例如未按时接送或者频繁...

    去哪儿Android客户端部分界面分析 - 去哪儿旅行 V8.1.0

    ### 去哪儿Android客户端V8.1.0部分界面分析及优化建议 #### 一、酒店住宿业务 **主营业务类别:** 去哪儿的酒店住宿业务主要包括以下几类: 1. **酒店**:涵盖各类星级酒店、商务酒店等。 2. **公寓**:包括短期...

    2021最新幼儿园管理档案-校车接送学生记录表.doc

    这份"2021最新幼儿园管理档案-校车接送学生记录表"是确保幼童交通安全的重要工具,它详尽地记录了幼儿园校车每天接送学生的情况,为幼儿园管理者提供了全面的数据支持,以监控和优化接送流程。 首先,记录表的结构...

    南博幼儿园安全接送系统

    2. **家长接送流程**:家长通过刷卡识别身份,系统比对照片确认接送人身份,对于多家长接送情况,系统提供照片切换功能,确保接送安全。 3. **后台实时监控及语音播报**:家长刷卡信息实时上传后台,便于管理人员...

Global site tag (gtag.js) - Google Analytics