版权声明:本文为博主原创文章,未经博主允许不得转载。
开发步骤:
视频播放器
1.一般视频播放器的界面是横屏的 全屏
2.准备好视频文件(暂停)
3.视频播放器=MediaPlayer播放音频+界面
4.SurfaceView Surface表皮/皮肤 双缓冲视图
java.lang.IllegalArgumentException: The surface has been released
说人话:SurfaceView被释放了--->SurfaceView压根就没有---->SurfaceView还没初始化
因为SurfaceView是用来播放视频的 在内部需要先准备一下数据 才能去播放(需要一段时间)
5.什么时候SurfaceView准备完? holder.addCallback()
6.播放的正常情况下应该有个进度条?
7.拖动之后没有效果
8.当没人去触摸界面的时候 进度条会自动隐藏掉 当再次点击屏幕的时候 进度条会出现 然后过了一会后继续隐藏
网络视频:
1.远程服务器下的视频数据在加载的时候 可能没那么快 导致了黑屏
2.出现了黑白屏(缓冲数据)---->应该在中间设置一个加载框
MediaPlayer的操作:
1.new MediaPlayer()--->IDLE空闲状态
2.设置数据源 setDataSource()
3.准备播放的数据 prepare()
4.开始播放 start()-------------------------------->正在播放视频
如果你想播放其他的音乐 但是已经有音乐在播放了--->reset() 重置播放器 释放原有资源
stop()停止
pause()暂停--->是可以恢复的--->start()
音乐播放完成--->也是可以恢复的--->start()
* 如果是网络数据 一般调用准备播放的数据 prepareAsync()
当OnPreparedListener.onPrepared()被调用的时候 说明数据就准备完毕了
* 当资源不再使用 或者说 播放器不想要了 可以调用release()去释放资源
* 为了提供用户的体验 当播放失败的时候 提醒用户 可以调用OnErrorListener.onError();
修改主题
1.一般视频播放器的界面是横屏的 全屏
2.准备好视频文件(暂停)
3.视频播放器=MediaPlayer播放音频+界面
4.SurfaceView Surface表皮/皮肤 双缓冲视图
java.lang.IllegalArgumentException: The surface has been released
说人话:SurfaceView被释放了--->SurfaceView压根就没有---->SurfaceView还没初始化
因为SurfaceView是用来播放视频的 在内部需要先准备一下数据 才能去播放(需要一段时间)
5.什么时候SurfaceView准备完? holder.addCallback()
6.播放的正常情况下应该有个进度条?
7.拖动之后没有效果
8.当没人去触摸界面的时候 进度条会自动隐藏掉 当再次点击屏幕的时候 进度条会出现 然后过了一会后继续隐藏
网络视频:
1.远程服务器下的视频数据在加载的时候 可能没那么快 导致了黑屏
2.出现了黑白屏(缓冲数据)---->应该在中间设置一个加载框
MediaPlayer的操作:
1.new MediaPlayer()--->IDLE空闲状态
2.设置数据源 setDataSource()
3.准备播放的数据 prepare()
4.开始播放 start()-------------------------------->正在播放视频
如果你想播放其他的音乐 但是已经有音乐在播放了--->reset() 重置播放器 释放原有资源
stop()停止
pause()暂停--->是可以恢复的--->start()
音乐播放完成--->也是可以恢复的--->start()
* 如果是网络数据 一般调用准备播放的数据 prepareAsync()
当OnPreparedListener.onPrepared()被调用的时候 说明数据就准备完毕了
* 当资源不再使用 或者说 播放器不想要了 可以调用release()去释放资源
* 为了提供用户的体验 当播放失败的时候 提醒用户 可以调用OnErrorListener.onError();
public class MainActivity extends Activity implements OnSeekBarChangeListener,
OnTouchListener {
private MediaPlayer mMediaPlayer;
private SurfaceView mSurfaceView;
private SeekBar mVedioSkb;
protected Timer mTimer;
private Timer mVedioSkbTimer;
private ProgressBar mLoadingPb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceview);
// 给SurfaceView设置一个触摸的监听器
mSurfaceView.setOnTouchListener(this);
mLoadingPb = (ProgressBar) findViewById(R.id.loading_pb);
mVedioSkb = (SeekBar) findViewById(R.id.vedio_skb);
// 给SeekBar设置一个拖动事件的监听器
mVedioSkb.setOnSeekBarChangeListener(this);
// 过了2秒后 进度条自动隐藏
hideVedioSkbAfter2Seconds();
// SurfaceHolder管理界面播放的一个控制器
SurfaceHolder holder = mSurfaceView.getHolder();
// 给holder设置一个SurfaceView准备数据的监听器
holder.addCallback(new Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
// mSurfaceView 准备完毕的时候调用的
@Override
public void surfaceCreated(final SurfaceHolder holder) {
try {
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
// 设置网络视频数据
Uri uri = Uri.parse("http://192.168.14.130:8080/oppo.3gp");
mMediaPlayer.setDataSource(MainActivity.this, uri);
mMediaPlayer.prepareAsync();
// 异步加载数据的情况下 需要给mMediaPlayer设置一个异步准备数据的操作
// 以避免加载框转动的时候出现卡顿
mMediaPlayer
.setOnPreparedListener(new OnPreparedListener() {
// 异步准备数据完毕后 该方法就会被调用
@Override
public void onPrepared(MediaPlayer mp) {
//播放之前 需要隐藏加载框
mLoadingPb.setVisibility(View.GONE);
mMediaPlayer.start();
// 关联音频与界面
mMediaPlayer.setDisplay(holder);
// 设置进度条总进度
mVedioSkb.setMax(mMediaPlayer.getDuration());
// 创建一个定时器 设置进度条的当前进度
mTimer = new Timer();
mTimer.schedule(new TimerTask() {
// 该方法是运行在子线程中的
@Override
public void run() {
// 在子线程中调用mVedioSkb的setProgress()
// 它在内部会返回主线程操作UI
mVedioSkb.setProgress(mMediaPlayer
.getCurrentPosition());
}
}, 500, 500);
}
});
}else{
mMediaPlayer.setDisplay(holder);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
}
private void hideVedioSkbAfter2Seconds() {
mVedioSkbTimer = new Timer();
mVedioSkbTimer.schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mVedioSkb.setVisibility(View.GONE);
}
});
}
}, 2 * 1000);
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
// 在拖动完成后 首先获取SeekBar当前进度 修改视频的播放进度
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
int progress = seekBar.getProgress();
mMediaPlayer.seekTo(progress);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// 首先让mVedioSkb显示出来
mVedioSkb.setVisibility(View.VISIBLE);
// 过了2秒后再次隐藏
hideVedioSkbAfter2Seconds();
return false;
}
@Override
protected void onRestart() {
// 恢复播放
mMediaPlayer.start();
super.onRestart();
}
@Override
protected void onStop() {
// 暂停播放器,
mMediaPlayer.pause();
super.onStop();
}
/*
* 退出销毁资源
*/
@Override
protected void onDestroy() {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer=null;
super.onDestroy();
}
}
修改主题
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.m520it.httpPlayer.MainActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>