Android多媒体篇

        多媒体接口和娱乐、游戏等业务密切相关,灵活地采用多媒体接口,可以使应用具备更强的吸引力。

1.音频处理

        作为多媒体处理的最基本的组成部分,音频处理在移动终端上十分复杂。音频的播放、记录、以及多种场景(如电话、音乐、提示音、录音等)的冲突、并发策略无疑增加了开发的难度。好在Google在设计Android时充分考虑了这些问你,在底层设计了一套围绕AndioFlinger、AudioPolicyManager的音频框架,使应用层的开发者可以忽略不同场景下的并发策略。通过这种方法,极大简化了音频应用的开发。

        在应用层,开发者可以调用MediaPlayer、MediaRecorder、SoundPool等进行音频的播放、记录以及游戏的特效音的制作等。在框架层,AudioFlinger、AudioPolicyManager、AudioService、AudioHardwareInterface构成了音频控制的基本骨架。框架层本身包括Java、C++两部分,并通过JNI进行通信,其中对服务的调用是基于C/S架构实现的。内核层提供不同音频设备的驱动和ALSA架构等。而音频本身的播放涉及的多媒体引擎是OpenCore和Stagefright。在默认情况下,OpenCore在Android2.2及以前版本中应用,而在较新的Android版本中,Stagefright则成了默认的多媒体引擎。

        AudioPolicyService所负责的工作在早期版本中是在AudioFlinger中实现的。随着场景的复杂化,Google将关于音频设备的链接状态、音频的并发策略、音量的处理等工作放置到AudioPolicyService中,而AudioFlinger更侧重于音频流的控制。AudioHardwareInterface则是对不同设备厂商的音频设备的驱动与框架层的适配接口,为框架层提供一个与驱动通信的统一接口,这样可以有效地保护硬件厂商的商业利益。
       

         (1)音频播放

                根据播放方式的不同,Android为应用层提供了多个播放接口,如MediaPlayer、SoundPool、AudioTrack、AsyncPlayer、JetPlayer、ToneGenerator等,他们适合用于不同的场景。

               1)基于MediaPlayer播放

                         MediaPlayer具有非常强大的播放功能,对音频和视频的播放均提供了支持。为了保证播放期间系统的正常工作,需要设置android.permission.WAKE_LOCK权限。

                         MediaPlayer支持的音频格式包括AAC、AMR、FLAC、MP3、MIDI、OGG、PCM等。考虑到MediaPlayer的复杂性,在原生层MediaPlayer有状态机控制。 

                                

                         当调用reset方法时,MediaPlayer会返回到MEDIA_PLAYER_IDLE状态,MediaPlayer还存在一个出错的状态,即MEDIA_PLAYER_STATE_ERROR。监听出错的监听器为MediaPlayer.OnErrorListener。

                        对于背景音乐,将MediaPlayer封装在Service中即可实现。

                        MediaPlayer支持元数据、音频文件、音频流等形式的源数据的播放。

                        (1)播放元数据

                                所谓元数据即raw文件夹下的资源文件,调用方法如下:

                                        mMediaPlayer=MediaPlayer.create(this, R.raw.test_cbr);

                                        mMediaPlayer.start();

                        (2)播放音频文件

                                对于本地文件,其数据源可以通过Uri来表示,在开始播放前需要设置播放类型并加载缓冲,示例如下:

                                        Uri myUri=...;

                                        MediaPlayer mediaPlayer=new MediaPlayer();

                                        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

                                        mediaPlayer.setDataSource(getApplicationContext(), myUri);

                                        mediaPlayer.prepare();    //加载缓冲

                                        mediaPlayer.start();

                       (3)播放流

                               MediaPlayer支持基于网络的流播放,其支持的网络协议包括RSTP(RTP、SDP)、HTTP渐进流(HTTP Progressive Streaming)、HTTP生活流(HTTP Live Streaming Draft Protocol,仅Honeycomb版本中用到)等。Android4.0开始支持HTTPS协议,在网络播放和本地播放上略有不同,示例如下:

                                       String url="http://zhangmenshiting.baidu.com/***.mp3;

                                       MediaPlayer mediaPlayer=new MediaPlayer();

                                       mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

                                       mediaPlayer.setDataSource(url);

                                       mediaPlayer.prepareAsync();

                                       ...

                                       mediaPlayer.start();

                                需要说明的是,考虑到网络情况的复杂性,以及获取数据和解码可能耗时较长,不退将在播放流时通过prepare方法来加载缓冲,尤其不能再UI主线程中调用prepare方法。应通过prepareAsync方法将加载缓冲的工作放置在非UI主线程中进行,当准备工作完成时,MediaPlayer通过MediaPlayer.OnPreparedListener监听器可以监听到该事件。设置监听器的方法如下:

                                        mMediaPlayer.setOnPrepareListener(mPreparedListener);

                                通常在准备工作完成后开始进行播放。监听器处理加载缓冲结束的消息方法如下:

                                        MediaPlayer.OnPreParedListener mPreparedListener=new MediaPlayer.OnPreparedListener(){

                                                public void onPrepared(MediaPlayer mp){

                                                        ...

                                                        mediaPlayer.start();

                                                }

                                       }

                                当播放结束时,通过MediaPlayer.OnCompletionListener可以监听到播放结束的消息,示例如下:

                                        mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){

                                               public void onCompletion(MediaPlayer mediaPlayer){

                                                       ...

                                               }

                                       });

                2)基于SoundPool播放

                        SoundPool能够播放音频流的组合音,这对游戏应用而言显然非常有用。其对应的JNI接口为android_media_SoundPool.cpp。

                        SoundPool可以通过APK包中的资源文件或文件系统中的文件将音频资源加载到内存中。在底层实现上,SoundPool通过媒体播放服务(MediaPlaybackService)可以将音频资源解码为一个16位的单声道或者立体声的PCM流,是应用避免了在回放过程中进行解码造成的延迟。

                        除了回放过程中延迟小的优点外,SoundPool还能够对一定数量的音频进行同时播放。当要播放的音频流数量超过SoundPool所设定的最大值时,SoundPool将会停止已播放的一条低优先级的音频流。SoundPool对最大播放音频流数量的设置(默认为32),可以避免CPU过载和影响用户体验。

                        对游戏等应用而言,MediaPlayer会使性能降低。在Android中,专门提供了SoundPool类来执行此类音频播放。SoundPool类占用的CPU资源较少、反应较快。

                        和其他音频播放类相比,SoundPool类可以自行设置音频播放时的品质、音量、播放速率等,并且可以管理多个音频流,每个流均拥有自己独立的ID,对单个音频流的管理均是通过其ID来进行的。SoundPool类适用的场景包括应用程序中的声效(按键提示音、消息等)、游戏中密集而短暂的声音(如多个飞船同时爆炸)。

                 3)基于AudioTrack播放

                         AudioTrack主要用于管理单个音频,这是一个较底层的音频播放方法,在构建AudioTrack时,需要指明流类型、采样率、通道配置、音频格式、缓冲大小、播放模式等参数。

                        AudioTrack支持STREAM_VOICE_CALL、STREAM_SYSTEM、STREAM_RING、STREAM_MUSIC和STREAM_ALAARM等流类型。

                        AudioTrack支持单声道(CHANNEL_OUT_MONO)和立体声(CHANNEL_OUT_STREAMO)两种通道。

                        AudioTrack支持ENCODING_PCM_16BIT和ENCODING_PCM_8BIT两种编码格式。

                        AudioTrack支持静态模式和流模式两种播放模式。静态模式由于没有从Java层向原生层传递数据造成的延迟,因此时延很小。当然。受限于音频缓冲的大小,静态模式通常在游戏场景中用于播放时长很短的音频资源。当音频流较大不足以在音频缓冲中一次写入时,可采用流模式。

                        在设置音频缓冲时,其大小与采样率、通道和音频格式有关。缓冲大小的计算公式如下:

                                缓冲大小=最小帧数*(通道==CHANNEL_OUT_STETEO ?2:1)*(音频格式==278带格式的:边框:底端:(PCM16?2:1)

                        而最小帧数则与采样率和音频设备的延迟等因素有关。

                        AudioTrack的播放状态包括PLAYSTATE_STOPPED、PLAYSTATE_PAUSED、PLAYSTATE_PLAYING等。

                        AudioTrack、示例的状态包括STATE_INITIALIZED、STATE_NO_STATIC_DATA、STATE_UNINITIALIZED等。

                        向音频缓冲中添加数据的方法为write,其应用格式如下:

                                public int write(short[] audioData. int offsetInShorts. int sizeInShorts)

                        通过AudioTrack.OnPlaybackPositionUpdateListener监听器可以监听播放进度。

                4)基于AsyncPlayer播放

                        对于不希望阻塞当前线程的简单播放,可以考虑AsyncPlayer,从而使播放线程可以从容加载缓冲。AsyncPlayer的示例如下:

                                final Uri PLAY_URI=Settings.System.DEFAULT_NOTIFICATION_URI;

                                AsyncPlayer asyncPlayer=new AsyncPlayer(null);

                                asyncPlayer.play(getContext(), PLAY_URI, true, AudioManager,STREAM_RING);

                                final int PLAY_TIME=3000;

                                Thread.sleep(PLAY_TIME);

                                asyncPlayer.stop();

                        虽然在底层依然是通过MediaPlayer进行播放的,但是AsyncPlayer支持的播放控制有限。

                5)基于JetPlayer播放

                        在Android中,还提供了对Jet播放的支持。它包括两部分:Jet播放器和Jet引擎。Jet常用于控制游戏的声音特效,采用MIDI格式。

                        MIDI数据由一套音乐符号构成,而非实际的音乐,这些音乐符号的一个序列被称为MIDI消息。Jet文件包含多个Jet段,而每个Jet段又包含多个轨迹,一个轨迹是MIDI消息的一个序列。

                        JetPlayer是Jet在应用层的接口,JetPlayer类内部有个存放Jet段的队列,其主要作用是向队列中添加Jet段或清空队列,其次就是控制Jet段的轨迹是否处于打开状态,需要注意的是,在Android中,JetPlayer是基于单子模式实现的,在整个系统中,仅存在一个JetPlayer的对象。

                        通过JetPlayer.OnJetEventListener可以处理播放事件。JetPlayer在普通应用开发中并不常见。

                6)基于ToneGenerator播放

                        ToneGeneator提供了对DTMF音,以及呼叫监督音和专用音中规定音频的支持,对应的JNI接口文件为android_media_ToneGenerator.cpp。

                        停止ToneGenerator播放的方法为stopTone。

                        需要说明的是,DTMF音为WAV格式,相关的音频类型定义位于ToneGenerator.h文件中。

                7)基于Ringtone播放

                        Ringtone和RingtoneManager为铃声、提示音、闹钟等提供了快速播放及管理的接口。

                        Ringtone提供了播放铃声、提示音的快速方法,通常和RingtoneManager配合使用。RingtoneManager在系统中维护着一个铃声数据库。

                        RingtoneManager管理来电铃声、提示音、闹铃铃声等,在本质上,Ringtone是对MediaPlayer的再封装。

        (2)音频录制

                录音的方式相对播放而言比较简单,Android仅提供了MediaRecorder、AudioRecord两个用于音频录制。

                为了录制音频,必须设置音源、输出路径、录制格式等。其中音源由MediaRecorder.AudioSource统一定义。音源包括MIC、VOICE_UPLINK、VOICE_DOWNLINK、VOICE_CALL、CAMCORDER、VOICE_RECOGNITION和VOICE_COMMUNICATION(VOIP)。

                1)基于MediaRecorder录制

                        MediaRecorder支持的音频编码包括AMR_NB、AMR_WB和AAC等,支持的输出格式包括AMR_NB、AMR_WB、MPEG_4、RAW_AMR和THREE_GPP等。

                2)基于AudioRecord录制

                        AudioRecord支持ENCODING——PCM_16BIT和ENCODING_PCM_8BIT等编码,支持CHANNEL_IN_MONO、CHANNEL_IN_STEREO、CHANNEL_IN_LEFT和CHANNEL_IN_RIGHT等声道。

        (3)音频管理

                音频管理主要是通过AudioManager来进行,通过AudioManager可以进行设备、音量、资源竞争、音效播放等方面的管理工作。

                1)设备管理

                         AudioManager的强大主要体现在对蓝牙、扬声器、麦克风、耳机振动等音频相关设备的管理等方面。AudioManager对音频设备进行管理的主要方法如下:

                                 public void setBluetoothScoOn(boolean on)

                                 public void setMicrophoneMute(boolean on)

                                 public void setSpeakerPhoneOn(boolean on)

                                 public void setVibrateSetting(int vibrateType, int vibrateSetting)

                         setRouting()、setWiredHeadsetOn()等方法已经被抛弃,不建议继续使用。另外,AudioManager还支持对流的管理,方法如下:

                                 public void setStreamMute(int streamType, boolean state)

                                 public void setStreamSolo(int streamType, boolean state)

                        当用户正在使用耳机欣赏音乐时,可能无意间因走动等造成耳机和终端断开,这时就需要处理Action为android.media.AUDIO_BECOMING_NOISY的广播消息,暂停播放,以避免外放而产生噪声。

                2)音量调整

                        AudioManager支持对特定流或整体的音量调节,方法如下:

                                public void adjustStreamVolume(int streamType, int direction, int flags)

                                public void adjustVolume(int direction, int flags)

                       音量调节的方向包括ADJUST_RAISE、ADJUST_LOWER、ADJUST_SAME等,标志位可以是FLAG_SHOW_UI、FLAG_ALLOW_RINGER_MODES、FLAG_PLAY_SOUND、FLAG_VIBRATE、FLAG_REMOVE_SOUND_AND_VIBRATE等,示例如下:

                               if(mAudioManager.isMusicActive()){     //判断是否有音乐播放

                                       mAudioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, keyCode==KeyEvent.KEYCODE_VOLUME_UP?AudioManager,ADJUST_RAISE: AudioManager.ADJUST_LOWER, 0);

                3)资源竞争

                        在Froyo版本以前,没有对多个应用竞争有限的扬声器资源提供内置的处理策略,用户体验不佳,故在Froyo版本中,引入了Audio Focus策略来处理这一问题。

                        当需要资源时,应用通过AudioManager的requestAudioFocus方法获得Audio Focus。一旦失去了Audio Focus,当前的播放会被剥夺资源。

                4)音效播放

                        AudioManager还支持音效播放,方法为playSoundEffect。在播放音效前,必须调用loadSoundEffects方法,即创建一个SoundPool对象来执行实际的播放。

        (4)音效处理

                在Android2.3中,对音频播放提供了更强大的音效支持,其实现位于android.media.audiofx包中。

                1)重低音

                        BassBoost通过放大音频中的地拼音来实现重低音特效。重低音的细节有OpenSL ES 1.0.1定义。

                        要想在通过AudioTrack、MediaPlayer进行音效播放时具有重低音特效,在构建BassBoost示例时指明音频流的会话ID即可。如果指定的会话ID为0,则BassBost作用于主要的音频输出混音器(mix)上,BassBoost将会话ID指定为0需要具备android.permission.MODIFY_AUDIO_SETTINGS权限。BassBoost的应用示例如下:

                                mBassBoost=new BassBoost(0, 0);

                                if(mBassBoost.getStringthSupported()){

                                        mBassBoost.setStrength(mBassBoost.getRoundedStrength());        //设置强度

                                }

                2)环绕音

                        环绕音依赖于输出和输入通道的数量和类型,需要打开立体声通道。环绕音通过将音源放置于不同的位置,完美地再现了声音的质感和饱满度。在创建Virtualizer示例时,在音频框架层会同时创建一个环绕音引擎。环绕音的细节由OpenSL ES 1.0.1规范定义。

                        要想在通过AudioTrack和MediaPlayer进行音频播放时具有环绕音特效,在构建Virtualizer示例时指明音频流的会话ID即可。如果指定的会话ID为0,则Virtualizer作用于主要的音频输出混音器上,Virtualizer将会话ID指定为0需要具备android.permission.MODIFY_AUDIO_SETTINGS权限。Virtualizer的应用示例如下:

                                mVirtualizer=new Virtualizer(0, 0);

                                Virtualizer.Settings settings=mVirtualizer.getProperties();

                                String str=settings.toString();

                                settings=new Virtualizer.Settings(str);        //设置属性

                3)均衡器

                        均衡器是一种可以分别调节各种频率电信号放大量的电子设备,它通过对各种不同频率电信号的调节来补偿扬声器和声场的缺陷,补偿和修饰各种声源,以及提供其他特殊作用。一般均衡器仅能对高频、中频、低频三段频率电信号分别进行调节。

                        要想在通过AudioTrack和MediaPlayer进行音频播放时具有均衡器特效,在构建Equalizer示例时指明音频流的会话ID即可。如果指定的会话ID为0,则Equalizer作用于主要的音频输出混音器上,Equalizer将会话ID指定为0需要具备android.permission.MODIFY_AUDIO_SETTINGS权限,相关的示例如下:

                                mp=new MediaPlayer();

                                equalizer=new Equalizer(0, mp.gerAudioSessionId());        //附着音频流

                                equalizer.setEnable(true);

                                equalizer.release();

                                mp.release();

                4)混响

                        混响是通过声音在不同路径上传播造成的反射叠加而产生的声音特效。在Android中,Google给出了两个实现:EnvironmentalReverb和PresetReverb,推荐在游戏场景中应用EnvironmentalReverb,在音乐场景中应用PresetReverb。在创建混响示例时,在音效框架层将会同时创建一个混响引擎。

                        要想在通过AudioTrack和MediaPlayer进行音频播放时具有混响特效,在构建EnvironmentalReverb示例时指明音频流的会话ID即可,。如果指定的会话ID为0,则EnvironmentalReverb作用于主要的音频输出混音器上,EnvironmentalReverb将会话ID指定为0需要具备android.permission.MODIFY_AUDIO_SETTINGS权限。

                        通过EnvitonmentalReverb还可以设置反射、房间等场景的强度和延迟等,PresetReverb的用法和EnvironmentalReverb类似。

                5)可视化

                       可视化分为两种情况:波形可视化和频率可视化。可视化的使用要求具备android.permission.RECORD_AUDIO全乡。在创建Visualizer示例时,将会同时在音频框架层创建一个可视化引擎。

                       要想在通过AudioTrack和MediaPlayer进行音频播放时具有可视化特效,在构建Visualizer示例时指明音频流的会话ID即可。如果指定的会话ID为0,则Visualizer作用于主要的音频输出混音器上,Visualizer将会话ID指定为0,需要具有android.permission.MOSIFY_AUDIO_SETTINGS权限。

