信息的接收工作是由底层来完成的,当有一个 新的信息时底层完成接收后会以Intent的方式来通知上层应用,信息的相关内容也包含在Intent当中,Android所支持的信息Intent都定 义在android.provider.Telephony.Intents里面。

短信的接收

短信接收,对于上层应用程序来讲就是要处理广播事件SMS_RECEIVED_ACTION,它是由Frameworks发出告诉上层有新的SMS已收 到。在Mms中,是由PrivilegedSmsReceiver来处理,它收到 SMS_RECEIVED_ACTION(android.provider.Telephony.Intents.SMS_RECEIVED_ACTION=”android.provider.Telephony.SMS_RECEIVED”) 后会启动SmsReceiverService来做具体的处理。

SmsReceiverService会先检查短信的类型,如果是Class0短信,直接在GUI中显示,不做任何其他的处理,也即不会存储到数据库中,也不会在Notification Bar中做Notification。

对于其他短信,会进行替换现有的消息,或是当作新消息插入。原则就是如果在数据库中已有的短信中,与新来的短信的原始地址和协议标识都一样,那么就把其替换成新进的短信,否则就当作新短信插入。

具体的替换流程:先用新进的短信生成一个ContentValues,再用短信的地址和协议标识当作条件到数据库中去查询,如果查到了,就替换,否则就存储。

存储的流程,也是先生成一个CotentValues,然后取出短信的Thread Id和地址,地址要与联系人数据库同步一下,以保证是能识别的地址。如果Thread Id不是合法的,那么就用同步过的地址尝试重新生成Thread Id,尝试5次。然后把刷新过的Thread Id放到ContentValues中,把ContentValues插入到数据库中。如果设置为把信息存储到SIM卡,还要调用SmsManager把 信息拷贝到SIM卡上。计算短信的大小,并更新至数据库。删除过期的短信,和超过数量限制的短信,然后返回插入后得到的短信Uri。

最后,对于替换或插入的短信,用Uri去StatusBar做Notification。

GUI在刷新列表时也能得到新短信,因为短信已经被存储到数据库中。

彩信的接收

彩信的接收过程与短信略有不同,它主要是由应用程序负责从彩信服务中心(MMSC Multimedia Messaging Service Center)下载彩信信息。大致的流程是Frameworks会先发出一条短信,告知应用程序有一个彩信,短信中含有一些信息比如过期日期,发送者手机 号码,彩信的URL等,然后应用程序自行通过HTTP取回URL所指的彩信内容。具体的流程为:

Telephony Frameworks会先发出一个 Intent:android.provider.Telephony.Intents.WAP_PUSH_RECEIVED_ACTION=”android.provider.Telephony.WAP_PUSH_RECEIVED” 告知上层应用有一个彩信来了。这个Intent中会含有一个”data”byte数组(通过byte[] data = intent.getByteArrayExtra(“data”)来获取),这个Byte数组是关于这个彩信的一些信息的描述,它是一个 NotificationInd,里面含有彩信的一些信息,比如发送者手机号码,彩信的ContentLocation(URL)。之后是由应用程序来决 定如何做下一步的处理。

在Mms中是由transaction.PushReceiver.java来接收WAP_PUSH_RECEIVED_ACTION,接收到彩信通知 Intent后,它会做一些预处理,把data字段取出来,用Pdu的工具解析成为GenericPdu,然后转化为NotificationInd,并 把它写入数据库,然后会启动TransactionService来做进一步的NOTIFICATION_TRANSACTION处理,同时把这个 NotificationInd的Uri也传过去。

TransactionService被唤起,在其onStartCommand中会处理一下把PushReceiver所传来的Intent放入自己的 MessageQueue中,然后在Handler.handleMessage()中处理TRANSACTION_REQUEST时处理 NOTIFICATION_TRANSACTION。先是加载默认的一些彩信相关的配置信息,主要是MMSC,Proxy和Port,这些都是与运营商相 关的信息,可以通过APN的设置来更改。TransactionService用PushReciver传来的NotificationInd的Uri和 加载的配置信息TransactionSettings构建一个NotificationTransaction对象。之 后,TransactionService检查其内的二个队列,或是加入Pending队列,或是直接处理(加入到正在处理队列),处理也是直接调用 NotificationTransaction.process()。

NotificationTransaction的process()方法是继承自父类Transaction的方法,它只是简单的开启一个新的线程,然后返回,这样就可以让Service去处理其他的Transaction Request了。

