- 第1章 Android Studio
- 第2章 AndroidManifest.xml
- 第3章 配置文件
- 第4章 UI Layout
- 第5章 Toast
- 第6章 Environment
- 第7章 Schedule 计划任务
- 第8章 Internationalization i18n with Android 国际化
- 第9章 存储
- 第10章 相机与相册
- 第11章 麦克风与录音
- 第12章 多媒体开发
- 第13章 定位
- 第14章 电话
- 第15章 消息广播
- 第16章 Service
- 第17章 NFC Near field communication
- 第18章 OkHttp - An HTTP HTTP/2 client for Android and Java applications
- 第19章 EventBus
- 第20章 设计模式
- 第21章 java.net 介绍和使用
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
12.2. VideoView 开发
12.2. VideoView 开发
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在使用完之后,无需编码回收资源。
12.2.1. 播放网络视频
加入 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 控制条
12.2.2. 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(); } }
12.2.3. 静音播放视频
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mediaPlayer) { mediaPlayer.setVolume(0f, 0f); } });
12.2.4. 更新进度条
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();
12.2.5. 完整的例子
<?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); } }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论