大橙子网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
从软件的功能角度来讲,Mms分为对话列表,消息列表,短信编辑,彩信编辑,短信显示,彩信显示和配置。
十余年的宁阳网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。成都全网营销的优势是能够根据用户设备显示端的尺寸不同,自动调整宁阳建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。成都创新互联从事“宁阳网站设计”,“宁阳网站推广”以来,每个客户项目都认真落实执行。
从实现的角度来看,它分为GUI展示层,发送/接收,彩信解析,彩信附件,信息数据等,这些分类对应着源码中的各种包。
源码导航
Mms的源码的位置在于android/packages/apps/Mms
其中Mms/src/com/android/mms里面都是Mms相关的代码,而Mms/src/org/w3c/dom里面是一个类库,主要用于彩信格式的解析和显示。这里主要讲一下Mms/src/com/android/mms下面的一些包和类的主要用途。
ui---GUI展示层,用于展示对话列表,消息列表,消息编辑页,彩信附件编辑,彩信展示,播放幻灯片。负责直接与用户交互。
•ConversationListAdapter.java---对话列表的Adapter用于给显示层ConversationList绑定数据。
•ConversationListItemData.java---代表对话列表中的每一项的数据结构,里面含有要在对话列表中展示的信息。
•ConversationList.java------这是对话列表的显示窗口Activity,它是一个ListActivity,这几个类都是对话列表的相关类,用于显示,编辑和管理所有的对话。
•ComposeMessageActivity.java----这个是核心的窗口Activity,编辑信息,显示一条对话Thread中的所有往来信息。MessageListView会加在其上面,另外,AttachmentEditor也会加在其上面。这个Activity也负责响应外部应用程序,发送SENDTO或SEND等请求Intent,比如外部应用想要发送信息,等就由这个Activity来响应。
•MessageItem.java---代表一个信息的抽象数据,它包含了信息相关的所有内容,比如信息的主题,消息内容,来信地址,附件内容等等。它的所有数据都是公共的内部成员,都可以直接访问。
•MessageListAdapter.java---用于给消息列表显示层(由ComposeMessageActivity创建,绑定到MessageListView上)绑定数据。
•MessageListView.java---用于显示消息列表,继承自ListView,其生命周期由ComposeMessageActivity来控制,显示与否也由它来控制。
•MessageListItem.java---是一个布局,用于显示和控制消息列表中的每一个消息的显示。
•AttachmentTypeSelectorAdapter.java---用于添加附件件时的一个支持的附件列表,它就是一个菜单。
•AttachmentEditor.java---用于在编辑MMS彩信信息时,显示已添加的附件,它的生命周期由ComposeMessageActivity来控制,显示与否也是由ComposeMessageActivity来控制,当有彩信附件时,它就会显示,否则就被Hide。它是一个布局管理器,管理着下面四个布局,根据附件的类型动态的显示下面四个View中的某一个。
•AudioAttachmentView.java---在编辑信息器中用于显示音频附件,它是继承自线性布局。并不在代码中直接使用,而是在布局文件中来当成布局管理器使用。
•ImageAttachmentView.java---在编辑信息器中用于显示图片附件,它是继承自线性布局。并不在代码中直接使用,而是在布局文件中来当成布局管理器使用。
•SlideshowAttachmentView.java---在编辑信息器中用于显示幻灯片附件,它是继承自线性布局。并不在代码中直接使用,而是在布局文件中来当成布局管理器使用。
•VideoAttachmentView.java---在编辑信息器中用于显示视频附件,它是继承自线性布局。并不在代码中直接使用,而是在布局文件中来当成布局管理器使用。
•SlideshowActivity.java—用来全屏播放幻灯片,也即幻灯片的展示,因为彩信的创建和播放都是以幻灯片的方式进行的,也即一张一张的,每张上面可以文字,图片,视频和音频,每一张有浏览时长。
•SlideshowEditActivity.java---以列表方式管理幻灯片,也即是把所有的幻灯片用列表显示出来,用户可添加一页幻灯片,也可以点击进入编辑某页幻灯片,用于创建和编辑幻灯片。
•SlideshowEditor.java---用于编辑某页幻灯片,比如添加元素,删除元素和替换元素,这里的元素可以是图片,视频,音频和文字。也可以用于编辑整页幻灯片,比如删除某页幻灯片,调整这页幻灯片在所有幻灯片中的位置等。它是一个具体操作幻灯片的封装,SlideEditorActivity创建它并使用它来完成纪灯片的编辑。
•SlideshowPresenter.java---用于展示所有的幻灯片,也就是播放所有的幻灯片。由SlideshowActivity来创建和使用。
•SlideViewInterface.java---定义了一些用于显示一页幻灯片中的内容的接口,如设置图像,设置视频,设置音频,播放视频,播放音频,暂停,随机定位等等。附件显示的View:AudioAttachmentView,ImageAttachmentView,SlideshowAttachmentView和VideoAttachmentView均实现了此接口,这样AttachmentEditor就可以用统一的接口来控制内容的播放,而不用关心具体的内容是什么。
•SlideEditorActivity.java---用于编辑某页幻灯片,比如添加音频,添加视频,添加图像,添加文字等。它只是提供用户界面,让用户来操作各种按扭以达到添加元素,替换元素或是删除元素。而对具体的幻灯片的操作是通过SlideshowEditor来完成的,它主要负责与用户交互。
•SlideListItemView.java--- SlideshowEditActivity中列表的每一项的布局管理,继承自LinearLayout。
•MmsThumbnailPresenter.java---用于在消息列表中,显示彩信的缩略图,因为彩信的内容不固定,可能是图片,可能是音频,可能是视频也可能是幻灯片,所以用这个类来处理并显示彩信的缩略图。
•MessagingPreferenceActivity.java---Mms的配置信息编辑器,用来编辑和更改配置信息,继承息PreferenceActivity。它负责与用户交互,显示和更改配置。在Mms启动时,MmsConfig会从SharedPreference中读出配置信息,在运行时其他的类的配置信息都是从MmsConfig中获取的,MmsConfig提供了很多Get方法以获取配置信息。
•Presenter.java---用来展示附件的一个抽象类。
•PresenterFactory.java---工厂方法。
•RecipientsAdapter.java
•RecipientsEditor.java---用于显示信息编辑页面上面的收信人的编辑框,它可以有自动补全的功能,补全的数据由RecipientsAdapter来提供。
•ViewInterface.java---代表一个View的基类,用于Slideshow显示内容或是取缩略图。可以取View的长宽高等。
•BasicSlideEditorView.java---编辑某一页幻灯片时所用的布局,也就是在SlideEditorActivity.java中使用。
•EditSlideDurationActivity.java---顾名思义,用于编辑某一页幻灯片的浏览时长。
•ManageSimMessages.java---这个是在设置中使用的,用来管理SIM里的消息。在设置中有一项是管理SIM卡上面的消息。在Mms的设置Settings中有一个选项可以设置是把信息存储在SIM卡,还是存储在手机里。在收信时SmsReceiverService会查看这个设置然后把收到的信息写到相应的地址。ManageSimMessages也是以列表方式显示SIM里面的信息,提供了二个菜单:把信息存入手机和删除。
•NumberPickerButton.java---用于显示选择数字的按扭,在配置里面用。
•NumberPickerDialog.java---用于显示选择数字的对话框,在配置里面用。
•NumberPicker.java---用于在配置的时候选择数字。这几个NumerPicker主要是用于Settings中的。
•DeliveryReportActivity.java---信息发送情况报告。以列表的方式来显示
•DeliveryReportAdapter.java---相应的Adapter
•DeliveryReportItem.java---相应的数据,每一项的数据
•DeliveryReportListItem.java---相应每一项的布局。
data---用于操作当前正在编辑的信息的相关数据,比如联系人列表,比如当前对话,比如当前消息。负责管理当前正在编辑的信息和当前所处的对话以及当前信息用到的联系人。这些类都是在编辑信息的时候使用,由于这些多半都是用来管理数据的,而又无法直接做为对象传递给编辑器。所以它们的很多方法都是静态的,也就是这些类都近似单键。
•WorkingMessage.java---用来管理当前正在编辑的消息,它从创建,草稿到发送完成后一直存在,只要打开了编辑信息的页面就会创建一个WorkingMessage,直到退出编辑页面。
•Conversation.java---用来管理对话Threads,通常用来管理当前的对话,也就是进入的对话和正在进行操作的对话,它也用来管理对话列表,比如查询对话列表。
•Contact.java---用来代表一个联系人的信息,和管理联系人,加载联系人信息,其中还有相应的Cache。因为一个联系人的数据是比较多的包含名字,名,姓,各种电话号码,各种地址等等。因为Mms中直接使用Contact来作为联系人,所有信息都是直接从其中获取。另外,由于信息交互中也会涉及到联系人,因为收发信时可以直接使用一串电话号码,这时就需要有如添加联系人的功能。Contact中有很多异步的操作,比如加载联系人信息的时候或者更新Cache的时候都需要异步操作以不阻塞调用者。
•ContactList.java---是一个Contact的List列表它继承自ArrayListContact。用来管理一个Contact列表,或管理多个Contact。因为每个信息可以发送给多个联系人,这时就需要用到ContactList来管理这些收信人。也提供了一些方便存储和传递Contact的方法,比如把多个Contact转成String,或者转成String数组等。
•RecipientIdCache.java---用于保存所用到的Contact的Id和地址(电话)。每次WorkingMessage会更新这个Cache,然后ContactList会优先从这个Cache中查询联络人。
dom---用于解析彩信内容smil的工具包
drm---用于处理DRM的媒体文件的工具包
layout---为了满足特殊需要而改写的布局元素
model---这里面定义了彩信支持的附件数据结构和附件的组织方式。彩信可包含的内容有图片,视频,音频和文字。这些内容可以单独存在,也可以组合在一起。如果组合在一起就变成了幻灯片。用户可以用幻灯片的方式来创建含有多个媒体的附件,图文并茂的展示。每张幻灯片上面可以加视频,音频,图片和文字,但通常一张幻灯片上面只允许加一个图片或视频,文字是都可以添加的,音频在没有视频的情况下只可以添加的。播放的时候可以设置每张幻灯片的播放时长,以及文字的滚动速度等等。
•CarrierContentRestriction.java---是具体的彩信附件检查站,对于不支持的附件,或者附件大小超出限制,或者图像分辨率不对,或者图像超出尺寸,会抛出异常:UnsupportedContentTypeException,ResolutionException,ExceedMessageSizeException,ContentRestrictionException。
•ContentRestriction.java是用于检查附件的接口,外部直接使用这相接口,而具体实现是CarrierContentRestriction
•ContentRestrictionFactory.java是创建附件检查的工厂方法。外部通过这个工厂来创建一个ContentRestriction对象,然后使用其中定义的检查方法来进行附件内部检查。
•SmilHelper.java用于解析和处理附件中的Smil的工具类。
•IModelChangedObserver.java接口,用于监听附件内容有变化。
•Model.java---彩信附件的数据组织方式和管理方式是每一个附件都是一个Model的子类,它不但用于管理附件的具体数据,比如Uri,大小,文件名,位置等,也可以用于在GUI显示附件和查看附件。
•LayoutModel.java---继承自Model用于管理可视的附件的布局的类。它用来管理RegionModel等的基本元素。它就好比ViewGroup或LinearLayout,RelativeLayout等一些布局管理器,用来组织并管理布局基本元素也就是RegionModel的子类ImageModel,TextModel和VideoModel。
•RegionModel.java---继承自Model用于管理可视附件和布局,比如图像,视频和文字。特别是在显示可视附件的时候,用于控制可视附件在屏幕中的位置。一个RegionModel代表着一张幻灯片上的一块区域,它是幻灯片上的布局基本元素。好比UI元素中的View,但多在使用时都是使用它的子类,也就是ImageModel,TextModel和VideoModel。
•RegionMediaModel.java---继承自MediaModel,是用于多媒体附件中的可视部分的布局控制,主要用在附件的显示和播放幻灯片时的控制。它的子类是ImageModel,TextModel和VideoModel。
•MediaModel.java---继承自Model,代表媒体的数据结构,管理具体的附件数据,同时也用于管理附件的显示控制,比如图像的显示,音频和视频的播放控制等。
•MediaModelFactory.java---用于从一个Pdu附件中解析出来MediaModel,也就是把Pdu转化为Mms内部的附件数据。
•ImageModel.java—继承自RegionMediaModel用于管理图像附件和控制图像附件的显示。
•VideoModel.java---继承自RegionMediaModel用于管理视频附件和控制视频附件的播放。
•AudioModel.java----继承自MediaModel用于管理音频附件和控制音频附件的播放
•SlideModel.java----继承自Model用于管理一组附件,这些附件同一次显示给用户。就好像幻灯片的一片一样,每一个SlideModel里面有一个可以存储Model的列表,可以包含文字,音频,图像或视频,其上面的附件同时显示出来。
•SlideshowModel.java---继承自Model,用于管理一个彩信中的所有附件。其内含有一个存储SlideModel的列表,用于保存和控制一条彩信中的所有附件。另外它也负责显示这些附件,把一个个SlideModel组织起来,播放。它也负责着把这些Mms形式的附件(各种Model)转化为Android的附件Pdu,和从Pdu提出各自Model,因为Slideshow是应用程序层的彩信处理方式,而能发送和接收的彩信数据是Pdu。
•TextModel.java---继承自RegionMediaModel用于管理文字附件和控制文字附件的显示,比如按时间来滚动
util---这里面是整个Mms共享的工具类,其中全部都是单键或是直接使用类,不可以创建对象和以对象方式来使用
•AddressUtils.java---关于地址的工具类,目前只有一个getFrom()方法,用于获取发信人地址。
•DraftCache.java---用于标识哪些对话Thread有Draft,哪些没有,也就是用于管理和查询对话的草稿状态,有草稿还是没有。它里面维护了一个HashSet,里面包含了所有含有草稿的Thread Id。它里面也有一个HashSet用于存储OnDraftChangedListener,即当Thread的Draft状态有变化时,DraftCache会调用相应的Listener以告知相应模块,这个对话的草稿状态有所变化。可以通过DraftCache.setDraftState(threadId, state)来设置某个对话的草稿状态; 可以通过DraftCache.hasDraft(threadId)来查询某个对话是否含有草稿。
•Recycler.java---是一个抽象的工具类,里面定义了SmsRecycler和MmsRecycler,用于删除陈旧的消息,或者删除超过信息数量限制的信息。使用方法都是Recycler.getSmsRecycler.deleteOldMessages(context) 或者Recycler.getMmsRecycler.deleteOldMessages(context)
•SmileyParser.java---把标点式的表情符号转化为图形的表情,比如把用图标笑脸来代替。
•DownloadManager.java---不要被名字骗到,它并不是真正意义上的下载管理器,因为它并不负责任何与下载文件过程或下载文件的管理。它是用于管理与下载相关的配置信息,比如是否是自动下载,以及下载过程的各种通知,比如Notification Bar和Toast提示等。
•RateController.java
•SendingProgressTokenManager.java
transaction---对于Mms来讲是最底层的一个包,用户不可见,它负责发信息的最后处理和收信息的最初处理。主要是负责发送信息和接收信息。它并不是真正的发送和接收信息。是由系统Frameworks里面来负责接收和发送信息。这个包只是对于Mms应用层来讲是发送和接收。
•AbstractRetryScheme.java
•DefaultRetryScheme.java—这二个类是实现一种Retry机制,因为信息的发送与接收会受到环境的限制,比如现在手机没信号,或是网络连接不成功,那么就会把信息放到Pending队列里面,等一段时间再重新尝试发送与接收。这里的二个类就是为了实现此Retry机制。
•HttpUtils.java—彩信发送与接收的最底层实现者,它负责用HTTP协议接收和发送彩信到MMSC彩信服务中心。
•MessageSender.java—像其名字所预示的那样,它是为了发送信息而封装的一个接口,它里面只有一个方法sendMessage(),UI层只需要调用实现了这个接口的类即可发送信息。
•MessagingNotification.java—专门负责在Status Bar上面做Notification,比如新接收到了信息,或是信息发送失败,或是接收失败等。它被UI层,和底逻辑层共用着。
•MmsMessageSender.java—继承自MessageSender,专门用于发送彩信。它并不是做发送的事情,而是做一些错误检查和前期准备工作,然后启动TransactionService来做发送相关的事情。
•NotificationTransaction.java—继承自Transaction,负责接收彩信和更新通知(Notification)。当有一个新彩信时,Frameworks会先发出一个短信,称作彩信通知(NotificationIndication),其内含有彩信相关的信息(MMSC, 彩信的ContentLocation(URL)等),之后是由应用程序自己去MMSC用ContentLocation取彩信。这个NotificationTransaction就是专门用于处理彩信通知的,它会从MMSC上取出彩信数据(Pdu),把它写入数据库中,然后更新Notification。需要注意的是,只有彩信的设置是自动获取(“auto retrieve”)时,它才会去下载彩信,否则,它只处理彩信通知(Notification Indication),而不去下载彩信。
•Observable.java—里面定义了观察对象,Transaction是它的一个子类,其他的实体Transaction都是观察对象,里面有一个列表保存着观察者的引用,当一个Transaction完成时,或是有异常时就会调用notifyObservers()方法来把状态通知给观察者。
•Observer.java—观察者,TransactionService实现了这个接口。它是所有Transaction的观察者,以监听他们的状态和处理结果,因为所有的Transaction都 是异步的,所以才用观察模式来通知Transaction的处理结果。
•PrivilegedSmsReceiver.java—继承自SmsReceiver短信收信的事件监听者,负责监听新短信事件android.provider.Telephony.Intents.SMS_RECEIVED_ACTION(“android.provider.Telephony.SMS_RECEIVED”);当接收到这个Intent时表明有一个新短信。它会唤起SmsReceiverServier来处理短信。
•ProgressCallbackEntity.java
•PushReceiver.java—一个BroadcastReceiver专门用于接收彩信事件android.provider.Telephony.WAP_PUSH_RECEIVED_ACTION(“android.provider.Telephony.WAP_PUSH_RECEIVED”),它会先做一些预处理,然后启动TransactionService,TransactionService又会创建NotificationTransaction来处理这个彩信通知。
•ReadRecTransaction.java
•RetrieveTransaction.java—继承自Transaction,用于主动获取彩信数据。当彩信设置为非自动获取时,需要用户触发获取,TransactionService会创建一个RetrieveTransaction来获取彩信数据(Pdu),存入数据库,更新Notification等。
•RetryScheduler.java
•SendTransaction.java—继承自Transaction,用于发送彩信数据。
•SimFullReceiver.java
•SmsMessageSender.java—发送短信的封装,继承自MessageSender。它会启动SmsReceiverService来发送。
•SmsReceiver.java—是一个BroadcastReceiver,不要被其名字唬到,它并不负责接收新短信通知,相反,它用于发送信息,接收发送信息请求,并唤起SmsReceiverService来处理发送。这里可能是Android命名规则的原因,Android里的四大组件都喜欢把其组件的名字加上,比如ComposeMessageActivity,是一个Activity,TransactionService是一个Service,而这里SmsReceiver是一个BroadcastReceiver,它与接收短信(receiving Sms)没有关系。当然了,这完全是一个糟糕的命名。
•SmsReceiverService.java—它是一个Service,专门用于处理短信的发送与接收。它是由SmsReceiver和PrivilegedSmsReceiver监听事件,然后启动它的,自己并不会监听Intent事件。
•SmsRejectedReceiver.java
•SmsSingleRecipientSender.java—继承自SmsMessageSender,它针对一个收信人,调用Frameworks层接口发送信息,对于Mms应用来说,这是发送短信的最后一站,对就是说对于应用来说,它会把短信发送出去。
•TransactionBundle.java—Transaction所用的一个数据结构,用于给Transaction传送数据。
•Transaction.java—各种Transaction的基类,它里面定义了二个方法getPdu(),sendPdu()这二个方法是从MMSC取彩信数据,和向MMSC发送数据。它是对HttpUtils的一层包装。
•TransactionService.java—是一个Service,接收各种Transaction请求,然后处理Transaction。每个Transaction都 会开启新的线程异步的处理,所以当处理完成时又会通过Observer来通知TransactionService。
•TransactionSettings.java—彩信相关配置信息的数据结构,比如MMSC,Proxy,Port等。请求方可能会提供这些数据,如果提供就使用;否则就会从Telephony数据库加载默认的数据,这些数据与运营商和APN的设置有关。
•TransactionState.java—标识每一个Transaction处理情况的数据结构,很简单,只是标明处理成功还是失败,用于Transaction回调Observer(TransactionService)时用。
还有com/android/mms根目录下面的一些文件,其中绝大多数是定义的基类异常和一些公共的类。
•MmsApp.java---Mms Application会在应用进程启动的时候做一些必要的初始化工作,比如配置,下载,联系人,对话,Smiley解析器和通知等。
•MmsConfig.java---管理Mms的一些常用配置,比如彩信大小上限,彩信图片尺寸上限,收信人的个数上限等等。这些配置信息是保存在在res/xml/mms_config.xml里面。MmsApp在初始化时会调用MmsConfig.init(),在这里面会调用loadMmsSettings来解析mms_config.xml从而得到所需要的配置信息。其他的模块只通过MmsConfig来访问这些配置信息。
•LogTag.java---有关日志跟踪信息的控制。它可以方便的控制日志输出级别。但是实际上整个Mms代码中使用这个LogTag的地方并不多。
第一步:编程入门课
时间预计:4个星期
推荐看公开课,Udacity也行,网易公开课也行,自己找一个面对对象语言(一般是JAVA, C++, Python)的课。我是在网易公开课看的斯坦福的CS106A,学的JAVA。
如果你纯粹学iOS开发,不推荐看哈佛CS50,CS50是给CS系的学生介绍整个计算机世界的框架,讲的内容比较多,进度比较快,对iOS开发其实有点累赘了。(臣妾有点跟不上啊!!)
计划安排是一天一课,看课程要求的书(至少看完一本)及大部分作业。这一阶段重点不是语法,而是以下3个目标。
目标:
1. 让自己对编程这件事感到适应。
写hello world。
怎么写function, 怎么调用function。
全局变量,局部变量这类基本知识点。
都是基本的东西。看看书,写多两个程序就欧啦。
2. 掌握编程语言的基本要素。
编程语言4个要素:
a. 基本的数据类型:整数,实数,character, string, boolean
b. 基本的运算符号:+-×/++--那啥的
c. 怎样输入输出
d. 怎样控制程序:sequence,selection,loop
3. 了解编程范式
面对过程编程。
面向对象编程。
第二步:上手iOS!
时间预计:2星期
强烈推荐CS193P,老头子讲的超级好!我的很多东西(对象思维啥的)是在这里跟着做练习的时候才真正明白的(好啦,也可能是上一堂课练习做得少的原因)。如果等到9月应该itunes U上会开始教iOS 7了。网易公开课的是2010年iOS 5版的,前10堂课,也行。(iTunes U上有完整的课)
CS193P说有prerequisite,一开始被吓到,事实证明还是可以学下去的。头两节课一头雾水,没关系,把itunes U上的课件下载下来,把所有代码打出来,然后一个个元素对应之前学的语言匹配,再不懂先放着,继续学后边的,过几天打多点代码就懂了。
感觉学5、6堂课,一个星期左右就可以开始进入下一阶段自己做东西了。之后用啥学啥,每堂课都有主题的。速度慢点的同学们,这阶段跟我一样准备两个星期吧!
第三步:开发app!
时间预计:2星期(本人...1个半月,实在不好意思说出口)
这个时间就可长可短啦,还包括美工,交互啥的。坚持要用啥学啥的原则,其实就是知道iOS SDK都有什么组件,每个组件有什么function而已。stackoverflow, Github, apple sample code多上,搜索引擎多用。如果有个师傅,这个阶段真的是进步神速。
好的!不出意外,你的第一个app就这么新鲜出炉了!从今天开始,成为一个冷艳逼格高尚的iOS开发者吧!
IOS故事类软件开发成本及人员:
一、IOS开发者会员年费:600元(要发布软件必须拥有开发者会员)。
二、研发人员,费用至少需要2~5万。
1、故事编剧、导演各1名。
2、插画师1名。
3、程序脚本编写人员(初级OC程序员)2~3名。
4、程序调整及BUG修复人员1~2名。
三、应用推广、营销费用至少需要1~3万,如果要求效果更好的至少需要5万。
四、后期维护费用:依据软件运营时间,时间越长单次维护费用越低,但综合维护费用越高。
纵观iOS发展历程, 不管是哪种技术,都有其历史的必然性,最终总会被一种新技术所取代。 apple 一直在引领科技的潮流,立足于浪潮之巅。
nib apps 代表了 iOS的过去, 而 storyboard apps 代表了iOS的现在和未来。 作为iOS开发者,我们既要脚踏实地,不忘过去,同时也得仰望星空,不断地自我创新。
1. nib apps 的回顾
nib apps 中,有一个必不可少的文件: MainWindow.xib 。 app运行时,呈现在你面前的第一个画面,就是UIWindow 对象。 而UIWindows 就是包含在 MainWindow.xib 中。
具体来讲, MainWindow.xib ,UIWindow, App Delegate,root view controller ,这四者是密切关联的。 我们要理解这四者之间的关系,方能更好地明白 storyboard apps 的运行机制。
2. storyboard apps 运行逻辑图
在storybord apps 中, MainWindow.xib 是不存在的。 取而代之的是 main.storyboard 文件。既然如此,那么storybord又是如何加载的呢?
在创建storyboard apps 时,会自动生成几个默认的文件, AppDelegate.h 便是其中之一。 示意如下:
import UIKit/UIKit.h
@interface AppDelegate : UIResponder UIApplicationDelegate
@property (strong, nonatomic) UIWindow *window;
@end
这些默认生成的文件, 我们要特别关注下, 弄清来龙去脉。
AppDelegate 继承于 UIResponder,并且拥有一个 UIWindow property。 声明的方式很简洁。
再打开默认生成的 AppDelegate.m 文件,你会感到很诧异, AppDelegate.m 所展示的代码几乎为空。 所有的method 都是空的。 即使 application:didFinishLaunc hingWithOptions: , 仅仅是返回 YES, 也没有其他代码可言。
这就是说,不管是 AppDelegate.h 还是AppDelegate.m , 都没看到什么玄机。 貌似庞然大物的storyboard,究竟是怎么玩的?
常言说的好,一个好汉三个帮。 仅仅查看AppDelegate.h/m ,还是远远不够的, storybord 还有三个好汉。
storyboard 帮手: info.plist 文件。 如下:
nib apps VS. storyboard apps - 悠悠电台 - 悠悠电台iOS客户端:几千个国内外电台
当storyboard apps 启动时, 它怎么知道从哪里加载main.storyboard 文件呢? 秘密就在info.plist上。 你会看到, UIMainStoryboardFile 或 “Main storyboard file base name” 的键值设为了 Main。当app 启动时,UIApplicaiton 会自动加载main.storyboard 文件。 同时,会自动加载 main.storyboard 上的第一个视图控制器 (view controller),并且,将该 view controller 所对应的 View 加载到UIWindow 对象中。
也许你已经注意到了, app 启动时,做了这么的工作,但我们还没有编写一行代码。 storyboard技术的引进,其最大的意义在于, 大大减少与 UI相关的 代码量。
storyboard 帮手:Deployment Info 的设置。 如下:
nib apps VS. storyboard apps - 悠悠电台 - 悠悠电台iOS客户端:几千个国内外电台
点击 Project settings, 可以看到Deployment Info。 你会注意到, Main Interface 也设为了 Main。 其实,这里的 Main 所指的就是 main.storyboard。
为了彻底理解 storyboard 的加载过程, 我们再来打探另一个重要的帮手。
storyboard 帮手:main.m 文件, 代码如下:
#import UIKit/UIKit.h
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
在main.m 中, 虽然语句不多,但这个语句直接决定了app 的生命周期。 这行代码的作用是,将app delegate class 传给 UIApplicationMain。 因为整个App 启动和运行的入口,就在UIApplicationMain中。
近期项目中有个需求就是要实现类似微信或者支付宝的收款时的语音播报功能,于是笔者就开始了漫长的踩坑之路。
刚开始讨论实现方案时,安卓的小伙伴说可以使用WebSocket + 讯飞语音在线合成实现。于是最初的几天笔者自己也一直在这条路上走了很久,基本功能都已经实现了,项目在前台的时候,基本没问题。但是项目一进入后台大概半分钟的时间,就无法播报了。原因是iOS项目如果不做任何处理的话,在进入后台大概30s之后,程序就会进入类似休眠的状态,然后就不会再进行任何操作了
跟安卓的同事讨论之后,发现安卓有方法可以让程序一直在后台处于活跃状态,于是笔者也开始找寻保持项目后台运行的方法,大概有两种
在这里我们并没有发现,程序在后台收到推送时,作相应处理的方法,哪到底能不能收到推送后就进行处理呢?
iOS 10 之后 iOS推出了Notification Service Extension,我们可以在收到推送之后,通过这个Extension 我们可以有三十秒的时间来对这个推送进行处理
完成之后长这样
然后我们配置一下NotificationService
然后我们看下NotificationService.swift文件
在完成上述操作之后,再次收到推送的话,就会走NotificationService的逻辑了,可以打断点或者Log测试一下
需要注意的是 在推送的内容中 必须配置mutable-content字段,结构大致如下
做完上边的操作之后,我们可以知道什么时候去播报语音了,但是语音又要怎么去播报呢?
笔者这边也是试过几个方案,下边一一说来
笔者刚开始使用讯飞发现不行,然后又测试了系统自带的AVSpeech,发现也不好用,查资料才知道,苹果在近期的版本中,停用的在NotificationService中播放语音的功能,之前的某个版本应该可以这么操作。好吧,此方案Pass
既然不让我播,那我存起来总可以了吧,测试发现讯飞在线生成是可以的,也可以存到本地,但。。。是,UNMutableNotificationContent的sound好像只支持提前添加到项目中的文件,并不支持立即生成之后存到本地,然后再设置的功能。。。
笔者在项目中预先生成的文件如下(语音包通过百度语音开放平台在线生成 百度语音在下生成(拉到中间就有了) )
比如说我要播放“支付宝到账100元”,我就会发放多个通知,依次播放wx-pre,1,bai,yuan这几个语音,连贯起来就能达到要求
笔者能力有限,暂时想到的方法就是这个,有好的方法可以多多分享,沟通
任何吸引人的游戏都少不了声音。iOS开发者在游戏中需要使用声音时有多种选择,取决于对游戏中音频的控制需求,可以选择简单的内置服务,也可以选择更高级的API(比如OpenAL)。
通过音频API,可以实现流式音频,播放简短音效,甚至模拟3d空间的音频。有些游戏可以通过音轨让玩家沉浸在特定的心境中玩游戏,设置鼓励用户使用耳机来获得更完美的体验。
本系列文章中,会陆续整理近几年来在工作中涉及到的音频的相关知识,以算做对自己知识体系的一次梳理吧,大体包括Core Audio、OpenAL 以及Cocos2d引擎中的音效部分等三个方面。
• Core Audio 是什么?
• Core Audio 中提供的音频服务
• Core Audio 中的有关音频框架
• 有关 Core Audio 的变化及更新
Core Audio 是什么?
Core Audio 是iOS和 MAC 的关于数字音频处理的基础,它提供应用程序用来处理音频的一组软件框架,所有关于IOS音频开发的接口都是由Core Audio来提供或者经过它提供的接口来进行封装的,按照官方的说法是集播放、音频处理、录制为一体的专业技术,通过它我们的程序可以同时录制,播放一个或者多个音频流,自动适应耳机,蓝牙耳机等硬件,响应各种电话中断,静音,震动等,甚至提供3D效果的音乐播放。
相关链接:
Core Audio Overview
Audio Video Starting Point
Core Audio Glossary
Core Audio中提供的音频服务
Core Audio 本身是一个很庞大的话题,涉及到多个领域中的不同服务,为了更方便的使用Core Audio,通常可以将其分割为更小的模块。图一展示了根据应用程序服务层分解的示意图。构建在应用程序栈最下面的是底层硬件。接下来往上是驱动程序层。构建在驱动层之上的每一层都是苹果提供给开发人员的应用层服务,包括各类音频API和框架。
主要的几类服务:
Audio Unit
Audio Unit 是Core Audio 在应用层中最底层的服务。在使用其他音频API时,最终在底层都会调用到Audio Unit。在所有的API中,Audio Unit 是延迟最短且最灵活的,但代价就是它的使用相当的复杂,幸运的是在实际使用中,我们很少直接使用Audio Unit。
相关链接:
Audio Unit Framework Reference
相关项目工程:
Core Audio Utility Classes
Audio File Service
通过Audio File Service 提供的API可以打开并读取或者写入磁盘上存储的文件。
Audio File Stream Service
它是对Audio File Service 的扩展补充。Audio File Service 对存储到磁盘上的音频文件进行操作,而Audio File Stream Service
并不一定关联到某个文件上,它更适合基于网络的音频应用程序。
Audio Conversion Service
通过它可以将数据转换为PCM格式或者从PCM格式转换成数据。
Extended Audio File Service
可以将它理解为Audio File Service 和 Audio File Service 的组合。通过这种API 可以直接加在并转换音频文件。
Audio Session Service
和Core Audio中的其他API不同,它的主要用于 iOS 系统中协调应用程序之间的音频播放的 API 的。例如,当有电话打进来时,音频的播放就会被暂停;在用户启动电影时,音乐的播放就会停止。我们需要使用这些 API 来确保一个应用程序能够正确响应并处理这类事件。
System Sound Service
它是一种允许播放短音效和警告的基本服务,还具有提供振动功能的独特能力,Core Audio中的其他任何服务都不能访问振动系统。
Audio Queue Service
它可以对播放音频进行精细的控制,比如暂停、继续、循环播放和音频同步等,因此特别适合于播放和录制持续时间很长的音频。在游戏中进行语音叙述等情景时,需要音乐或者长时间的播放文件,便会需要它。
AVFoundation
它是Core Audio中唯一基于Objective-C的框架。这个框架提供了AVAudioPlayer类用于播放,AVAudioReconder类用于录音,以及AVAudioSession类用于设置音频回话。和其他高层API一样,我们需要在易用性和功能之间做出权衡。如果在此框架中找不到我们需要的特性或者功能,那么就必须深入底层服务并直接使用底层的API。
相关链接:
AV Foundation Framework Reference
AV Foundation Programming Guide
Audio Session Programming Guide
相关的项目工程:
AVCaptureAudioDataOutput To AudioUnit iOS
OpenAL
和其他专用API不同,OpenAL是一个狂平台的用于播放和捕捉音频的工业标准。OpenAL更适合播放空间音频(spatialized sound)或者定位音频(positional sound)。可以将空间音频理解成3D空间中的声音,通过OpanAL可以对音效添加一些效果,比如位置属性,这样会使远程的声音比近处的声音听起来要弱一些。
相关链接:
OpenAL FAQ for iPhone OS
相关的项目工程:
oalTouch
Core Audio中的有关音频框架
Core Audio 中的服务和框架并没有一对一的对应关系,应用层的服务实际上分为5个不同的框架:Core Audio、Audio Toolbox、Audio Unit、AVFoundtaion、OpenAL。图二中很好的展示了这些框架和服务之间的映射关系。
Audio Unit、AVFoundation和OpenAL的框架非常明了,和他们同名的服务直接对应,其中AVFoundtion有三个Objective-C类组成:AVAudioPlayer、AVAudioRecorder和AVAudioSession。
Audio Toolbox 框架提供了前面列出的其他剩下的应用层服务,包括非常重要的Audio Session Service。
相关链接:
Audio Toolbox Framework Reference
其他相关框架:
Media Player Framework
它是一个用于音频和视频播放的高层级接口,它包含了一个可以在应用中直接使用的默认的用户界面,可以使用它来播放用户在 iPod 库中的项目,或者播放本地文件以及网络流。另外,这个框架也包括了查找用户媒体库中内容的 API,同时还可以配置像是在锁屏界面或者控制中心里的音频控件。
相关链接:
Media Player Framework Reference
Core MIDI Framework
提供与MIDI设备通讯的标准方式,包括硬件键盘和合成器。可以使用这个框架来发送和接收MIDI消息以及与通过dock连接器或网络连接到iOS设备的MIDI外设交互。
相关链接:
Core MIDI Framework Reference
OS 4.0以后的功能变化如下:
iOS 7.1
Support for External Media Players (CarPlay相关的)
iOS 7.0
新增 Inter-App Audio和 AudioCopy
强化 Media Player / AV Foundation Framework
弃用 Audio Toolbox framework内的Audio Session API
iOS 6.0
新增 Audio UnitのComponent
强化 Media Player / Core Media / AV Foundation Framework
iOS 5.0
新增 Audio UnitのComponent
强化 Media Player / AV Foundation / AudioToolbox Frameworks
iOS 4.3
强化 AV Foundation
强化 Media Player / Audio Unit / Audio Toolbox Frameworks
iOS 4.2
新增 Core MIDI framework
强化 Media Player Framework
新增 AirPlay
iOS 4.1
强化 AV Foundation
iOS 4.0
新增 Core Media Framework
强化 AV Foundation
相关链接:What's New in iOS