`
zcwfeng
  • 浏览: 98693 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
社区版块
存档分类
最新评论

Android 4.1系统变化

 
阅读更多
Android 4.1,英文代号简称JB。在国人眼里,JB这个词还和动物有点关系。Google如此频繁修改Android,终于推出了一个可以被大家整天JB JB挂在嘴上的版本。以后我的文章也可以一面用JB表示版本号,一面用JB表示常说的”战略上的鄙视了“。请大家根据上下文揣摩我写下JB一词的心情。
今天将稍深入得介绍一下JB 4.1在Audio系统做的翻天覆地的改动。这里先啰嗦几句:就像80后经常抱怨自己晚生了几年一样,马上就会有很多码农抱怨接触Android太晚了。为何?JB Audio系统的难度相对4.0, 2.3, 2.2已经非常非常大了。99%的情况下,在你没有看到这个NB(这不是脏话,4.1 Audio系统中就有一个类叫NBAIO,篮球控不要搞错成NBA了,原意是Non-block Audio I/O。看到了吧, 非阻塞I/O,各位自问下,有多少人对这个东西有深刻理解?)东西演化的基础上,不太可能能看懂JB Audio系统。所以,建议这99%中的没有见识过Audio演化历史的屌丝同学们,先仔细研究(以前我仅仅建议大家看看,现在提高要求为仔细研究)《深入理解Android 卷I》Audio系统。 BTW,此书在某个章节里特意提醒过大家要去研究下各种I/O模型,不知道有几个人屌过我了。
本文将分几个部分,事前没有打草稿,所以会有点乱。
先从Java层AudioTrack类说起
一 AudioTrack Java类变化说明
  • 声道数上,以前只有单声道(MONO)和立体声(STEREO),现在拓展到最NB八声道(7.1 HiFi啊)。参数名为CHANNEL_OUT_7POINT1_SURROUND。看到这个参数,我下巴咣当就掉下来了。这玩意,一时半会我还弄不明白是个什么道理。有知晓的屌丝码农们不妨告诉大家。 当然,最终的输出还是双声道。多声道(大于2)的时候会使用downmixer处理(下变换处理,同学们可搜索之)
  • 其他的变化也有,但不大了。我这里先挑一些吸引眼球的。BTW,放心,不会像那个泷泽萝拉首秀片子一样只让大家看见大鼻孔的。
二 AudioTrack JNI层变化说明
这一层包括JNI层和AudioTrack本身
  • JNI层变化不大。
  • Audio Native核心代码移到了framework/av下。对,你没看错。真的是av。这就是JB Audio一个比较大的变化。Audio Native核心代码全部移到了frameworks/AV目录下。
  • AudioTrack增加了一个变量,用于控制使用它的进程的调度优先级(前文说错了,这里确实设置的是nicer值)。如果处于播放状态的话,将设置进程调度优先级为ANDROID_PRIORITY_AUDIO。就像你们看到马赛克时一定会嘟喃一样。我这里也要特别啰嗦几句。在单核CPU的情况下,设置优先级是比较愚蠢的(ANDROID_PRIORITY_AUDIO的值为-16,优先级极高,单核设置个这么高的怪物,不知道其他app还怎么玩。如果你不知道我在说什么,先看看这篇文章吧,http://blog.csdn.net/innost/article/details/6940136)。但现在2核,4核已经比较常见了,这里就可以来玩玩调度方面的事情。对屌丝码农的真正考验是:多核并行编程,linux os的原理,需要各位屌丝同学努力掌握。Audio已经不那么能轻易被你们任意蹂躏了。另外,低端手机,求求你们别移植4.1了,这个真的不是低端能玩的。
  • AudioTrack升级为父亲了。JB为它定义了一个莫名其妙的的TimedAudioTrack子类。这个类在编解码的aah_rtp(我现在还不知道aah是什么)里边用到了。从注释上看,该类是一个带时间戳(有时间戳,就可以做同步了)的音频输出接口。详细理解的话,就需要结合具体应用场景去分析了(主要是rtp这一块)。搞编解码的同学们,抓紧了!
  • 另外一个超级复杂的变化,是Audio定义了几个输出flag(见audio.h的audio_output_flags_t枚举定义)。根据注释,该值有两个作用,一个是AT的使用者可以指明自己想使用怎样的outputDevice。另外一个是设备厂商可以通过它声明自己支持的输出设备(看来,设备初始化的时候,又增添了参数读取和配置这方面的工作)。不过,从该枚举的定义来看,我还看不出它和硬件有什么关系。它定义的值如下:
typedef enum {
AUDIO_OUTPUT_FLAG_NONE = 0x0, // no attributes
AUDIO_OUTPUT_FLAG_DIRECT = 0x1, // this output directly connects a track
// to one output stream: no software mixer
AUDIO_OUTPUT_FLAG_PRIMARY = 0x2, // this output is the primary output of
// the device. It is unique and must be
// present. It is opened by default and
// receives routing, audio mode and volume
// controls related to voice calls.
AUDIO_OUTPUT_FLAG_FAST = 0x4, // output supports "fast tracks", 《==什么叫fast track?太难理解了!目前,java层的audiotrack只会使用第一个标志。
// defined elsewhere
AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8 // use deep audio buffers 《==deep buffer是个什么玩意?这个马赛克是不是太大了点?现在完全看不清楚啊??!
} audio_output_flags_t;
  • AudioTrack其他变化不大。AudioTrack.cpp总共才1600多行,so easy!
OK,上面有好几个马赛克,平常看看日本大片的时候也就撸过去了,但分析Audio可不行。把去马赛克的希望寄托在下一步AudioFlinger的分析上吧!
三 AudioFlinger变化说明
我们将根据AF工作的主要流程来介绍下变化情况:
  • AF创建,包括其onFirstRef函数
  • openOutput函数及MixerThread对象的创建
  • AudioTrack调用createTrack函数
  • AudioTrack调用start函数
  • AF混音,然后输出
3.1 AF创建和onFirstRef
恩,没什么太大变化。有三个点:
  • 现在对Primary设备的音量有了更为细致的控制,例如有些设备能设音量,有些不能设置音量,所以定义了一个master_volume_support(AudioFlinger.h)枚举,用来判断Primary设备的音量控制能力。
  • 以前播放过程的standby时间(就是为了节电而用)是写死的,现在可由ro.audio.flinger_standbytime_ms控制,如果没有这个属性,则默认是3秒。AF还增加了其他变量控制,例如有一个gScreenState变量,用来表示屏幕是开还是关。可通过AudioSystem::setParameters来控制。另外还定义了一个和蓝牙SCO相关的mBtNrecIsOff变量,是用于控制蓝牙SCO(录音时用,蓝牙上的一个专业术语叫,NREC。不知道是什么,用懂的人告诉我一下)时禁止AEC和NS特效的。请参考AudioParameter.cpp
3.2 openOutput函数
openOutput函数比较关键,其中会见到以前的老朋友MixerThread,AudioStreamOutput等。整个流程包括加载Audio相关的硬件so。这部分工作在4.0的时候就有了,谈不上太多的变化。但物是人非,老朋友已经发生巨大变化了。先来看MixerThread家族。

图1 PlaybackThread家族
图1稍加解释:
  • ThreadBase从Thread派生,所以它会运行在一个单独的线程中(啰嗦一句,线程和对象其实没有关系的,不懂多线程编程的码农们请务必认真学习多线程)。它定义了一个枚举type_t,用来表示子类的类型,这几个类型包括MIXER,DIRECT,RECORD,DUPLICATING等。这个应该比较好懂吧?
  • ThreadBase的内部类TrackBase从ExtendedAudioBufferProvider派生,这个应该是新增加的。TrackBase嘛,大家把它理解成一个Buffer Container就好了。
  • ThreadBase的内部类PMDeathRecipient用来监听PowerManagerService的死亡消息。这个设计有点搞,因为PMS运行在SystemService中,只有SS挂了,PMS才会挂。而SS挂了,mediaserver也会被init.rc的规则给弄死,所以AudioFlinger也会死。既然大家都一起死,速度很快。故,设置这个PMDeathRecipient有何大的意义呢?
再来看ThreadBase的一个重要子类PlaybackThread,这个类应该是做过大整容了。
  • 其定义了一个枚举mixer_state,用来反映当前混音工作的状态,有MIXER_IDLE,MIXER_READY和MIXER_ENABLED
  • 定义了几个虚函数,需要子类实现,包括threadLoop_mix,prepareTracks_l等。这几个函数的抽象工作做得还是可以。但变化之大让人防不胜防啊。
  • Track类增加了从VolumeProvider派生,这个VP是用来控制音量的。根据前面的介绍,在JB中,音量管理比以前来得细致
  • 新增定义了TimedTrack。这个类的作用和前面提到的rtp aah有关。等同学们学完本篇,即可开展相应研究,打响歼灭战!
接下来看图2。

图2 MixerThread和它的弟兄们
图2,简单介绍一下:
  • MixerThread从PlaybackThread派生,这个关系至始至终不会变化,相信以后也不会。
  • MT最大的变化是其中几个重要的成员变量。大家肯定认识其中的AudioMixer,它是用来混音的。
  • 新增一个Soaker对象(由编译宏控制),它是一个线程。这个单词的前缀soak在webster词典(相信经历过,那些年,我们一起GRE的日子 的人知道什么是webster)中最贴切的一条解释是to cause to pay an exorbitant amount。还是不很明白是干嘛的?再一看代码。原来,soaker就是一个专职玩弄CPU的线程。它的工作就是不断得做运算,拉高CPU使用率。它的存在应该是为了测试新AF框架在多核CPU上的效率等等等的问题。所以,低端智能机们,你们不要玩JB了。
  • 另外一条证明低端智能机不能随便玩JB的铁证就是:我们看到MT中新增了一个FastMixer,它也是一个线程。明白了?在JB中,多核智能机上,混音工作可以放到FastMixer所在的线程来做,当然速度,效率会高了。
  • FastMixer工作流程比较复杂,又牵扯到多线程同步。所以,这里定义了一个FastMixerStateQueue,它由typedef StateQueue<FastMixerState>得到。首先它是一个StateQueue(简单把它当做数组吧)。其数组元素的类型为FastMixerState。一个StateQueue通过mStats变量保存4个FasetMixerState成员。
  • FasetMixerState类似状态机,有一个enum Command,用来控制状态的。FastMixerState中含有一个八元组的FastTracks数组。FastTrack是用来完成FastMixer的一个功能类。
  • 每个FastTrack都有一个mBufferProvider,该成员类型为SourceAudioBufferProvider。
以上的内容已经比较复杂了,下面来介绍下MixerThread对象创建中碰到的其他内容:
3.3 MixerThread创建
通过图1和图2,应该对AF的几个主要成员有了认识。可惜啊,上面MixerThread中还有一个mOutputSink成员,没看到吧?它就和我们前面提到的NBAIO(Non-block Audio I/O )有重大关系。NBAIO的存在,是为了想实现非阻塞的音频输入输出操作。下面是这个类的注释:
NBAIO注释:
// This header file has the abstract interfaces only. Concrete implementation classes are declared
// elsewhere. Implementations _should_ be non-blocking for all methods, especially read() and
// write(), but this is not enforced. In general, implementations do not need to be multi-thread
// safe, and any exceptions are noted in the particular implementation.
NBAIO只是定义了一个接口,需要去实现具体的实现类。当然,它要求read/write函数是非阻塞的,真实实现到底是不是阻塞,由实现者去控制。
个人感觉这部分框架还没有完全成熟,但NBIO的引入,需要同学们小心,相对而言,难度也比较大。下面我们通过图3来看看NBAIO的一些内容。

图3 NBAIO相关内容
图3解释如下:
  • NBAIO包括三个主要类,一个是NBAIO_Port,代表I/O端点,其中定义了一个negotiate函数,用于调用者和I/O端点进行参数协调。注意,并不是为I/O端点设置参数。因为I/O端点往往和硬件相关,而硬件有些参数是不能像软件一般随意变化的。例如硬件只支持最多44.1KHZ的采样率,而调用者传递48KHz的采样率,这直接就需要一个协商和匹配的过程。这个函数的比较难用,主要是规则较多。同学们可以参考其注释说明。
  • NBAIO_Sink对应output端点,其定义了write和writeVia函数,writeVia函数需要传递一个回调函数via,其内部将调用这个via函数获取数据。类似数据的推/拉两种模式。
  • NBAIO_Source对应input端点,其定义了read和readVia函数。意义同NBAIO_Sink。
  • 定义一个MonoPipe和MonoPipeReader。Pipe即管道,MonoPipe和LINUX中的IPC通信Pipe没毛关系,只不过借用了这个管道概念和思路。MonoPipe即只支持单个读者的Pipe(AF中,它是MonoPipeReader)。这两个Pipe,代表了Audio的Output和Input端点。
  • MT中由mOutputSink指向AudioStreamOutSink,此类用NBAIO_Sink派生,用于普通的mixer的输出。mPipeSink指向MonoPipe,本意是用于FastMixer的。另外,还有一个变量mNormalSink,它将根据FastMixer的情况,指向mPipeSink,或者是mOutputSink。这段控制的逻辑如下:
switch (kUseFastMixer) { //kUseFastMixer用于控制FastMixer的使用情况,一共4种:
case FastMixer_Never: //永远不使用FastMixer,这个选项用于调试,即关闭FastMixer的情况
case FastMixer_Dynamic: //根据情况,动态使用。根据注释,这个功能似乎还没有完全实现好
mNormalSink = mOutputSink;
break;
case FastMixer_Always: //永远使用FastMixer,调试用
mNormalSink = mPipeSink;
break;
case FastMixer_Static://静态。默认就是这个。但具体是否使用mPipeSink,将收到initFastMixer的控制
mNormalSink = initFastMixer ? mPipeSink : mOutputSink;
break;
}
由上所述,kUseFastMixer默认是FastMixer_Static,但mNormalSink是否指向mPipeSink,还由initFastMixer控制。这个变量本身又有mFrameCount和
mNormalFrameCount的大小决定,只有mFrameCount小于mNormalFrameCount时,initFastMixer才为真。晕了....这两个frameCount由PlaybackThread的
readOutputParameters得到。请同学们自己研究这段代码吧,就是一些简单的计算。想要搞明白的话,最好带着参数进去,把值都算出来。
好了,MixerThread的创建就分析到此,最好还是把这段代码多研究研究。了解几个兄弟对象是做什么的....
3.4 createTrack和start说明
createTrack中最大的变化就是新增了对MediaSyncEvent同步机制的处理。MediaSyncEvent的目的很简单,其Java API的解释如下:startRecording(MediaSyncEvent) is used to start capture only when the playback on a particular audio session is complete. The audio session ID is retrieved from a player (e.g MediaPlayer, AudioTrack or ToneGenerator) by use of the getAudioSessionId() method. 简单点讲,就是必须等上一个player工作完毕了,才能开始下一个播放或者录制。这个机制解决了Android长久以来的声音经常混着出来的问题(目前一个恶心但却实效的方法就是加一个sleep,以错开多个player不同步的问题。)。注意,iPhone上就没有这个问题。
另外,这个机制的潜在好处就是解放了做AudioPolicy AudioRoute工作的同学们, 似乎(个人感觉是可以解决这个问题的)可以不用再去琢磨到底sleep多少时间,在哪加sleep的问题了
在AF中,MediaSyncEvent机制的代表是SyncEvent。大家自己看看就好。
start函数的变化不大,其中加了对SyncEvent的处理。
另外,createTrack中还涉及到FastMixer和TimedTrack处理。核心在PlaybackThread的createTrack_l和Track构造函数中。尤其是和FastMixer的关系。
根据图2,FM(FastMixer简写)内部用得数据结构是FastTrack,而MT用得是Track,所以这里存在一一对应的关系。FM的FastTrack是保存在数组中的,所以
使用FM的Track将通过mFastIndex来指向这个FastTrack。
现在搞清楚FastTrack和Track之间的关系即可,后续的数据流动还需要详细讨论
下面来看看MixerThread的工作流程。这部分是重头戏!
3.5 MixerThread的工作流程
这部分难的还是在FastMixer的工作原理上。 不过这里提前和大家说:目前这个功能还没有做完,代码里边一堆的FIXME...。但屌丝们不要happy太早了,
估计马上、很快、必须得下个版本就好了。现在看看这个不成熟的东西,可以缓解以后看到成熟的东西的心理压力。
MT是一个线程,其工作内容主要在threadLoop中完成,而这个函数是由其基类PlaybackThread定义的,大体变化如下:
  • PlaybackThread的threadLoop定义了整个音频处理的大体流程,具体的细节通过几个虚函数(如prepareTracks_l,threadLoop_mix,threadLoop_write)交给子类去实现了
  • MT变化大的首先是prepareTracks_l,首先处理的是FastMix类型的Track,判断标准是该Track是否设置了TRACK_FAST标志(爽了,目前JB中还没有哪个地方使用了这个标志)。这部分判断比较复杂。首先FastMixer维护了一个状态机,另外,这个FastMixer运行在自己的线程里,所以线程同步是必须的。这里采用的是状态来控制FastMixer的工作流程。由于涉及到多线程,所以音频的underrun,overrun状态(不知道是什么吗?看前面提到的参考书!)也是一个需要处理的棘手问题。另外,一个MT是带一个AudioMixer对象,这个对象将完成数据的混音,下变换等等超难度,数字音频处理等方面的工作。也就是说,对于混音来说,前期的prepare工作还是由MT线程来完成,因为这样可以做到统一管理(有些Track并不需要使用FastMixer。但仔细一想,谁都希望处理越快越好,在多核CPU上,将混音工作交给多个线程处理是充分利用CPU资源的典范,这应该是未来Android演化的趋势。所以,我估计这个JB还没完全长大....)。对FastMixer感兴趣的屌丝们,请务必认真研究prepareTracks_l函数。
  • MT下一个重要函数就是threadLoop_mix了,由于存在一个TimedTrack类,那么AudioMixer的process函数就带上了一个时间戳,PTS,presentation timestamp。从编解码角度来说,还有一个DTS,Decode timestamp。这里要闲扯下PTS和DTS的区别了。DTS是解码时间,但编码的时候由于有可能会根据未来帧来编码当前帧。所以,解码的时候会先解未来帧,然后解出当前帧,但是。你播放的时候可不能先播未来帧。只能老老实实得按播放顺序来先播当前帧,然后播未来帧(尽管先解出来的是未来帧)。关于PTS/DTS,请屌丝们研究下IBP相关的知识吧。回到MT,这个PTS是从硬件hal对象取的,应该是HAL内部维护的时间戳。这个时间戳原则上会比较准确。
  • 混音完了,再做特效处理(和以前的版本差不多),然后调用threadLoop_write。MT的threadLoop_write函数的输出端点就是前面那个坑爹的mNormalSink,如果不为空,就调用它的write函数。想着是调用NBAIO_Sink的非阻塞的write函数。根据图2的分析,它有可能是那个MonoPipe,也有可能就是AudioStreamOutputSink,这个sink节点用得就是以前的AudioStreamOutput。而MonoPipe的write其内部就是一个buffer。并没有和真实的AUDIO HAL Output挂上关系。这.....咋整??(大胆假设,小心求证。只能是FastMixer把这个buffer取出来,然后再写到真实的Audio HAL中了。因为在MixerThread构造函数中,曾经为FastTrack保存过mOutputSink,这个就是用来和AudioStreamOutput联系的)
另外,DulicatingThread,DirectOuptutThread没有太大变化。
四 FastMixer工作原理简单说明
我以前想得是:混音工作由FastMixer线程和MixerThread线程共同完成,但输出工作依然在MixerThread做。从上面MonoPipe的分析来看,这个判断可能不准。
既有可能是输出工作也交给FastMixer来做,而MixerThread仅做一部分混音工作,然后把数据通过MonoPipe传给FastMixer线程。FastMixer线程将自己的FastTrack的混音结果和MT的混音结果再做一次混音,然后再由FastMixer输出。
FM定义在FastMixer.cpp中,核心就是一个ThreadLoop。由于AF所有Track的预备工作由MT线程来做,所以FM的threadLoop基本上就是根据状态来做对应处理。
这里的同步使用了LINUX中很底层的futex(Fast Userspace Mutex)。晕,futex是POSIX Mutex的实现基础。不知道写这段代码的人为何不直接用Mutex(估计还是嫌效率的问题,但是 妈的,用了Mutex效率能差多少?代码是写给人看的,太B4我们了...)。玩多线程玩到这种地步,佩服啊!不懂多线程编程的屌丝们,请仔细研究Posix MultiThread Programming吧
  • FastMixer内部还使用了一个AudioMixer,用于它的混音
  • 然后再write出去.....
这里是FM的简单说明,详细内容,没有拿个真机给我,我也没法整啊....欢迎乐善好施的兄弟们刷个4.1的机器,然后借给我研究下...
(这玩意,个人感觉也不是太难。东西嘛,耐不住琢磨,总能搞透的)。兄弟们今天知道FM和MT的大体工作流程就可以了。
五 其他变化
其他变化包括:
  • 非常注重调试了,加了大量的XXXDump类。看来,Google自己开发的时候也碰到不少问题。简单的功能,谁会想着去dump呢?
  • 增加AudioWatchdog类,用来监控AF性能的,如CPU使用情况等。
六 总结
我记得在研究2.2 AF的时候,AudioFlinger才3k多行,而JB已经有9K多行了。还没算其他的辅助类。从整体上看,JB变化趋势为:
  • 要充分利用多核资源,所以FastMixer的出现是必然。还包括NBAIO接口。感觉对HAL编写会有大的挑战。
  • 增加TimedTrack和SyncEvent,对于RTP或者多个player间的同步会带来比较好的用户体验。
  • 增加native层往java层通知的接口。

分享到:
评论

相关推荐

    Android安卓开发文档从0到1开发知识.rar

    Android 是一个开源的,基于 Linux 的移动设备操作系统,如智能手机和平板电脑。Android 是由谷歌及其他公司带领的开放手机联盟开发的。 Android 提供了一个统一的应用程序开发方法,这意味着开发人员只需要为 ...

    安卓Android编程视频, 安卓代码大全, 安卓开发系列视频, 移动开发教程

    Android 是一个开源的,基于 Linux 的移动设备操作系统,如智能手机和平板电脑。Android 是由谷歌及其他公司带领的开放手机联盟开发的。 Android 提供了一个统一的应用程序开发方法,这意味着开发人员只需要为 ...

    A850_TWRP_EnCnTw_forAndorid4.1

    1.仅适用于A850,系统版本4.1以上,且4.0以下系统启动会黑屏 2.编译使用的内核,是从A850K_S0837212的官方Recovery中提取的 3.在CM9环境中编译 4.以2.4.1.0、2.4.4.0、2.5.0.0这3个版本源代码进行编译 5.每个版本又...

    深入理解Android:卷I--详细书签版

     笔者认为,本书最大的特点在于,较全面、系统、深入地讲解了Android系统中的几大重要组成部分的工作原理,旨在通过直接剖析源代码的方式,引领读者一步步深入于诸如Binder、 Zygote、Audio、Surface、Vold、Rild...

    老罗android视频开发源码和ppt经典

    1.1 android系统介绍 1.2 android系统框架的介绍 1.3 如何搭建android开发环境 1.4 android生命周期的介绍 1.5 android使用全局变量传递数据 1.6 android使用剪切板传递数据 1.7 意图传递数据的第一种方式 1.8 ...

    《Google Android SDK开发范例大全(第3版)》.pdf

    5.29 模拟文件下载notification进度变化与关闭 285 5.30 取得已安装应用程序列表与安装日期信息 291 5.31 造假的toast画面 294 5.32 剪贴簿管理器 298 第6章 手机自动服务纪实 302 6.1 您有一条短信...

    Google Android SDK开发范例大全(第3版) 1/5

    余志龙、陈昱勋、郑名杰、陈小风,分别来自手机制造业、电视媒体业、网络、电信产业、软件开发等领域,擅长嵌入式系统软件设计、J2ME游戏开发、Android开发,以及12EE、JSP、Servlet、Java Bean、PHP、C#等程序语言...

    精通ANDROID 3(中文版)1/2

    4.1 探索Android内置的ContentProvider  4.2 ContentProvider的架构  4.3 实现ContentProvider  4.4 练习图书提供程序  4.4.1 添加图书  4.4.2 删除图书  4.4.3 获取图书数量  4.4.4 显示图书列表  ...

    Google Android SDK开发范例大全(第3版) 4/5

    余志龙、陈昱勋、郑名杰、陈小风,分别来自手机制造业、电视媒体业、网络、电信产业、软件开发等领域,擅长嵌入式系统软件设计、J2ME游戏开发、Android开发,以及12EE、JSP、Servlet、Java Bean、PHP、C#等程序语言...

    Google Android SDK开发范例大全(第3版) 3/5

    余志龙、陈昱勋、郑名杰、陈小风,分别来自手机制造业、电视媒体业、网络、电信产业、软件开发等领域,擅长嵌入式系统软件设计、J2ME游戏开发、Android开发,以及12EE、JSP、Servlet、Java Bean、PHP、C#等程序语言...

    Google Android SDK开发范例大全(第3版) 5/5

    余志龙、陈昱勋、郑名杰、陈小风,分别来自手机制造业、电视媒体业、网络、电信产业、软件开发等领域,擅长嵌入式系统软件设计、J2ME游戏开发、Android开发,以及12EE、JSP、Servlet、Java Bean、PHP、C#等程序语言...

    Google Android SDK开发范例大全(第3版)part2

     5.29 模拟文件下载Notification进度变化与关闭  5.30 取得已安装应用程序列表与安装日期信息  5.31 造假的Toast画面  5.32 剪贴簿管理器  第6章 手机自动服务纪实  6.1 您有一条短信pop up提醒  6.2 ...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    鉴于市场上用户的手机型号、种类、屏幕分辨率等参差不齐,传统方式根据主流系统分别开发相应的系统耗时又耗力,为了高效开发并节约开发项目成本,本文采用Android+HTML5相结合的方式进行移动端Web系统的设计研发工作...

    Android电子相册设计报告.doc

    1 1.1Android平台背景 1 1.2安卓电子相册市场需求 1 1.3安卓电子相册功能需求 1 2 软件总体设计 2 2.1电子相册功能设计 2 2.2电子相册软件流程图 2 2.3电子相册UI设计 3 3 关键技术分析 5 4 软件详细设计 5 4.1 获取...

    软件系统整体设计方案.docx

    整体方案 技术架构 用户使用层 支持在android手机、pad电脑、PC电脑等终端上的使用 应用服务层 软件系统整体设计方案全文共25页,当前为第9页。系统基于业内主流WEB框架LAMP进行应用的开发(LAMP框架具有Web资源...

    精通Android 3 (中文版)2/2

    4.1 探索Android内置的ContentProvider  4.2 ContentProvider的架构  4.3 实现ContentProvider  4.4 练习图书提供程序  4.4.1 添加图书  4.4.2 删除图书  4.4.3 获取图书数量  4.4.4 显示图书列表  ...

    Greenify 绿色守护 2.5.2 beta 2

    在Android 4.1及以上版本中,可以通过激活绿色守护提供的『辅助功能』模块实现手动休眠操作的自动代劳,不必再反复点击。 重要说明:『绿色化』一个应用,意味着您确确实实希望这个应用在不启动的时候休眠,也就是说...

    WebSocket客户端和服务端实例源码

    2012 年 Adobe 官方宣布不再支持 Android4.1+系统,宣告了 Flash 在移动终端上的死亡。 从上文可以看出,传统 Web 模式在处理高并发及实时性需求的时候,会遇到难以逾越的瓶颈,我们需要一种高效节能的双向通信机制...

Global site tag (gtag.js) - Google Analytics