2.视频处理

        在Android中,视频处理大致可以分为视频播放、视频记录和视频电话等3个部分,其中视频播放主要基于MediaPlayer进行,视频录制主要通过mediaRecorder进行,而视频电话则相对复杂。视频电话涉及多路视频、视频协议栈3G-324M等内容。

        (1)视频播放

                在Android中,视频的播放有两种方案,一种是基于VideoView的,一种是基于SurfaceView的。基于VideoView的方案实现简单,但无法进行更多的个性化配置,不支持播放界面的动态变化;而基于SurfaceView的方案则具备更多的能力,但实现较复杂,多用于商业应用中。视频播放的部分参数受制于实际的硬件。

                1)视频状态机

                        从视频播放的状态分析,除了正常播放、进度控制等外,视频播放还需要支持缓冲刷新等功能。

                        视频播放的状态包括MEDIA_NOP、MEDIA_PREPARED、MEDIA_PLAYBACK_COMPLETE、MEDIA_BUFFERING_UPDATE、MEDIA_SEEK_COMPLETE、MEDIA_SET_VIDEO_SIZE、MEDIA_ERROR、MEDIA_INFO等。

                        视频播放的进度控制和音频播放类似,这里不再详述,当缓冲发生更新时,通过OnBufferingUpdateListener监听器即可收到缓冲进度信息。

                2)基于SurfaceView的播放

                        基于SurfaceView来播放视频可以充分利用系统的硬件加速能力,保障播放的流畅。Surface渲染是Android底层框架的一个重要技术,其管理由SurfaceFlinger进行。基于SurfaceView的播放框架如下图:

                               

                        Android 4.0中提供了与SurfaceView相似的TextureView来支持视频或OpenGL场景,但TextureView的用法更类似于普通的视图。开发者还可以显示地设置Surface,方法为setSurface。

                        为了将播放信息及时地反馈给UI',MediaPlayer提供了多个监听器供开发者选择。这些监听器包括OnBufferingUpdateListener(用于监听缓冲的变化)、OnCompletionListener(监听播放是否完成)、OnErroListener(监听播放过程中出错信息)、OnInfoListener(监听播放过程中的提示等)、OnPreparedListener(监听播放时资源的分配情况)、OnSeekCompleteListener(监听跳转的完成情况)、OnVideoSizeChangeListener(监听视频大小的变化)等。

                3)基于VideoView的播放

                        VideoView事实上是对SurfaceView和MediaPlayer的一种封装,VideoView支持数据源的设置、播放状态控制、播放信息获取等。

                        VideoView支持通过Uri和路径两种方式设置数据源,其方法如下:

                                public void setVideoPath(String path)

                                public void setVideoURI(Uri uri)

                        对于播放状态控制,VideoView支持播放控制器的设置和直接进行状态控制。

                        对于播放信息,VideoView支持文件播放时长和当前进度的获取。

                4)播放控制器

                        MediaController是一个提供控制条的Widget,利用MediaController,开发者可以避免不必要的重复工作。

                        但对于商业开发而言,图形界面产生的用户体验是吸引用户的第一道关口,软件能否复用并非开发者和厂商关注的重点,所以MediaController的作用基本可以忽略。厂商通常会指定自己的播放控制界面。

        (2)视频录制

                录制视频是主流移动终端的基本功能,随着硬件能力的提升,其支持的视频记录格式越来越多,主要有H263、H264 AVC等,相关的后缀有.3gp、.mp4、.ts等。录制视频的部分参数受制于实际的硬件配置。

                通过MediaRecord进行视频录制于进行音频录制的主要区别在于前者需要设置视频源,并且输出格式不同。为了录制视频,需要设置很多参数。

                MediaRecorder的许多方法间存在依赖关系,如setVideoSource方法和setAudioSource方法必须在setOutFormat方法前设置;通过setOrientationHint方法设置角度,必须在prepare方法前调用;通过setMaxDuration方法设置持续时间,则必须在setOutFormat方法后并在prepare方法前进行。在开发视频录制的应用前,必须了解这些依赖关系。

                在Android 4.0中,当完成一段视频的录制后,系统会广播android.hardware.action.NEW_VIDEO消息。

