欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android Mms之:深入理解Compose

程序员文章站 2023-12-09 22:51:15
mms中的composemessageactivity(以下简称composer)是整个mms中最重要的一个组件,它负责编辑信息,发送信息,管理信息,接收信息,与外部应用接...

mms中的composemessageactivity(以下简称composer)是整个mms中最重要的一个组件,它负责编辑信息,发送信息,管理信息,接收信息,与外部应用接口。在mms内部与composer关联的类和组件特别多,几乎所有的类和组件都与composer有关联,关于信息的所有操作流程都起始于composer;在外部composer也是公开的接口,能够处理intent.action_send和intent.action_sendto以及文件类型为audio/*,image/*,video/*和text/*。
composer是一个标准的activity,它的启动流程也要经过oncreate(), onstart(),onresume(),销毁流程要经过onpause(),onstop()和ondestroy() 。除此之外,其他的操作都要经过用户来触发,或者由其他事件,比如新来信息,数据库变化等。
初始化流程
composer的初始化流程要做的事情有初始化ui,注册一些receiver和listener,初始化conversation和workingmessage,查询信息等。其中,初始始化conversation和workingmessage是最重要的,因为ui和一些操作要依赖于conversation是否存在,以及消息数量和是否有草稿。所以这里我们主要讨论初始化conversation和workingmessage。
初始化的主要流程都是在initialize()函数中进行的,这里也主要解析下initialize()函数。initialize()最先要做的就是初始化workingmessage,创建一个新的workingmessage对象mworkingmessage;然后就是根据intent和bundle来初始化conversation,这一过程相当重要,因为conversation对象含有这一会话的所有重要数据,包括是否有草稿,信息的数量,是新建的信息还是已有信息,这些信息都将影响后续的初始化工作。
initactivitystate()主要看二个参数一个是所传入的bundle另一个就是intent。它会优先查看bundle,如果bundle对象不为空的话,会从bundle之中取出一些状态,比如收信人recipients,比如退出状态exit_on_sent等。根据所拿出来的的收信人就可以用conversation的get()方法来获取conversation对象mconversation,之后便会让mworkingmessage从bundle中读取相关的数据。其实,这里从bundle中初始化是与onsaveinstancestate()相对应的,在onsaveinstancestate()中会保存recipients和让mworkingmessage写数据到bundle中,以保存activity的状态。总体来讲,onsaveinstancestate是保存activity的状态,而initactivitystate()中当bundle不为空时是恢复activity的状态。
如果bundle对象为空的话,那么就从intent中来初始化相关的数据,这也是大多数的情况所走的逻辑。首先是检查intent中是否有thread_id和address,也直接从intent的uri中搜寻收信人的相关信息,以便用conversation.get()来获取conversation对象mconversation。之后还会试图从intent中获取其他信息比如消息的主体sms_body,主题subject等。
调用完initactivitystate()以后,mworkingmessage和mconversation二个对象应该都被正确的初始化了。这时候就要处理特殊的intent:action_send和forward了。先是处理action_send,这是对外的接口,当外部程序想通过mms来发送文本(text/*),图片(image/*),音频(audio/*)和视频(video/*)时就会通过intent.action_send来发送。对于这个intent的处理很简单就是把相关文件的uri,通常放在intent.getextras(intent.extra_stream)中,把uri加载为附件,也可以通过intent.send_multiple来处理多个附件,但是逻辑是一样的。forward是intent当中有forward_message时,同时取出另外二个选项,一个是要转发的信息的uri,一个是主题subject和消息主体sms_body。因为对于send和forward都仅指定信息的内容而没有指定收信人,所以mconversation对象是没有实际内容的,它们都会与新建信息是一样的,只不过有信息的内容。
除了action_send和forward的信息有内容外,其他的信息都需要检查是否有草稿,以便能加载草稿。加载草稿是由mworkingmessage.loaddraft()来完成的,它会检查mconversation的状态,如果有草稿存在就从数据库中加载出来。
到此,初始化的关键操作都已完成,数据的加载都已完成,剩下的工作就是根据这些数据来初始化ui,比如是否显示收信编辑栏等。
销毁流程
composer的销毁要做的只有二件事,一个是保存当前编辑的信息内容,也就是保存草稿,如果有的话;另一个就是通过onsaveinstancestate来保存状态,不过这个通常用不到,只有当composer被系统杀掉并希望重启时才会调用到。
保存草稿的工作主要放在onstop()的时候,所以每当用户离开composer页面都会走进onstop()也就都会检查相关的条件以确定是否要保存草稿。保存草稿的条件有三个:信息有内容(mworkingmessage.isworthsaving(),有内容,有主题,有附件均可),并且信息有正确的收信人(在不在数据库中均可),还有就是composer在等待其他activity(这个通常出现在添加联系人或添加草稿过程中,因为要跳转到其他activity,所以composer也会走到onstop(),但是这个时候因为信息还在编辑中,所以就需要保存草稿)。如果以上条件不满足就丢弃信息内容(mworkingmessage.discard()),否则就保存草稿(mworkingmessage.savedraft())。
对外公开的接口
跟android中组件复用的公开接口一样,composer对外公开的接口也是通过处理intent来完成的,主要是二个intent一个是intent.action_send,另一个就是intent.action_sendto。接口的声明处是在androidmanifest文件中的intentfilter。对于处理,有二个地方,一个是在initactivitystate()中,会从intent中尝试取出address, sms_body 和subject;另外对于action_send需要明显的处理handlesendintent(),因为需要从intent中取出信息的内容通常都是多媒体文件,取出多媒体文件然后通过mworkingmessage.setattachment()添加为信息的附件。
还有一个接口就是对于分享联系人,分享联系人的方式是把联系人的信息作为短信的内容发送出去。这个过程实际上是由contacts中的sharecontactsviasms来先行处理,它会把联系人的信息从数据库中读取出来,然后拼成一个字串再用intent当成sms_body传给mms发送。
与其他组件的交互
composer在编辑信息过程中,特别是编辑mms的过程中需要不断的与其他组件进行交互,比如添加图片,添加音频,添加视频或拍摄图片,拍摄视频等。对于选择图片,选择视频来讲是通过与gallery应用进行交互,发送get_content的intent给gallery,gallery会列出图片和视频供用户选择,当用户选择后,gallery会把用户所选择的图片或视频的uri传给composer,之后composer就用传过来的uir进行添加附件的动作。对于音频是与music应用进行交互,逻辑类似。对于拍摄图片和拍摄视频和录制音频流程稍有不同。拍摄图片和拍摄视频在请求intent中要指定输出的路径通过intent.extra_output来指定输出uri。camera在拍摄的过程中会把数据写在所指定的uri中,之后composer会直接从这个uri中读取文件(这里与2.3不同,2.3是camera把文件的uri放在intent中)。tempfileprovider就专门用于管理拍摄图片和拍摄视频时临时存储数据的。传给camera的uri是”content://mms_temp_file/scrapspace”,这个uri由tempfileprovider来管理,由camera来使用,当camera要写数据时openfile()时,tempfileprovider就会创建一个临时文件,在外部存储卡上/sdcard/android/data/com.android.mms/mms_temp_file/scrapspace/.temp.jpg,camera所拍摄的图片和视频都存放在这个文件之中。tempfileprovider中还有方法以操作这个文件,比如tempfileprovider.renacescrapfile()就是把.temp.jpg文件重命名成为一个.3gp的视频。除了composer会用到这个tempfileprovider,在slideeditoractivity中编辑一张幻灯片的时候也会用到这个临时文件,因为编辑幻灯片的时候也是能够通过camera来添加图片的视频的。