Android Mms 接收信息流程

信息的接收工作是由底层来完成的,当有一个
新的信息时底层完成接收后会以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 接收信息流程,布布扣,bubuko.com

时间: 2024-08-26 09:12:48

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

Android应用层View绘制流程与源码分析

Android应用层View绘制流程与源码分析 1 背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原理,记不记得最终分析结果就是下面的关系: 看见没有,如上图中id为content的内容就是整个View树的结构,所以对每个具体View对象的操作,其实就是个递归的实现. 前面<Android触摸屏事件派发机制详解与源码分析一(View篇)>文章的3-1

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

hexdump /dev/hidraw0就能看到usbhid设备传输过来的裸流 如:按下Input键 003ae60 0000 0096 8000 006b 0000 0000 0000 0000 * 003aea0 0000 0086 8000 0000 0000 0000 0000 0000 * 前面的估计是码流头(003ae60),还有按下(0096),松开(8000)等信息,识别按键有效信息是(006b) 006b其实是索引值,会在下表中寻找键值发送给Android,如:6b对应186

[Android][Framework]Activity启动流程

开始 从Launcher点击一个App图标,会触发如下动作: LauncherActivity.java protected void (ListView l, View v, int position, long id) { Intent intent = intentForPosition(position); startActivity(intent);} 走到了 Activity.java 的startActivity相关方法: public void startActivity(Int

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

本文将从引擎源代码Jni分析Cocos2d-x3.3RC0的Android Activity的启动流程,以下是具体分析. 1.引擎源代码Jni.部分Java层和C++层代码分析 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXV4aWt1b18x/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" > watermark/2/text/aHR0cDov

ANDROID自定义视图——onMeasure流程,MeasureSpec详解

简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量--onMeasure():决定View的大小 2.布局--onLayout():决定View在ViewGroup中的位置 3.绘制--onDraw():如何绘制这个View. 而第3步的onDraw系统已经封装的很好了,基本不用我们来操心,只需要专注到1,2两个步骤就中好了. 而这篇文章就来谈谈第一步,也是十分关键得一步:"测量(Measure)" Measure(): Measure的中文意思就是测量.所以它的

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

Android之SystemUI载入流程和NavigationBar的分析 本篇仅仅分析SystemUI的载入过程和SystemUI的当中的一个模块StatusBar的小模块NavigationBar,以Android6.0代码进行分析 AndroidManifest.xml <application android:name=".SystemUIApplication" android:persistent="true" android:allowClear

【小功能2】android获取手机信息(号码,内存,CPU,分辨率,MAC,IP,SD卡,IMEI,经纬度,信号强度等等)

为了实现一个功能,需要搜集手机信息,自己先在网上找了相关信息进行了汇总,主要是汇集手机的信息,一般想要的信息在手机设置->关于手机->状态消息里面包含了手机的各种信息,下面的代码中也主要显示了那些信息,但是源码的方法我还没有看,先把总结的贴出来.先上图(太多就截取几个).  上代码啦,太多了,就写主要代码了. // 获取Android手机中SD卡存储信息 获取剩余空间 public void getSDCardInfo() { // 在manifest.xml文件中要添加 /* * <u

Android process 的启动流程

1.android启动时所运行的进程: USER    PID     PPID    VSIZE    RSS    WCHAN         PC              NAMEroot  1  0  264   176  c00acc6c  0000c36c        S /initroot    28  1  724   308    c0051354  afe0c4cc  S /system/bin/shsystem  30 1  796   248  c026516c  a

Android Socket发送信息时闪退

尝试Android写Socket通信的时候,遇到的个坑,记录一下: 1.无法建立连接. 原因:没有添加网络使用权限请求: 解决方式:在"AndroidMainfest.xml"中添加<uses-permission android:name="android.permission.INTERNET"/> 2.建立连接后正常接收信息,但发送信息时直接闪退,LogCat中异常提示为:android.os.NetworkOnMainThreadExceptio