3.Camera服务

        Camera是目前最常见的业务之一,主要用于拍照、录像、预览、设置参数等,调用Camera需要如下权限:

                <uses=permission android:name="android.permission.CAMERA"/>

                <uses=feature android:name="android.hardware.camera"/>

                <uses=feature android name="android.hardware.camera.autofocus"/>

        为了支持Camera功能,驱动层必须实现CameraHardwareInterface接口。Android支持前后摄像头,默认为后置摄像头,对应的选项为CameraInfo.CAMERA_FACING_BACK、CameraInfo.CAMERA_FACING_FRONT等,通过如下方法可以获得摄像头的数量:

                int numberOfCameras=Camera.getNumberOfCaneras();

        (1)为了实现预览和参数设置

                1)通过open方法获得摄像头实例,在打开摄像头时,如果是切换摄像头的场景,一定要项停止预览,然后释放摄像头头,再打开新摄像头。用到的方法如下:

                         private void stopPreview();

                         public final void release();

                2)设置摄像头参数。摄像头的参数很多,具体的参数项位于Camera.parameters类中,获得Camera.Parameters类实例的方法如下:

                         Camera.Parameters parameters=camera.getParameters();

                      通过Camera.Perameters类可以设置摄像头的预览大小、JPEG质量、速率、照片大小、拍照格式、白平衡、缩放、特效等。

                3)设置显示方向

                       设置显示方向是通过setDisplayOrientation方法进行的。Android支持0度、90度、180度、270度旋转。需要注意的是,在预览时,不允许调用该方法。另外该方法仅对预览起作用。

                4)设置Surface

                        要设置Surface,必须创建一个SurfaceHolder.Callback类来监听SurfaceView的创建和销毁。

                5)启动预览

                        启动和停止预览非常简单。

        (2)拍照

                为了拍照,必须调用如下方法:

                        public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback postview, PictureCallback jpeg);

                照片的拍摄和编码是个复杂的过程,而takePicture是个异步的方法,通常需要轻微的延迟才能得到最终的数据,因此Android提供了ShutterCallback、PictureCallback回调用于处理相关的数据。

                ShutterCallback回调会在照片拍摄后触发,用于播放拍照音;当照片的元数据可用时,会触发PictureCallback回调;PictureCallback回调在生成缩放图像后触发(并非所有硬件都支持);PictureCallback回调在压缩JPEG图像生成时触发。

                在Android 4.0中,在拍摄完一张照片后,系统会广播android.hardware.action.NEW_PICTURE消息。

