其实就是一个简单的视频和音频播放小程序! 先看截图:
本程序是根据网上一个示例更改的: 上面链接文档中的程序是无法直接(在Android2.3上)执行的,会提示一个:getVideoHeight failed 错误! 如果通过注释的方法忽略该错误,将会导致音频和视频的进度条无法实时更新;于是本示例抛弃了原文档中的定时器(mTimerTask)控制方法,改用成多线程进行更新。 下面来看源代码吧,首先是布局文件main.xml:
主要就是使用了线性布局(LinearLayout)的嵌套,其它也没什么特别的。
然后是AndroidManifest.xml文件,需要添加一个强制竖屏的设置,因为要是允许了重力感应,多媒体的进度条将会变得无法控制。只需在<activity>标签中添加:android:launchMode="singleTask" android:screenOrientation="portrait"
因为强制设置了竖屏显示,所以布局中<SurfaceView>的高度定义可以根据自己的视频实际尺寸计算一下,免得比例失真!
关于横屏、竖屏、全屏的设置可以参看: 最后就是主程序文件Mplayer.java了:package com.ucrobotics.mplayer; import java.io.IOException; import android.app.Activity; import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Button; import android.widget.SeekBar; import android.widget.Toast; public class Mplayer extends Activity { /** Called when the activity is first created. */ private SeekBar skb_audio=null; private Button btn_start_audio = null; private Button btn_stop_audio = null; private SeekBar skb_video=null; private Button btn_start_video = null; private Button btn_stop_video = null; private SurfaceView surfaceView; private SurfaceHolder surfaceHolder; private MediaPlayer m = null; private String mp3Path = "/sdcard/Music/Young_For_You.mp3"; private String mp4Path = "/sdcard/Video/mv.mp4"; private boolean isVideo=false; private boolean isAudio=false; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //----------Media控件设置---------// m=new MediaPlayer(); //播放结束后释放MediaPlayer m.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){ public void onCompletion(MediaPlayer arg0) { //Toast.makeText(Mplayer.this, "结束", Toast.LENGTH_LONG).show(); m.release(); } }); btn_start_audio = (Button) this.findViewById(R.id.Button01); btn_stop_audio = (Button) this.findViewById(R.id.Button02); btn_start_audio.setOnClickListener(new ClickEvent()); btn_stop_audio.setOnClickListener(new ClickEvent()); skb_audio=(SeekBar)this.findViewById(R.id.SeekBar01); skb_audio.setOnSeekBarChangeListener(new SeekBarChangeEvent()); btn_start_video = (Button) this.findViewById(R.id.Button03); btn_stop_video = (Button) this.findViewById(R.id.Button04); btn_start_video.setOnClickListener(new ClickEvent()); btn_stop_video.setOnClickListener(new ClickEvent()); skb_video=(SeekBar)this.findViewById(R.id.SeekBar02); skb_video.setOnSeekBarChangeListener(new SeekBarChangeEvent()); surfaceView = (SurfaceView) findViewById(R.id.SurfaceView01); surfaceHolder = surfaceView.getHolder(); //surfaceHolder.setFixedSize(100, 100); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } /* * 按键事件处理 */ class ClickEvent implements View.OnClickListener{ public void onClick(View v) { if(v==btn_start_audio) { //设置audio或video标记,以便控制各自的进度条变化 isAudio = true; isVideo = false; //恢复到未初始化的状态 m.reset(); //有两种方式获取资源文件:从工程的resource目录,或是指定路径;鉴于文件比较大,所以本示例均是从SD卡获取 //m=MediaPlayer.create(TestPlayer.this, R.raw.big);//读取音频 m=MediaPlayer.create(Mplayer.this, Uri.parse("file://" + mp3Path)); //设置SeekBar的长度 skb_audio.setMax(m.getDuration()); //每次播放都将进度条重置为0 skb_audio.setProgress(0); try { m.prepare(); //准备 } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } m.start(); //播放 //启动一个新线程用于更新音频的进度条 aseekth as = new aseekth(); as.start(); } else if(v==btn_stop_audio) { try{ m.stop(); isAudio = false; } catch (Exception e) { } } else if(v==btn_stop_video) { try{ m.stop(); isVideo = false; } catch (Exception e) { } } else if(v==btn_start_video) { isVideo = true; isAudio = false; m.reset(); //m=MediaPlayer.create(TestPlayer.this, R.raw.test);//读取视频 m=MediaPlayer.create(Mplayer.this, Uri.parse("file://" + mp4Path)); //设置SeekBar的长度 skb_video.setMax(m.getDuration()); //每次播放都将进度条重置为0 skb_video.setProgress(0); m.setAudioStreamType(AudioManager.STREAM_MUSIC); m.setDisplay(surfaceHolder);//设置屏幕 try { m.prepare(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } m.start(); //启动一个新线程用于更新视频的进度条 vseekth vs = new vseekth(); vs.start(); } } } /* * SeekBar进度改变事件 */ class SeekBarChangeEvent implements SeekBar.OnSeekBarChangeListener{ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } public void onStartTrackingTouch(SeekBar seekBar) { } public void onStopTrackingTouch(SeekBar seekBar) { m.seekTo(seekBar.getProgress()); } } /* * 音频进度条线程处理 */ private class aseekth extends Thread { public void run() { try { while(isAudio){ if(skb_audio.getProgress() < m.getCurrentPosition()){ skb_audio.setProgress(m.getCurrentPosition()); sleep(10); } } } catch (Exception e) { } } } /* * 视频进度条线程处理 */ private class vseekth extends Thread { public void run() { try { while(isVideo){ if(skb_video.getProgress() < m.getDuration()){ skb_video.setProgress(m.getCurrentPosition()); sleep(10); } } } catch (Exception e) { } } } }