转载http://www.oschina.net/question/54100_36978
MMS - 入口和联系人,想到什么说什么。
在MMS中最重要的两个ui,或者说是用户操作短信的入口,一个是conversationList(短信列表界面) ,另一个就是ComposeMessageActiity(单个对话或者短信),以后简称CMA。
每个CMA 录属于一个Conversation或者不属于任何conversation(无收件人草稿);每个converation由独立的threadId来相互区分
每个CMA有一个WorkingMessage,唯一,表示这个thread(话题)下,用户编辑的短信草稿。
CMA和ConversationList的launch mode都是singleTop,(关于launch mode,请参考 http://androidappdocs.appspot.com/guide/topics/fundamentals.html)
android的launch mode涉及到Task和Activity,简单点说,用户看到的每个界面,基本上都是一个个的Activity,而这些Activity以栈的形式放入在Task中,比如进栈操作由用户的点击进入其他Activity产生,出栈由用户按下back键完成。
一个Task的属性,由他拥有的第一个Activity,也就是栈底的那个activity决定。
一个Activity的launch mode,就是决定他在Task中的表现特点,比如默认的standard模式,就是没有特点,可以在一个Task里随便加,随便加几个instance都成,还能同时在多个Task中共存,就像IE打开网页那种感觉,没有什么限制。
singleTask是整个手机中只能有一个,而且必须出现在这个Task的栈底。
singleInstance表示这个Acitivity独占了整个Task,这个task只有这么一个Activity,最霸道。
singleTop和standard有点类似,区别是,他会去重用Task顶层的他自己的实体,有点绕,像文档上说的,举个例子就明白了。
比如说ABC是3个Activity,mode是standard,在一个栈中的排列是A-B-C,这时候由C再new一个C的intent时,Task变成A-B-C-C;
如果C的mode凑巧是singleTop,那么顶部只能是一个C,也就是在A-B-C这个场景下,再来一个C时,Task变成A-B-C。只是现在顶部的C已经是崭新的C,不是原来那个。
另外,比如launcher按下一个C的图标,这时候,系统会检索所有以C为栈底的Task,如果找到了,就把他起起来,如果没有,就起一个新的。
(I)
CMA的 onSaveInstanceState 函数
引用一段在文档上的说明,
Called to retrieve per-instance state from an activity before being killed
so that the state can be restored in onCreate(Bundle) or onRestoreInstanceState(Bundle) (the Bundle populated by this method will be passed to both).
This method is called before an activity may be killed so that when it comes back some time in the future it can restore its state. For example, if activity B is launched in front of activity A, and at some point activity A is killed to reclaim resources, activity A will have a chance to save the current state of its user interface via this method so that when the user returns to activity A, the state of the user interface can be restored via onCreate(Bundle) or onRestoreInstanceState(Bundle).
Do not confuse this method with activity lifecycle callbacks such as onPause(), which is always called when an activity is being placed in the background or on its way to destruction, or onStop() which is called before destruction. One example of when onPause() and onStop() is called and not this method is when a user navigates back from activity B to activity A: there is no need to call onSaveInstanceState(Bundle) on B because that particular instance will never be restored, so the system avoids calling it. An example when onPause() is called and not onSaveInstanceState(Bundle) is when activity B is launched in front of activity A: the system may avoid calling onSaveInstanceState(Bundle) on activity A if it isn't killed during the lifetime of B since the state of the user interface of A will stay intact.
The default implementation takes care of most of the UI per-instance state for you by calling onSaveInstanceState() on each view in the hierarchy that has an id, and by saving the id of the currently focused view (all of which is restored by the default implementation of onRestoreInstanceState(Bundle)). If you override this method to save additional information not captured by each individual view, you will likely want to call through to the default
implementation, otherwise be prepared to save all of the state of each view yourself.
If called, this method will occur before onStop(). There are no guarantees about whether it will occur before or after onPause().
,大概是说: 这个函数的调用,和onPause()以及onStop()都有区别,但是能保证如果CMA被杀死,他能在onStop()前被调用。
这个函数调用发生的场景发生在类似于,CMA调用了某个Activity: AS, 这个AS运行中CMA不幸要阵亡了,那么,因为用户的界面在AS上,用户可能希望在按下back建或者从home进入之类的场景下,还能重现出CMA当时的状态,于是有了这个函数被调用的必要。
在CMA的onSaveInstanceState()函数中,会保存一份联系人,同时保存workingMessage的subject标题/body正文/uri草稿在数据库中的位置 。
这些信息就够恢复用户离开时的场景了。
(II) initialize
mWorkingMessage = WorkingMessage.createEmpty(this);
initActivityState时,
如果之前CMA在onSaveInstanceState时报存了联系人,则会从旧有联系人里面读取出来,联系人相互之间用“;”分割开 。 workingmessage也由之前保存的变量初始化,这个初始化就基本完成了,返回了。
如果没有保存,则从传入的intent中读取thread_id值,进而得到初始化需要的信息:
如果thread_id>0 ; 那么mConversation从Conversation的cache中,有thread_id取得。
如果thread_id<=0;那么从intent的Date获得thread_id,
再不行,就说明之前没有过这个thread了,可能用户是手写的地址,就从address去产生一个ContactList,从ContactList去Conversation的Cache里匹配得到相应的Conversation
这时候,如果匹配还是没有得到Conversation时,Cache里就会偷偷生成一个Conversation返回回来,适用于你这个状况。
Cache用来保证联系人匹配的所有消息,被放入同一个对话(thread)中。
再还有如果联系人也是空的,那么直接产生一个新的Conversation; 这个Conversation是廉价的,因为他没有thread_id,不被放入cache,在使用ensurethreadid之前,他可以创建无数个,可以随意调用创建出来。
有了conversation之后,就可以initMessageList,查询显示出这个thread下面的所有消息
handleSendIntent() 函数
判断是否由一个intent调用起来的CMA,
特征是intent可以得到Action和mimeType; 比如ACTION_SEND和ACTION_SEND_MULTIPLE; 文件流比如EXTRA_STREAM,字符串EXTRA_TEXT;
遇到这些情况,直接添加附件,其他流程类似于messagelist继续。
handleForwardedMessage() 函数
在不是intent调用的CMA时,检查是不是由转发发起的调用
这些检查归根到底是检查intent的extra中带的关键字,比如 “forwarded_message” , intent.getAction() ,“recipients” , “thread_id”
(III)
CMA的入口只有两个:
onCreate()和 onNewIntent()
这俩个初始化函数的核心是: initialize(Bundle savedInstanceState)
onCreate比较简单,他的内容主要是:
初始化变量 ; 初始化UI ; initialize()
onNewIntent, 只发生在,singleTop的场景,也就是说,已经有一个CMA在Task的顶部(也就是用户的视线内,或者被隐藏到后台了),
之后在从launcher的短信或者从statusbar的短信入口进入时,就会调用到onNewIntent。
在onNewIntent调用时,需要保存原有的CMA的状态,并用新的Intent里的信息,形成新的CMA,从而替代他。
原有的Intent的信息在mConversation和mWorkingMessage里面,
比如mConversation.getThreadId() 得到threadId,如果threadId是0,则说明原来的CMA包含一个草稿,需要保存
比如mWorkingMessage里面,包含最新的收件人信息,需要用mWorkingMessage.syncWorkingRecipients()复制到conversation中,这时候把这份联系人复制到Conversation里,以备保存草稿用
关于新起来的这个Intent和原来的CMA是不是属于同一个conversation的判断;
判断的唯一依据是联系人列表
新来的intent的uri调用uri.getSchemeSpecificPart()函数返回的是一个由“;“分割的电话号码序列,可以拼装成ContactList,是新来的联系人列表。
通过对比,可以知道原来的和信来的两者之间的ContactList是否相同;
如果对比是不同的,那么新的intent将占据CMA,如果对比相同,则没有更换Conversation以及占据这个操作。
‘这个占据包括三步:
1,saveDraft() 函数 ,保存原有conversation的草稿 ,(mRecipientsContainer同步到workingmessage中去。)
2,initialize(null)函数 ,也即(I)里提到的流程,只是传入的初始化参数是null,也就是说在init时,没有在bundle里提供联系人
3,loadMessageContent()函数,查询Conversation下的消息状况,初始化联系人信息,画相关按钮界面
(IV)总结
onCreate()入口:
1 新建短信;bundle和intent都为空初始化
2 在conversation点击一条短信: intent非空,由intent初始化
3 转发:handleForwardedMessage时把intent中的uri中的数据取出来放入mWorkingMessage,有文本以及可能的彩信;同时把list的cursor置空。
4 文件或者文字通过短信发送
5 handleSendIntent处理,如果intent中有extra内容,可以附带Intent.EXTRA_STREAM或者Intent.EXTRA_TEXT;
前者就是一个文件流,可以解析出来多媒体文件,后者是一个文本,
还有一种是Intent.ACTION_SEND_MULTIPLE, 不怎么用,看名字大概知道是怎么回事,不过不懂细节。
MMS - 入口和联系人,想到什么说什么。
在MMS中最重要的两个ui,或者说是用户操作短信的入口,一个是conversationList(短信列表界面) ,另一个就是ComposeMessageActiity(单个对话或者短信),以后简称CMA。
每个CMA 录属于一个Conversation或者不属于任何conversation(无收件人草稿);每个converation由独立的threadId来相互区分
每个CMA有一个WorkingMessage,唯一,表示这个thread(话题)下,用户编辑的短信草稿。
CMA和ConversationList的launch mode都是singleTop,(关于launch mode,请参考 http://androidappdocs.appspot.com/guide/topics/fundamentals.html)
android的launch mode涉及到Task和Activity,简单点说,用户看到的每个界面,基本上都是一个个的Activity,而这些Activity以栈的形式放入在Task中,比如进栈操作由用户的点击进入其他Activity产生,出栈由用户按下back键完成。
一个Task的属性,由他拥有的第一个Activity,也就是栈底的那个activity决定。
一个Activity的launch mode,就是决定他在Task中的表现特点,比如默认的standard模式,就是没有特点,可以在一个Task里随便加,随便加几个instance都成,还能同时在多个Task中共存,就像IE打开网页那种感觉,没有什么限制。
singleTask是整个手机中只能有一个,而且必须出现在这个Task的栈底。
singleInstance表示这个Acitivity独占了整个Task,这个task只有这么一个Activity,最霸道。
singleTop和standard有点类似,区别是,他会去重用Task顶层的他自己的实体,有点绕,像文档上说的,举个例子就明白了。
比如说ABC是3个Activity,mode是standard,在一个栈中的排列是A-B-C,这时候由C再new一个C的intent时,Task变成A-B-C-C;
如果C的mode凑巧是singleTop,那么顶部只能是一个C,也就是在A-B-C这个场景下,再来一个C时,Task变成A-B-C。只是现在顶部的C已经是崭新的C,不是原来那个。
另外,比如launcher按下一个C的图标,这时候,系统会检索所有以C为栈底的Task,如果找到了,就把他起起来,如果没有,就起一个新的。
(I)
CMA的 onSaveInstanceState 函数
引用一段在文档上的说明,
Called to retrieve per-instance state from an activity before being killed
so that the state can be restored in onCreate(Bundle) or onRestoreInstanceState(Bundle) (the Bundle populated by this method will be passed to both).
This method is called before an activity may be killed so that when it comes back some time in the future it can restore its state. For example, if activity B is launched in front of activity A, and at some point activity A is killed to reclaim resources, activity A will have a chance to save the current state of its user interface via this method so that when the user returns to activity A, the state of the user interface can be restored via onCreate(Bundle) or onRestoreInstanceState(Bundle).
Do not confuse this method with activity lifecycle callbacks such as onPause(), which is always called when an activity is being placed in the background or on its way to destruction, or onStop() which is called before destruction. One example of when onPause() and onStop() is called and not this method is when a user navigates back from activity B to activity A: there is no need to call onSaveInstanceState(Bundle) on B because that particular instance will never be restored, so the system avoids calling it. An example when onPause() is called and not onSaveInstanceState(Bundle) is when activity B is launched in front of activity A: the system may avoid calling onSaveInstanceState(Bundle) on activity A if it isn't killed during the lifetime of B since the state of the user interface of A will stay intact.
The default implementation takes care of most of the UI per-instance state for you by calling onSaveInstanceState() on each view in the hierarchy that has an id, and by saving the id of the currently focused view (all of which is restored by the default implementation of onRestoreInstanceState(Bundle)). If you override this method to save additional information not captured by each individual view, you will likely want to call through to the default
implementation, otherwise be prepared to save all of the state of each view yourself.
If called, this method will occur before onStop(). There are no guarantees about whether it will occur before or after onPause().
,大概是说: 这个函数的调用,和onPause()以及onStop()都有区别,但是能保证如果CMA被杀死,他能在onStop()前被调用。
这个函数调用发生的场景发生在类似于,CMA调用了某个Activity: AS, 这个AS运行中CMA不幸要阵亡了,那么,因为用户的界面在AS上,用户可能希望在按下back建或者从home进入之类的场景下,还能重现出CMA当时的状态,于是有了这个函数被调用的必要。
在CMA的onSaveInstanceState()函数中,会保存一份联系人,同时保存workingMessage的subject标题/body正文/uri草稿在数据库中的位置 。
这些信息就够恢复用户离开时的场景了。
(II) initialize
mWorkingMessage = WorkingMessage.createEmpty(this);
initActivityState时,
如果之前CMA在onSaveInstanceState时报存了联系人,则会从旧有联系人里面读取出来,联系人相互之间用“;”分割开 。 workingmessage也由之前保存的变量初始化,这个初始化就基本完成了,返回了。
如果没有保存,则从传入的intent中读取thread_id值,进而得到初始化需要的信息:
如果thread_id>0 ; 那么mConversation从Conversation的cache中,有thread_id取得。
如果thread_id<=0;那么从intent的Date获得thread_id,
再不行,就说明之前没有过这个thread了,可能用户是手写的地址,就从address去产生一个ContactList,从ContactList去Conversation的Cache里匹配得到相应的Conversation
这时候,如果匹配还是没有得到Conversation时,Cache里就会偷偷生成一个Conversation返回回来,适用于你这个状况。
Cache用来保证联系人匹配的所有消息,被放入同一个对话(thread)中。
再还有如果联系人也是空的,那么直接产生一个新的Conversation; 这个Conversation是廉价的,因为他没有thread_id,不被放入cache,在使用ensurethreadid之前,他可以创建无数个,可以随意调用创建出来。
有了conversation之后,就可以initMessageList,查询显示出这个thread下面的所有消息
handleSendIntent() 函数
判断是否由一个intent调用起来的CMA,
特征是intent可以得到Action和mimeType; 比如ACTION_SEND和ACTION_SEND_MULTIPLE; 文件流比如EXTRA_STREAM,字符串EXTRA_TEXT;
遇到这些情况,直接添加附件,其他流程类似于messagelist继续。
handleForwardedMessage() 函数
在不是intent调用的CMA时,检查是不是由转发发起的调用
这些检查归根到底是检查intent的extra中带的关键字,比如 “forwarded_message” , intent.getAction() ,“recipients” , “thread_id”
(III)
CMA的入口只有两个:
onCreate()和 onNewIntent()
这俩个初始化函数的核心是: initialize(Bundle savedInstanceState)
onCreate比较简单,他的内容主要是:
初始化变量 ; 初始化UI ; initialize()
onNewIntent, 只发生在,singleTop的场景,也就是说,已经有一个CMA在Task的顶部(也就是用户的视线内,或者被隐藏到后台了),
之后在从launcher的短信或者从statusbar的短信入口进入时,就会调用到onNewIntent。
在onNewIntent调用时,需要保存原有的CMA的状态,并用新的Intent里的信息,形成新的CMA,从而替代他。
原有的Intent的信息在mConversation和mWorkingMessage里面,
比如mConversation.getThreadId() 得到threadId,如果threadId是0,则说明原来的CMA包含一个草稿,需要保存
比如mWorkingMessage里面,包含最新的收件人信息,需要用mWorkingMessage.syncWorkingRecipients()复制到conversation中,这时候把这份联系人复制到Conversation里,以备保存草稿用
关于新起来的这个Intent和原来的CMA是不是属于同一个conversation的判断;
判断的唯一依据是联系人列表
新来的intent的uri调用uri.getSchemeSpecificPart()函数返回的是一个由“;“分割的电话号码序列,可以拼装成ContactList,是新来的联系人列表。
通过对比,可以知道原来的和信来的两者之间的ContactList是否相同;
如果对比是不同的,那么新的intent将占据CMA,如果对比相同,则没有更换Conversation以及占据这个操作。
‘这个占据包括三步:
1,saveDraft() 函数 ,保存原有conversation的草稿 ,(mRecipientsContainer同步到workingmessage中去。)
2,initialize(null)函数 ,也即(I)里提到的流程,只是传入的初始化参数是null,也就是说在init时,没有在bundle里提供联系人
3,loadMessageContent()函数,查询Conversation下的消息状况,初始化联系人信息,画相关按钮界面
(IV)总结
onCreate()入口:
1 新建短信;bundle和intent都为空初始化
2 在conversation点击一条短信: intent非空,由intent初始化
3 转发:handleForwardedMessage时把intent中的uri中的数据取出来放入mWorkingMessage,有文本以及可能的彩信;同时把list的cursor置空。
4 文件或者文字通过短信发送
5 handleSendIntent处理,如果intent中有extra内容,可以附带Intent.EXTRA_STREAM或者Intent.EXTRA_TEXT;
前者就是一个文件流,可以解析出来多媒体文件,后者是一个文本,
还有一种是Intent.ACTION_SEND_MULTIPLE, 不怎么用,看名字大概知道是怎么回事,不过不懂细节。
发表评论
-
ActivityGroup 替代tabActivity
2013-12-26 16:43 2539转载自http://www.cnblogs.com/answe ... -
Android实战技巧:为从右向左语言定义复杂字串
2013-09-04 17:37 1140我们所使用的语言,无论是中文还是英语, ... -
Android 5种方式存储数据:
2013-05-08 17:17 1098Android 提供了5种方式存储数据: --使用Shared ... -
widget的设计与应用
2013-02-02 16:27 9301.AppWidgetProviderInfo对象 ... -
Android系统主题设计和实现
2012-12-11 14:09 1481转自:http://www.apkbus.com/ ... -
Android实现DES对字符串加密
2012-09-02 14:15 17155import java.io.Unsuppor ... -
android综合
2012-08-02 16:25 15891 ,手动设置横竖屏 TestA ... -
onSaveInstanceState
2012-08-01 17:40 718@Override //存储 public void onSa ... -
处理多个Activity
2012-07-20 09:40 707public class LifecycleManager ... -
bitmap 和drawable 互相转换
2012-07-19 13:37 648// bitmap to drawable; Drawable ... -
设置壁纸的三种方法
2012-07-19 11:46 25221111111111111111111111111111111 ... -
sqlite数据库处理时间问题 和 日期时间函数
2012-06-27 10:36 22840首先,sqlite数据库在时间 ... -
app缓存管理
2012-06-27 10:25 1052无论大型或小型应用, ... -
Uri、UriMatcher、ContentUris类使用介绍&&Android应用间数据共享之ContentProvider
2012-05-24 15:50 4424Android应用开发中我们会经常用Uri进行数据的处理,下面 ... -
getWidth()为0
2012-04-12 10:06 2008一般在刚开始开发android时,会犯一个错误,即在View的 ... -
自定义View 及使用
2012-04-05 14:08 769可能是一直都在做Web的富客户端开发的缘故吧,在接触Andro ... -
搜索手机联系人所有字段
2012-03-28 15:54 1441想取手机联系人的有效字段,但是苦于找不到API表示的字段变量, ... -
Andoid2.X各字段意义
2012-03-28 14:59 1249ContactsContract.Contacts.TIMES ... -
SMS发送流程
2012-03-20 18:07 1256发短信流程: 1 afterTextChanged{mWork ... -
Android telephony MMS 学习笔记
2012-03-14 13:32 2882转载 http://blog.csdn.net/tjy1985 ...
相关推荐
这个名为"Sms.rar"的压缩包包含了一个关于Android SMS(Short Message Service)功能的源码实现,特别提到了MMS(Multimedia Messaging Service)的支持,这允许发送和接收包含多媒体内容的消息。下面将详细解释这些...
**MMS/MM1解码器详解** MMS(Manufacturing Message Service)协议是基于ISO/OSI模型的工业通信协议,主要用于智能设备间的通信,如SCADA(Supervisory Control And Data Acquisition)系统、PLC(Programmable ...
在Android平台上,短信服务(SMS)是移动应用开发中的一个重要组成部分。这个压缩包"SMS.rar"和"android_android sms.zip"包含的可能是一系列与在Android系统上编程短信功能相关的资源和代码示例。让我们深入探讨...
标题中的“sms-mms.rar_MMS_at sms_mms sms_sms”暗示了这是一个关于MMS(Multimedia Messaging Service,多媒体信息服务)和SMS(Short Message Service,短消息服务)的C语言编程资源,其中可能包含了用于发送MMS...
在Android平台上,实现MMS(Multimedia Messaging Service)流媒体播放是一个相对复杂的过程,因为MMS协议主要用于多媒体消息传输,而并非设计为实时流媒体的标准。然而,通过一些技术手段,我们可以利用Android的...
android permission BROADCAST SMS"> <intent filter android:priority "2147483647"> <action android:name "android provider Telephony SMS RECEIVED" > < intent...
首先,GUI展示层负责与用户交互,这部分代码主要集中在`Mms/src/com/android/mms/ui`目录下。`ConversationListAdapter.java`是对话列表的适配器,它将数据绑定到`ConversationList`上展示。`...
在Android系统中,MMS(Multimedia Messaging Service,多媒体信息服务)是用于发送和接收包含文本、图片、音频、视频等多媒体内容的短信服务。MMS是SMS(Short Message Service,短消息服务)的一个扩展,允许用户...
《Symbian系统下的MMS & SMS应用开发详解》 Symbian操作系统,作为一个历史悠久的移动设备操作系统,曾经在智能手机领域占据着重要地位。对于开发者来说,理解和掌握Symbian平台上的MMS( Multimedia Messaging ...
- **JAVA文件**:`Src/com/android/mms/ui/ConversationList.java`是此界面的activity,它包含一个`ListView`,并通过`ConversionListAdapter.java`进行数据绑定。`ConversationListItem.java`则是`ListView`中每个...
"rtsp/mms/http测试安装包"是一个专门用于检测rtsp、mms和http流媒体URL是否可正常使用的工具。这些协议是流媒体服务常用的传输方式,各有特点和应用场景。 1. **RTSP(Real Time Streaming Protocol)**:实时流...
3. **MMS配置**:在Android设备上,MMS的配置信息通常包含APN(Access Point Name),这是与运营商网络交互的入口点,用于MMS的上传和下载。开发者可能需要在代码中动态设置或修改这些配置。 4. **接收MMS**:...
"MMS和SMS问题分析" MMS(Multimedia Messaging Service,多媒体短信服务)和SMS(Short Message Service,短消息服务)都是移动电话网络中的重要组件,负责处理移动电话用户之间的短消息服务。下面对MMS和SMS的...
Android MMS 彩信发送代码流程详解 Android MMS 彩信发送代码流程是 Android 操作系统中一个复杂的过程,涉及到多个应用层和系统服务的交互。下面将对该过程进行详细解释,从 Messaging 应用层到 framework 应用层...
MMS基于SMS(Short Message Service)短信服务,但扩展了其功能,使得用户可以发送和接收包含多种媒体格式的消息。MMS协议由一系列标准组成,包括WAP、HTTP、SMIL(Synchronized Multimedia Integration Language)...
【标题】"Android_SMS.rar" 是一个包含有关Android短信功能的源代码压缩包,主要针对的是Android平台上短信的发送和接收。"Android_SMS_android_apk" 暗示了这可能是一个已经打包好的APK应用,可以安装在Android设备...
在Android系统中,MMS功能是通过系统的MMS应用来实现的,它与SMS(Short Message Service,短信服务)一起构成了Android设备的基本通信功能。 在Android源码中,MMS服务涉及到多个组件和模块,包括PDU解析、WAP ...
2. `MmsApp.java`: 主要应用入口,提供MMS UI和相关功能。 3. `ContentProviders`如`MmsSmsProvider.java`: 数据库操作接口,用于读写MMS和SMS数据。 4. `BroadcastReceivers`如`NewMessageReceiver.java`: 监听并...
- **Content Provider**:提供对MMS和SMS数据的统一访问接口,允许其他应用通过URI查询和修改MMS信息。 - **BroadcastReceiver**:监听系统事件,如网络状态变化、新消息到达等,触发相应操作。 4. **库和框架的...