在线程中,首先从DownloadManager和TelephonyManager中加载一些配置信息,是否彩信设置为自动获取(auto retrieve),以及Telephony是否设置为数据延迟(DATA_SUSPEND),然后会采取不同的措施,再从 NotificationInd中取出彩信的过期日期。如果配置为不取数据(更确切的说,是不现在取数据),那么就先给DownloadManager的 状态标记为STATE_UNSTARTED,再给MMSC发送一个Notify Response Indication,之后结束处理,函数返回,彩信的通知处理流程到此为止。用户可以通过操作UI,用其他方法手动下载彩信,这个会在后面详细讨论。

如果设置为自动获取或者数据传输是畅通的,那么就把DownloadManager状态标记为START_DOWNLOADING并开始下载彩信数据。彩 信的获取是通过HTTP到彩信的ContentLocation(URL)取得数据。先是调用父类方法getPdu(),传入彩信的URL,最终调用 HttpUtils的httpConnection方法发送HTTP GET请求,MMSC会把彩信数据返回,作为getPdu()的返回值返回。拿到的是一个byte数组,需要用Pdu的工具解析成为 GenericPdu,然后用PduPersister把其写入数据库,再把彩信的大小更新到数据库,到这里一个彩信的接收就算完成了。剩下的就是,因为 已经获得了彩信的数据,所以要把先前的通知信息(NotificationInd)删除掉,然后更新一下相关的状态,给MMSC返回Notify Response Indication,结束处理。因为数据库已经有所改变,所以UI会收到ContentChanged事件,刷新UI列表,新信息就会显示出来。

如前所述,如果彩信配置设置为不自动获取,那么UI刷新了后就会显示彩信通知:到期日期,彩信大小等,并提供一个”Download”按扭。用户可以点击 按扭来下载彩信内容,点击按扭后,会启动TransactionService,把彩信通知的Uri,和RETRIEVE_TRANSACTION request打包进一个Intent传给TransactionService。TransactionService,像处理其他的 Transaction一样,都是放进自己的MessageQueue,然后加载默认的TransactionSettings,构建 RetrieveTransaction对象,然后处理调用RetrieveTransaction.process()。

RetrieveTransaction也是继承自Transaction,其process()也是创建一个线程,然后返回。在线程中,首先它用Pdu 工具根据Uri从数据库中加载出彩信通知(NotificationInd),从NotificationInd中取得彩信的过期日期,检查过期日期,如 果彩信已经过期,那么给MMSC发送Notify Response Indication。把DownloadManager状态标记为开始下载,然后如果彩信已过期,标记Transaction状态为Failed,然后 返回,结束处理流程。如果一切正常,会用getPdu()从彩信的ContentLocation(URL)上面获取彩信内容,它会用 HttpUtils.httpConnection()通过HTTP来获取,返回一个byte数组。用Pdu工具解析byte数组,得到 GenericPdu,检查一下是否是新信息,是否是重复的信息,如果重复,标记状为失败,然后返回,结束处理。如果是新信息,先把GenericPdu 用PduPersister写入数据库中,更新信息大小和ContentLocation(URL)到数据库中,到这里一个彩信其实已经全部获取完了。接 下来就是发送收到确认信息给MMSC,标记处理状态为成功,结束处理。这时UI应该监听到数据库变化,并刷新,新信息应该会显示给用户。

总结,与信息发送类似,数据库在接收信息过程中也扮演了重要角色,信息接收到后进行解析,然后就写入数据库,与发送不同,接收的信息没有那么多状态,一旦写入了数据库就意味着信息接收已经成功,UI也是只监听数据库的变化,一旦有变化立刻刷新显示信息。

