中国广东省深圳市望海路半岛城邦三期
518067
+86 13113668890
<netkiller@msn.com>
$Id: book.xml 606 2013-05-29 09:52:58Z netkiller $
版权 © 2018 Neo Chan
版权声明
转载请与作者联系,转载时请务必标明文章原始出处和作者信息及本声明。
2018-10
我的系列文档
编程语言
Netkiller Architect 手札 | Netkiller Developer 手札 | Netkiller Java 手札 | Netkiller Spring 手札 | Netkiller PHP 手札 | Netkiller Python 手札 |
---|---|---|---|---|---|
Netkiller Testing 手札 | Netkiller Cryptography 手札 | Netkiller Perl 手札 | Netkiller Docbook 手札 | Netkiller Project 手札 | Netkiller Database 手札 |
VideoView,用于播放一段视频媒体,它继承了SurfaceView,位于"android.widget.VideoView",是一个视频控件。
VideoView也为开发人员提供了对应的方法,这里简单介绍一些常用的:
int getCurrentPosition():获取当前播放的位置。
int getDuration():获取当前播放视频的总长度。
isPlaying():当前VideoView是否在播放视频。
void pause():暂停
void seekTo(int msec):从第几毫秒开始播放。
void resume():重新播放。
void setVideoPath(String path):以文件路径的方式设置VideoView播放的视频源。
void setVideoURI(Uri uri):以Uri的方式设置VideoView播放的视频源,可以是网络Uri或本地Uri。
void start():开始播放。
void stopPlayback():停止播放。
setMediaController(MediaController controller):设置MediaController控制器。
setOnCompletionListener(MediaPlayer.onCompletionListener l):监听播放完成的事件。
setOnErrorListener(MediaPlayer.OnErrorListener l):监听播放发生错误时候的事件。
setOnPreparedListener(MediaPlayer.OnPreparedListener l)::监听视频装载完成的事件。
上面的一些方法通过方法名就可以了解用途。和MediaPlayer配合SurfaceView播放视频不同,VideoView播放之前无需编码装载视频,它会在start()开始播放的时候自动装载视频。并且VideoView在使用完之后,无需编码回收资源。
加入 android.permission.INTERNET 允许访问网络
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.netkiller.video">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".VideoViewActivity"></activity>
</application>
</manifest>
最简洁的布局,只有一个 VideoView
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".VideoViewActivity">
<VideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="236dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
播放的文件来自 IPFS 星际文件系统
package cn.netkiller.video;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.MediaController;
import android.widget.VideoView;
public class VideoViewActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_view);
Uri uri = Uri.parse("http://ipfs.netkiller.cn/ipfs/QmcA1Fsrt6jGTVqAUNZBqaprMEdFaFkmkzA5s2M6mF85UC");
VideoView videoView = (VideoView) this.findViewById(R.id.videoView);
videoView.setMediaController(new MediaController(this));
videoView.setVideoURI(uri);
videoView.start();
videoView.requestFocus();
}
}
运行程序开始播放视频,点击视频会在屏幕下方弹出 MediaController 控制条
package cn.netkiller.video;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.VideoView;
public class VideoViewActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_view);
final Uri uri = Uri.parse("http://ipfs.netkiller.cn/ipfs/QmcA1Fsrt6jGTVqAUNZBqaprMEdFaFkmkzA5s2M6mF85UC");
final VideoView videoView = (VideoView) this.findViewById(R.id.videoView);
MediaController mediaController = new MediaController(this);
mediaController.setMediaPlayer(videoView);
mediaController.setPrevNextListeners(
new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(VideoViewActivity.this, "下一曲", Toast.LENGTH_SHORT).show();
videoView.setVideoURI(Uri.parse("http://ipfs.netkiller.cn/ipfs/QmUaDftnPB7zCTwTASnSAWLiXWd1L5vNGEeU585rddfVTh"));
}
},
new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(VideoViewActivity.this, "上一曲", Toast.LENGTH_SHORT).show();
videoView.setVideoURI(Uri.parse("http://ipfs.netkiller.cn/ipfs/QmbvKvj9X368WMtmkLYFuf59gSwLXYDLcdJuSiSHKPhTG4"));
}
});
videoView.setMediaController(mediaController);
videoView.setVideoURI(uri);
videoView.start();
videoView.requestFocus();
}
}
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.setVolume(0f, 0f);
}
});
new Thread() {
@Override
public void run() {
try {
while (videoView.isPlaying()) {
// 如果正在播放,没0.5.毫秒更新一次进度条
int current = videoView.getCurrentPosition();
seekBar.setProgress(current);
sleep(500);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".VideoViewActivity">
<VideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="236dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/textViewTime"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="00:00" />
<SeekBar
android:id="@+id/seekBar"
android:layout_width="270dp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textViewCurrentPosition"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="00:00" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/buttonPlay"
android:layout_width="183dp"
android:layout_height="wrap_content"
android:text="播放" />
<Button
android:id="@+id/buttonStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="停止" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/textViewStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text=" "
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/videoView" />
</android.support.constraint.ConstraintLayout>
package cn.netkiller.video;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class VideoViewActivity extends AppCompatActivity implements View.OnClickListener {
private VideoView videoView;
private SeekBar seekBar;
private Button buttonPlay;
private TextView textViewTime;
private TextView textViewCurrentPosition;
private TextView textViewStatus;
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
public void run() {
if (videoView.isPlaying()) {
int current = videoView.getCurrentPosition();
seekBar.setProgress(current);
textViewCurrentPosition.setText(time(videoView.getCurrentPosition()));
}
handler.postDelayed(runnable, 500);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_view);
final Uri uri = Uri.parse("http://ipfs.netkiller.cn/ipfs/QmcA1Fsrt6jGTVqAUNZBqaprMEdFaFkmkzA5s2M6mF85UC");
videoView = (VideoView) this.findViewById(R.id.videoView);
videoView.setVideoURI(uri);
videoView.requestFocus();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
textViewTime.setText(time(videoView.getDuration()));
textViewStatus.setText("视频加载完毕");
buttonPlay.setEnabled(true);
}
});
// 在播放完毕被回调
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Toast.makeText(VideoViewActivity.this, "播放完成", Toast.LENGTH_SHORT).show();
}
});
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// 发生错误重新播放
play();
Toast.makeText(VideoViewActivity.this, "播放出错", Toast.LENGTH_SHORT).show();
return false;
}
});
textViewStatus = (TextView) findViewById(R.id.textViewStatus);
textViewStatus.setText("玩命加载中");
textViewTime = (TextView) findViewById(R.id.textViewTime);
seekBar = (SeekBar) findViewById(R.id.seekBar);
// 为进度条添加进度更改事件
seekBar.setOnSeekBarChangeListener(onSeekBarChangeListener);
textViewCurrentPosition = (TextView) findViewById(R.id.textViewCurrentPosition);
buttonPlay = (Button) findViewById(R.id.buttonPlay);
buttonPlay.setEnabled(false);
final Button buttonStop = (Button) findViewById(R.id.buttonStop);
buttonPlay.setOnClickListener(this);
buttonStop.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.buttonPlay:
play();
break;
case R.id.buttonStop:
stop();
break;
default:
break;
}
}
private SeekBar.OnSeekBarChangeListener onSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
// 当进度条停止修改的时候触发
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// 取得当前进度条的刻度
int progress = seekBar.getProgress();
if (videoView.isPlaying()) {
// 设置当前播放的位置
videoView.seekTo(progress);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
}
};
protected void play() {
if (buttonPlay.getText().equals("播放")) {
buttonPlay.setText("暂停");
textViewStatus.setText("请您欣赏");
// 开始线程,更新进度条的刻度
handler.postDelayed(runnable, 0);
videoView.start();
seekBar.setMax(videoView.getDuration());
} else
{
buttonPlay.setText("播放");
if (videoView.isPlaying()) {
videoView.pause();
}
}
}
protected void stop() {
if (videoView.isPlaying()) {
videoView.stopPlayback();
}
}
protected String time(long millionSeconds) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("mm:ss");
Calendar c = Calendar.getInstance();
c.setTimeInMillis(millionSeconds);
return simpleDateFormat.format(c.getTime());
}
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(runnable);
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。