android 获取ui线程onpreparedlistener的onprepared是在ui线程吗

android mediaPlay 播放视频
循环播放 -Android- TryCatch
>> Content
android mediaPlay 播放视频
&&&我有一个存放播放路径的List&String&&里面有四个文件,我想一直循环播放这四个文件。请问要怎么去实现??最好给一个demo,非常感谢大家!
------Solutions------
Mediaplayer&加一个OnCompletionListener完成后播放下一个就是了。
------Solutions------
设置了,但是设置后连视频都不能播放了?能帮我看看代码吗?package&ele.bus.import&java.io.Fimport&java.io.IOEimport&java.util.ArrayLimport&java.util.Limport&java.util.Timport&java.util.TimerTimport&android.app.Aimport&android.media.AudioMimport&android.media.MediaPimport&android.media.MediaPlayer.OnBufferingUpdateLimport&android.media.MediaPlayer.OnCompletionLimport&android.media.MediaPlayer.OnPreparedLimport&android.os.Bimport&android.os.Eimport&android.os.Himport&android.os.Mimport&android.util.Limport&android.view.KeyEimport&android.view.SurfaceHimport&android.view.SurfaceHolder.Cimport&android.view.SurfaceVimport&android.webkit.WebVimport&android.webkit.WebViewCpublic&class&ElebusDemActivity&extends&Activity&implementsOnCompletionListener,&Callback,&OnBufferingUpdateListener,OnPreparedListener&{/**&Called&when&the&activity&is&first&created.&*/private&SurfaceView&sVprivate&SurfaceHolder&private&MediaPlayer&mediaPprivate&int&videoWprivate&int&videoHprivate&List&String&&private&int&index&=&0;@Overridepublic&void&onCreate(Bundle&savedInstanceState)&{super.onCreate(savedInstanceState);//&requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.main);mediaPlayer&=&new&MediaPlayer();sView&=&(SurfaceView)&findViewById(R.id.surfaceView1);//&得到SurfaceHolder对象hodler&=&sView.getHolder();//&设置回调函数hodler.addCallback(this);//&设置风格hodler.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);list&=&new&ArrayList&String&();String&url&=&Environment.getExternalStorageDirectory().getAbsolutePath()&+&File.separatorChar&+&"VideosZip";System.out.println(url);getFiles(url);}private&void&play(String&str)&{String&path&=&Environment.getExternalStorageDirectory().getPath()+&File.separatorChar&+&"VideosZip1"&+&File.separator+&"video.mp4";//&构建MediaPlayer对象try&{//&设置媒体文件路径mediaPlayer.setDataSource(path);System.out.println(str);//&设置通过SurfaceView来显示画面mediaPlayer.setDisplay(hodler);//&准备mediaPlayer.prepareAsync();//&设置监听事件mediaPlayer.start();}&catch&(IllegalArgumentException&e)&{//&TODO&Auto-generated&catch&blocke.printStackTrace();}&catch&(IllegalStateException&e)&{//&TODO&Auto-generated&catch&blocke.printStackTrace();}&catch&(IOException&e)&{//&TODO&Auto-generated&catch&blockje.printStackTrace();}mediaPlayer.setOnBufferingUpdateListener(this);mediaPlayer.setOnPreparedListener(this);mediaPlayer.setOnCompletionListener(new&OnCompletionListener()&{@Overridepublic&void&onCompletion(MediaPlayer&mp)&{//&TODO&Auto-generated&method&stubnext();}});mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);}@Overridepublic&boolean&onKeyDown(int&keyCode,&KeyEvent&event)&{if&(keyCode&==&KeyEvent.KEYCODE_BACK&&&&event.getRepeatCount()&==&0)&{event.startTracking();finish();System.exit(0);return&}return&super.onKeyDown(keyCode,&event);}public&class&MyWebViewClient&extends&WebViewClient&{public&boolean&shouldOverviewUrlLoading(WebView&view,&String&url)&{view.loadUrl(url);return&}}private&void&next(){if&(++index&&=&list.size())&{index&=&0;}&else&{play(list.get(index));System.out.println("111");}}public&void&onCompletion(MediaPlayer&mp)&{//&TODO&Auto-generated&method&stub//&mp.seekTo(0);mp.start();}public&void&onPrepared(MediaPlayer&mp)&{//&TODO&Auto-generated&method&stubvideoWhith&=&mediaPlayer.getVideoWidth();videoHeight&=&mediaPlayer.getVideoHeight();if&(videoWhith&!=&0&&&&videoHeight&!=&0)&{//&设置视频的宽度和高度hodler.setFixedSize(videoWhith,&videoHeight);//&开始播放}}public&void&onBufferingUpdate(MediaPlayer&mp,&int&percent)&{//&TODO&Auto-generated&method&stub}//&更改时触发事件public&void&surfaceChanged(SurfaceHolder&holder,&int&format,&int&width,int&height)&{//&TODO&Auto-generated&method&stub}//&当SurfaceHolder创建时触发public&void&surfaceCreated(SurfaceHolder&holder)&{//&TODO&Auto-generated&method&stubplay(list.get(index));}public&void&surfaceDestroyed(SurfaceHolder&holder)&{//&TODO&Auto-generated&method&stub}//&销毁@Overrideprotected&void&onDestroy()&{//&TODO&Auto-generated&method&stubsuper.onDestroy();if&(mediaPlayer&!=&null)&{mediaPlayer.release();mediaPlayer&=&}}private&void&getFiles(String&url)&{try&{File&file&=&new&File(url);File[]&files&=&file.listFiles();for&(int&i&=&0;&i&&&files.&i++)&{if&(files[i].isDirectory())&{getFiles(files[i].getAbsolutePath());}&else&{if&(files[i].getAbsolutePath().endsWi(".3gp")||&files[i].getAbsolutePath().endsWith(".mp4"))&{list.add(files[i].toString());System.out.println(files[i].toString());}}}}&catch&(Exception&e)&{Log.d("getfile",&"查找成功!");}}}
------Solutions------
播放下一个之前,把mediaplayer的对象stop()&&release(),这样再试试呢?貌似播完一个,直接setDataSource()是不行的。
------Solutions------
我今天才实现了这个功能。不过我是用VideoView控件做的。。你已经继承了&OnCompletionListener,为什么添加监听器的时候,还要自己new一个呢。
------Solutions------
引用&4&楼&&的回复:我今天才实现了这个功能。不过我是用VideoView控件做的。。你已经继承了&OnCompletionListener,为什么添加监听器的时候,还要自己new一个呢。你这样的话,这个方法是不会执行的,只会执行你添加的那个监听器的onCompletion方法。public&void&onCompletion(MediaPlayer&mp)&{//&TODO&Auto-generated&method&stub//&mp.seekTo(0);mp.start();}
------Solutions------
问题找到了,就是一个同步和一般的准备问题。Android 视频开发
Android 视频开发
16:40北大青鸟锦江天府学院
[导读] 在Android中,我们有三种方式来实现视频的播放: 1、使用其自带的播放器。指定Action为ACTION_VIEW,Data为Uri,Type为其MIME类型。 2、使用VideoView来播放。在布局文件中使用VideoView结合MediaCo
在Android中,我们有三种方式来实现视频的播放:
1、使用其自带的播放器。指定Action为ACTION_VIEW,Data为Uri,Type为其MIME类型。
2、使用VideoView来播放。在布局文件中使用VideoView结合MediaController来实现对其控制。
3、使用MediaPlayer类和SurfaceView来实现,这种方式很灵活。
1、调用其自带的播放器:
Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()+&/Test_Movie.m4v&);
&&&&Intent intent = new Intent(Intent.ACTION_VIEW);
&&&&Log.v(&URI:::::::::&, uri.toString());
&&&&intent.setDataAndType(uri, &video/mp4&);
&&&&startActivity(intent);&
2、使用VideoView来实现:
Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()+&/Test_Movie.m4v&);
VideoView videoView = (VideoView)this.findViewById(R.id.video_view);
videoView.setMediaController(new MediaController(this));
videoView.setVideoURI(uri);
videoView.start();
videoView.requestFocus();
3.使用MediaPlayer
package demo.
import java.io.IOE
import android.app.A
import android.media.MediaP
import android.media.MediaPlayer.OnCompletionL
import android.media.MediaPlayer.OnErrorL
import android.media.MediaPlayer.OnInfoL
import android.media.MediaPlayer.OnPreparedL
import android.media.MediaPlayer.OnSeekCompleteL
import android.media.MediaPlayer.OnVideoSizeChangedL
import android.os.B
import android.os.E
import android.util.L
import android.view.D
import android.view.SurfaceH
import android.view.SurfaceV
import android.widget.LinearL
public class VideoSurfaceDemo extends Activity implements OnCompletionListener,OnErrorListener,OnInfoListener,
&&&&OnPreparedListener, OnSeekCompleteListener,OnVideoSizeChangedListener,SurfaceHolder.Callback{
&&&&private Display currD
&&&&private SurfaceView surfaceV
&&&&private SurfaceH
&&&&private MediaP
&&&&private int vWidth,vH
&&&&public void onCreate(Bundle savedInstanceState){
&&&&&&&&super.onCreate(savedInstanceState);
&&&&&&&&this.setContentView(R.layout.video_surface);&
&&&&&&&&surfaceView = (SurfaceView)this.findViewById(R.id.video_surface);
&&&&&&&&holder = surfaceView.getHolder();
&&&&&&&&holder.addCallback(this);
&&&&&&&&holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);&
&&&&&&&&player = new MediaPlayer();
&&&&&&&&player.setOnCompletionListener(this);
&&&&&&&&player.setOnErrorListener(this);
&&&&&&&&player.setOnInfoListener(this);
&&&&&&&&player.setOnPreparedListener(this);
&&&&&&&&player.setOnSeekCompleteListener(this);
&&&&&&&&player.setOnVideoSizeChangedListener(this);
&&&&&&&&Log.v(&Begin:::&, &surfaceDestroyed called&);
&&&&&&&&String dataPath = Environment.getExternalStorageDirectory().getPath()+&/Test_Movie.m4v&;
&&&&&&&&try {
&&&&&&&&&&&&player.setDataSource(dataPath);
&&&&&&&&&&&&Log.v(&Next:::&, &surfaceDestroyed called&);
&&&&&&&&} catch (IllegalArgumentException e) {
&&&&&&&&&&&&e.printStackTrace();
&&&&&&&&} catch (IllegalStateException e) {
&&&&&&&&&&&&e.printStackTrace();
&&&&&&&&} catch (IOException e) {
&&&&&&&&&&&&e.printStackTrace();
&&&&&&&&currDisplay = this.getWindowManager().getDefaultDisplay();
&&&&@Override
&&&&public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
&&&&&&&&Log.v(&Surface Change:::&, &surfaceChanged called&);
&&&&@Override
&&&&public void surfaceCreated(SurfaceHolder holder) {
&&&&&&&&player.setDisplay(holder);
&&&&&&&&player.prepareAsync();&
&&&&@Override
&&&&public void surfaceDestroyed(SurfaceHolder holder) {&
&&&&&&&&Log.v(&Surface Destory:::&, &surfaceDestroyed called&);
&&&&@Override
&&&&public void onVideoSizeChanged(MediaPlayer arg0, int arg1, int arg2) {
&&&&&&&&Log.v(&Video Size Change&, &onVideoSizeChanged called&);&
&&&&@Override
&&&&public void onSeekComplete(MediaPlayer arg0) {
&&&&&&&&Log.v(&Seek Completion&, &onSeekComplete called&);&
&&&&@Override
&&&&public void onPrepared(MediaPlayer player) {
&&&&&&&&vWidth = player.getVideoWidth();
&&&&&&&&vHeight = player.getVideoHeight();&
&&&&&&&&if(vWidth & currDisplay.getWidth() || vHeight & currDisplay.getHeight()){
&&&&&&&&&&&&
&&&&&&&&&&&&float wRatio = (float)vWidth/(float)currDisplay.getWidth();
&&&&&&&&&&&&float hRatio = (float)vHeight/(float)currDisplay.getHeight();&
&&&&&&&&&&&&
&&&&&&&&&&&&float ratio = Math.max(wRatio, hRatio);&
&&&&&&&&&&&&vWidth = (int)Math.ceil((float)vWidth/ratio);
&&&&&&&&&&&&vHeight = (int)Math.ceil((float)vHeight/ratio);&
&&&&&&&&&&&&
&&&&&&&&&&&&surfaceView.setLayoutParams(new LinearLayout.LayoutParams(vWidth, vHeight));&
&&&&&&&&&&&&
&&&&&&&&&&&&player.start();
&&&&@Override
&&&&public boolean onInfo(MediaPlayer player, int whatInfo, int extra) {
&&&&&&&&switch(whatInfo){
&&&&&&&&case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING:
&&&&&&&&&&&&break;
&&&&&&&&case MediaPlayer.MEDIA_INFO_METADATA_UPDATE:
&&&&&&&&&&&&break;
&&&&&&&&case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:
&&&&&&&&&&&&break;
&&&&&&&&case MediaPlayer.MEDIA_INFO_NOT_SEEKABLE:
&&&&&&&&&&&&break;
&&&&&&&&return false;
&&&&@Override
&&&&public boolean onError(MediaPlayer player, int whatError, int extra) {
&&&&&&&&Log.v(&Play Error:::&, &onError called&);
&&&&&&&&switch (whatError) {
&&&&&&&&case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
&&&&&&&&&&&&Log.v(&Play Error:::&, &MEDIA_ERROR_SERVER_DIED&);
&&&&&&&&&&&&break;
&&&&&&&&case MediaPlayer.MEDIA_ERROR_UNKNOWN:
&&&&&&&&&&&&Log.v(&Play Error:::&, &MEDIA_ERROR_UNKNOWN&);
&&&&&&&&&&&&break;
&&&&&&&&default:
&&&&&&&&&&&&break;
&&&&&&&&return false;
&&&&@Override
&&&&public void onCompletion(MediaPlayer player) {
&&&&&&&&Log.v(&Play Over:::&, &onComletion called&);
&&&&&&&&this.finish();
IT行业前景一片光明
成都北大青鸟招生简章
2+1大专直通车招生简章:
职业技能双修...
高考成绩不理想,职业教育为你延续大学梦
课程涵盖:安全运维、虚拟化工程、数据库、高级系统工程
课程涵盖:JAVA 前端 大数据 .net 数据库
理论课实战课1:1分配
&&跟着大牛的步伐,独家...
2017高考生选什么专业有前途
工资低、福利差、想转行?
刚毕业、没规划、很迷茫?
别让时光蹉跎了梦想,学技术做更好的自己!...
互联网+时代高薪职业——UI设计师
会ps,你顶多是个p图的
学UI,做高薪全能设计师
北大青鸟前端开发工程师
支持你成为一名高薪前端开发工程师
IT行业就业前景如何你造吗?做互联网营销精英,你能行吗?
先入行的都月薪过万了,你还在观望什...
相关文章推荐
大学毕业后要换工作学java可以吗?随着高校不断扩招,出现了很...
成都学电脑java如何快速入门?快速入门还是需要好的方法,特别...
成都学JAVA好还是安卓好?事实上编程语言在很多公式上都是相通...
零基础在读本科学生学JavaScript好找工作?大学毕业后重新学门技...
零基础待业大学生学Java编程有出路?一个人是否有前途不能从他...
二十多岁的大学生学Java去哪里好?俗话说,活到老学到老,古时...
成都地区学Java学费是一个什么情况?其实,现在高校学生就业也...
多少本书关于java技术,卖的是一个很遥远的记忆。处于中年时期...
2017年学Java去哪个学校比较好?我们可以在智联招聘、58同城等招...
成都的在职大学生学IT究竟好不好呢?对于在职大学生学技术的...
电话:400-680-6399Android多媒体篇
&&&&&&& 多媒体接口和娱乐、游戏等业务密切相关,灵活地采用多媒体接口,可以使应用具备更强的吸引力。
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="/***.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的示例如下:
&&&&&&&&&&&&&&&&&}

我要回帖

更多关于 android ui主线程 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信