4.TTS的实现

        在Android 1.6及以后版本中,Android开始通过支持语音合成的Svox语音引擎,即TTS。

        TTS引擎目前支持English、French、German、Italian和Spanish等语言。当然,对于同一种语言,Android支持不同的语言变种,如美式英语和英式英语。

        (1)TTS语言资源

                由于设备存储空间的限制,并非所有设备上均安装了所有的TTS语音资源,为了判断请求的TTS语音资源是否可用,可用空间是否足够,需要进行检测,检测方法如下:

                        Intent cheakIntent=new Intent();

                        checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);

                        startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);

                上述程序如果返回的标识符为TextToSpeech.Engine.CHECK_VOICE_DATA_PASS表示请求的TTS语音资源存在,否则可以通过Action为ACTION_INSTALL_TTS_DATA的Intent来请求安装相应TTS语言资源。

        (2)TTS应用开发

                TTS的功能主要依据TextToSpeech进行,为了开发TTS应用,需要经过4步。

                1)创建TextToSpeech对象

                        在创建TextToSpeech对象的过程中,TTS引擎会进行一系列参数设置并调用TextToSpeech.OnInitListener监听器监听初始化的万层情况,具体方法如下:

                                public TextToSpeech(Context context, OnInitListener listener)

                        当TTS引擎初始化成功时,会在初始化回调函数OnInitListener中返回TextToSpeech.SUCCESS状态,否则返回TextToSpeech.ERROR状态。

                2)处理初始化回调

                        如果希望在TTS希望在TTS引擎初始化完成后立即执行某些动作,则必须处理初始化回调,其方法为inInit,实例如下:

                                public void onInit(int state){

                                        if(status==TextToSpeech.SUCCESS){

                                                int result=mTts.setLanguage(Locale.US);

                                        }

                               }

                3)执行语音合成

                        执行语音合成的方法如下:

                                public int speak(String text, int queueMode, HashMap<String, String> params)

                        目前,TTS引擎支持QUEUE_FLUSH和QUEUE_ADD两种排队方法,前者抛弃当前队列中的其他选项,立即处理当前项,后者将当前项添加到当前队列的尾部。判断合成语音是否播放完成,可以通过TextToSpeech.OnUtteranceCompletedListener监听器监听。

                        另外TTS还支持字符串和音频资源和音频文件的映射,用于实现更复杂的音频内容播放,实现方法如下:

                                public int addSpeech(String text, String packagename, int resourceId)

                                public int addSpeech(String text, String filename)

                        要保持合成的语音,可采用如下方法:

                                public int synthesizeToFile(String text, HashMap<String, String>param, String filename)

                        判断是否正在进行TTS的方法为isSpeaking,停止TTS的方法为stop,另外通过setSpeechRate方法还可以设置合成语音速率。

                4)关闭TextToSpeech

                        当不再使用TTS引擎时,应关闭TextToSpeech,方法为shutdown,这会释放一些TTS引擎占用的原生资源。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值