Android Mms 接收信息流程的更多相关文章

  1. [Android] hid设备按键流程简述

    hexdump /dev/hidraw0就能看到usbhid设备传输过来的裸流 如:按下Input键 003ae60 0000 0096 8000 006b 0000 0000 0000 0000 * ...

  2. Android Mms专题之:Mms源码结构

    从软件的功能角度来讲,Mms分为对话列表,消息列表,短信编辑,彩信编辑,短信显示,彩信显示和配置. 从实现的角度来看,它分为GUI展示层,发送/接收,彩信解析,彩信附件,信息数据等,这些分类对应着源码 ...

  3. Android Mms之:深入MMS支持

    Composing and editing MMS在Android Mms应用里面的具体实现形式,或数据结构是SlideshowModel,它是一个每个节点为SlideModel的ArrayList, ...

  4. Android process 的启动流程

    Android process 的启动流程 1.android启动时所运行的进程: USER    PID     PPID    VSIZE    RSS    WCHAN         PC   ...

  5. Android窃取用户信息新思路

    0×01 我们能得到哪些android手机上的app敏感信息手机上的app敏感信息◦通讯录,通讯记录,短信◦各种app的帐号密码,输入信息资料等◦各种影音资料,照片资料◦等等0×02  我们有哪些方法 ...

  6. Cocos2d-x3.3RC0的Android编译Activity启动流程分析

    本文将从引擎源代码Jni分析Cocos2d-x3.3RC0的Android Activity的启动流程,以下是具体分析. 1.引擎源代码Jni.部分Java层和C++层代码分析 watermark/2 ...

  7. Android开机动画启动流程

    android开机动画启动流程   从android的Surface Flinger服务启动分析知道,开机动画是在SurfaceFlinger实例通过调用startBootAnim()启动的. 下面我 ...

  8. Android系统开机启动流程及init进程浅析

    Android系统启动概述 Android系统开机流程基于Linux系统,总体可分为三个阶段: Boot Loader引导程序启动Linux内核启动Android系统启动,Launcher/app启动 ...

  9. Android之SystemUI载入流程和NavigationBar的分析

    Android之SystemUI载入流程和NavigationBar的分析 本篇仅仅分析SystemUI的载入过程和SystemUI的当中的一个模块StatusBar的小模块NavigationBar ...

随机推荐

  1. BaseAdapter中重写getview的心得以及发现convertView回收的机制

    以前一直在用BaseAdapter,对于其中的getview方法的重写一直不太清楚.今天终于得以有空来探究它的详细机制. 下面先讲讲我遇到的几个问题: 一.View getview(int posit ...

  2. C++实现网格水印之调试笔记(三)—— 初有结果

    错误: error C2338: THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD 这种错误 ...

  3. MorningSale 介绍

    MorningSale是一个WEB端的收集门店销售数据,显示销售数据的简单系统,我相信该系统能够有效的提高销售公司在门店销售数据收集 汇总 分析方面的工作效率. 主要功能介绍如下: 1.查看某个店面 ...

  4. [GRYZ2015]Graph

    题目描述 给出 N 个点,M 条边的有向图,对于每个点 v,求 A(v) 表示从点 v 出发,能到达的编号最大的点. 输入格式 第 1 行,2 个整数 N,M. 接下来 M 行,每行 2 个整数 Ui ...

  5. 如何在 Windows Azure 的虚拟机 ubuntu 上面安装和配置 openVPN(二)

    第二步:登录到虚拟机 一旦创建好虚拟机后,默认azure会打开TCP 22端口,即SSH的端口.所以,我们可以通过远程连接,访问和管理该虚拟机. 首先,下载一个PuTTY软件.该软件很简单,就一个可执 ...

  6. Emmet:HTML/CSS代码快速编写神器(转)

    Emmet的前身是大名鼎鼎的Zen coding,如果你从事Web前端开发的话,对该插件一定不会陌生.它使用仿CSS选择器的语法来生成代码,大大提高了HTML/CSS代码编写的速度,比如下面的演示: ...

  7. 一起刷LeetCode1-Two Sum

    感觉有必要重新刷刷题了,为以后找工作做做准备,选择LeetCode+topcoder上的Data Science Tutorials, 争取每天晚上10:00开始刷一道,复习一下相关知识点. ---- ...

  8. 办公室网络二三事 - chunyu

    开始的时候,我们办公室拉了两条家庭百兆宽带,两条宽带分别接到路由器的wan1/wan2口上,我们愉快的工作愉快的上网. 后来,再拉了一条十兆企业专线,接到了路由器的wan3口上面,配了一些静态路由,希 ...

  9. algorithm@ Shortest Path in Directed Acyclic Graph (O(|V|+|E|) time)

    Given a Weighted Directed Acyclic Graph and a source vertex in the graph, find the shortest paths fr ...

  10. 《Java数据结构与算法》笔记-CH4-1栈的实现

    class StackX{ private int maxSize; private long[] stackArray; private int top; public StackX(int siz ...