1.项目清单文件
2. 第一种使用系统自带或第三方播放器
3.第二种用VideoView实现视频的播放
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main2" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.videoplay.Main2Activity"> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/iv_pic" android:scaleType="fitXY" /> <ImageButton android:layout_width="100dp" android:layout_height="100dp" android:id="@+id/iv_player" android:layout_gravity="center" android:background="@drawable/timg" /> </FrameLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.example.videoplay.MyVideoView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/vv_palyer" /> <ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/pb_loading" android:layout_centerInParent="true" android:layout_gravity="center" /> <ImageButton android:layout_width="100dp" android:layout_height="100dp" android:id="@+id/ib_player" android:layout_centerInParent="true" android:background="@drawable/timg" /> </RelativeLayout> </FrameLayout>
package com.example.videoplay; import android.app.Activity; import android.content.res.Configuration; import android.graphics.Bitmap; import android.media.MediaMetadataRetriever; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.MediaController; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.Toast; import java.util.HashMap; public class Main2Activity extends Activity { /* 使用videoView播放视频 */ private MyVideoView vv_paler; private ProgressBar pb_loading; private MediaController meContro; private ImageView iv_pic; private ImageButton iv_player, ib_player; private GestureDetector detector; private int position; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); //设置网络视频的uri路径 Uri uri = Uri.parse("http://7sbsl4.com1.z0.glb.clouddn.com/gogogo.mp4"); vv_paler = (MyVideoView) findViewById(R.id.vv_palyer); pb_loading = (ProgressBar) findViewById(R.id.pb_loading); iv_pic = (ImageView) findViewById(R.id.iv_pic); iv_player = (ImageButton) findViewById(R.id.iv_player); ib_player = (ImageButton) findViewById(R.id.ib_player); iv_player.setVisibility(View.VISIBLE); vv_paler.setVisibility(View.GONE); iv_pic.setVisibility(View.VISIBLE); ib_player.setVisibility(View.GONE); pb_loading.setVisibility(View.GONE); //设置播放预览图 //MediaMetadataRetriever类提供了一个统一的接口用于从一个输入媒体文件中取得帧和元数据。 MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.setDataSource("http://7sbsl4.com1.z0.glb.clouddn.com/gogogo.mp4", new HashMap<String, String>()); //获取第一帧图片 Bitmap bitmap = retriever.getFrameAtTime(); iv_pic.setImageBitmap(bitmap); retriever.release(); //设置播放预览图 vv_paler.setVideoURI(uri); //初始化控制条 meContro = new MediaController(this); // meContro=new MyMediaController(this); meContro.show(0); vv_paler.setMediaController(meContro); //设置播放完成以后的监听 vv_paler.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { } }); //设置播放发生错误时的监听 vv_paler.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { return false; } }); //设置文件加载完成后的监听 vv_paler.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { pb_loading.setVisibility(View.GONE); } }); //设置videoview的单击监听和双击监听 vv_paler.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (detector == null) { detector = new GestureDetector(Main2Activity.this, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDown(MotionEvent e) { //返回false的话只能响应长摁事件 return true; } @Override public void onLongPress(MotionEvent e) { //长摁事件 super.onLongPress(e); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { //滑动事件 return super.onScroll(e1, e2, distanceX, distanceY); } }); detector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() { @Override public boolean onSingleTapConfirmed(MotionEvent e) { //单击事件 //单击暂停播放视频 switch (vv_paler.getState()) { case 1: //当前处于暂停状态 ib_player.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { vv_paler.setVisibility(View.VISIBLE); vv_paler.start(); ib_player.setVisibility(View.GONE); vv_paler.setFocusable(true); } }); break; case 2: //当前处于播放状态 vv_paler.pause(); ib_player.setVisibility(View.VISIBLE); break; } return true; } @Override public boolean onDoubleTap(MotionEvent e) { //双击事件 //设置双击实现全屏播放视频 setFillLayoutPlay(); Toast.makeText(Main2Activity.this, "双击监听了", Toast.LENGTH_SHORT).show(); return true; } @Override public boolean onDoubleTapEvent(MotionEvent e) { return false; } }); } return detector.onTouchEvent(event); } }); //点击播放按钮 iv_player.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { iv_pic.setVisibility(View.GONE); vv_paler.setVisibility(View.VISIBLE); pb_loading.setVisibility(View.VISIBLE); vv_paler.start(); vv_paler.setFocusable(true); iv_player.setVisibility(View.GONE); } }); } /* 双击实现全屏播放视频 */ private void setFillLayoutPlay() { ViewGroup.LayoutParams params = vv_paler.getLayoutParams(); params.height = RelativeLayout.LayoutParams.MATCH_PARENT; params.width = RelativeLayout.LayoutParams.MATCH_PARENT; vv_paler.setLayoutParams(params); vv_paler.setFocusable(true); } @Override protected void onPause() { super.onPause(); //如果当前页面暂停则保存当前的播放位置 position = vv_paler.getCurrentPosition(); //停止回放视频 vv_paler.stopPlayback(); } /* 当再次进入播放页面时 */ @Override protected void onResume() { super.onResume(); if (position > 0) { vv_paler.seekTo(position); position = -1; ib_player.setVisibility(View.VISIBLE); } } //当屏幕方向发生转变时 @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); int rot = getWindowManager().getDefaultDisplay().getRotation(); Log.i("show", "rot:" + rot); if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { ViewGroup.LayoutParams params = vv_paler.getLayoutParams(); params.height = RelativeLayout.LayoutParams.MATCH_PARENT; params.width = RelativeLayout.LayoutParams.MATCH_PARENT; vv_paler.setLayoutParams(params); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } else if (rot == Surface.ROTATION_0) { RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(320, 240); lp.addRule(RelativeLayout.CENTER_IN_PARENT); vv_paler.setLayoutParams(vv_paler.getLayoutParams()); } } @Override protected void onDestroy() { super.onDestroy(); } }
package com.example.videoplay; import android.content.Context; import android.util.AttributeSet; import android.widget.VideoView; /** * 自定义VideoView类实现对视频播放状态的监听 * Created by admin on 2017/2/13. */ public class MyVideoView extends VideoView { private int state; public final int ON_PAUSE=1; public final int ON_PLAY=2; public int getState() { return state; } public void setState(int state) { this.state = state; } public MyVideoView(Context context) { super(context); } public MyVideoView(Context context, AttributeSet attrs) { super(context, attrs); } public MyVideoView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public void pause() { super.pause(); state=ON_PAUSE; } @Override public void start() { super.start(); state=ON_PLAY; } }
4、第三种,surfaceView+mediaplayer实现视频的播放,以及弹幕
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main3" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.videoplay.Main3Activity"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <SurfaceView android:layout_width="match_parent" android:layout_height="200dp" android:id="@+id/sv" /> <ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:id="@+id/pb" /> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#88000000" android:gravity="center_vertical" android:paddingLeft="5dp" android:paddingRight="5dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/bt_pause" android:text="暂停" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/bt_replay" android:layout_toRightOf="@+id/bt_pause" android:text="重播" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/bt_screeshot" android:text="播放" android:layout_toRightOf="@+id/bt_replay" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/bt_fillscree" android:text=" 全屏" android:layout_toRightOf="@+id/bt_screeshot" /> <SeekBar android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/sb" android:layout_alignParentLeft="true" android:layout_below="@+id/bt_replay" android:layout_toLeftOf="@+id/tv" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tv" android:layout_alignParentRight="true" android:textColor="#ffffff" android:layout_below="@+id/bt_replay" android:layout_centerVertical="true" android:text="222222" /> </RelativeLayout> <master.flame.danmaku.ui.widget.DanmakuView android:id="@+id/danmaku_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:id="@+id/ll" android:orientation="horizontal" android:layout_alignParentBottom="true" android:layout_marginBottom="100dp" android:background="#ff0000" android:visibility="visible" > <EditText android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:id="@+id/et" /> <Button android:layout_width="wrap_content" android:layout_height="match_parent" android:text="发送弹幕" android:id="@+id/btSend" /> </LinearLayout> </RelativeLayout>
package com.example.videoplay;
import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Random;
import master.flame.danmaku.controller.DrawHandler;
import master.flame.danmaku.danmaku.model.BaseDanmaku;
import master.flame.danmaku.danmaku.model.DanmakuTimer;
import master.flame.danmaku.danmaku.model.IDanmakus;
import master.flame.danmaku.danmaku.model.android.DanmakuContext;
import master.flame.danmaku.danmaku.model.android.Danmakus;
import master.flame.danmaku.danmaku.parser.BaseDanmakuParser;
import master.flame.danmaku.ui.widget.DanmakuView;
public class Main3Activity extends Activity implements View.OnClickListener {
/*
使用surfaceview+mediaplayer 进行实现视频播放
*/
private int position;
private SurfaceView sv;
private ProgressBar pb;
private SeekBar sb;
private TextView tv;
private Button bt_replay, bt_pause, bt_cressshot, bt_fillscree;
private SurfaceHolder surfholder;
private MediaPlayer mediaplayer;
private String totalTime;
private boolean seekBarAutoFlag = false;
//实现弹幕效果
private boolean showDanView;
private DanmakuView danView;
private DanmakuContext danContext;
private EditText et;
private Button bt_send;
private LinearLayout ll;
private BaseDanmakuParser parse=new BaseDanmakuParser() {
@Override
protected IDanmakus parse() {
return new Danmakus();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//去除标题栏
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main3);
et= (EditText) findViewById(R.id.et);
bt_send= (Button) findViewById(R.id.btSend);
ll= (LinearLayout) findViewById(R.id.ll);
bt_send.setOnClickListener(this);
danView= (DanmakuView) findViewById(R.id.danmaku_view);
sv = (SurfaceView) findViewById(R.id.sv);
pb = (ProgressBar) findViewById(R.id.pb);
sb = (SeekBar) findViewById(R.id.sb);
tv = (TextView) findViewById(R.id.tv);
bt_pause = (Button) findViewById(R.id.bt_pause);
bt_replay = (Button) findViewById(R.id.bt_replay);
bt_cressshot = (Button) findViewById(R.id.bt_screeshot);
bt_fillscree = (Button) findViewById(R.id.bt_fillscree);
bt_pause.setOnClickListener(this);
bt_fillscree.setOnClickListener(this);
bt_cressshot.setOnClickListener(this);
bt_replay.setOnClickListener(this);
//设置SurfaceHolder
surfholder = sv.getHolder();
//设置hodler的类型,该类型表示surfaceview自己不管理缓存区
surfholder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
//设置surfcace的回调
surfholder.addCallback(new SurfaceHolder.Callback() {
/*
surfaceview被创建
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
//播放视频
palyVideo();
Log.i("show","surfaceView:created");
}
/*
Surfaceview大小的改变
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.i("show","surfaceView:surfaceChanged");
}
/*
SurfaceView被销毁
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//当surfaceview被销毁的时候,将mediaplayer也一并销毁
if (null != mediaplayer) {
mediaplayer.release();
mediaplayer = null;
}
Log.i("show","surfaceView:destroyed");
}
});
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
if(visibility==View.SYSTEM_UI_FLAG_VISIBLE){
onWindowFocusChanged(true);
}
}
});
}
//随机生成一些弹幕内容测试
private void generateSomeMessage() {
new Thread(){
@Override
public void run() {
while (showDanView){
int time=new Random().nextInt(300);
String content=""+time+time;
addDan(content,false);
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
/*
向屏幕中添加一条弹幕信息
@param content (弹幕内容),b(弹幕是否有边框)
*/
private void addDan(String content, boolean b) {
BaseDanmaku danku=danContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_LR);
danku.text=content;
danku.padding=5;
danku.textSize=spTopx(20);
danku.textColor= Color.GREEN;
danku.setTime(danView.getCurrentTime());
if(b){
danku.borderColor=Color.WHITE;
}
danView.addDanmaku(danku);
}
/*
sp转px
*/
public int spTopx(float sp){
float fontScale = getResources().getDisplayMetrics().scaledDensity;
return (int) (sp*fontScale+0.5f);
}
private void palyVideo() {
//设置网络视频的uri路径
Uri uri = Uri.parse("http://7sbsl4.com1.z0.glb.clouddn.com/gogogo.mp4
"); mediaplayer = new MediaPlayer(); mediaplayer.reset(); try { mediaplayer.setDataSource(Main3Activity.this, uri); //设置异步加载视频,包括两种方式,prepare()同步,parepareAsync()异步 mediaplayer.prepareAsync(); } catch (IOException e) { e.printStackTrace(); } //设置声音效果 mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC); //播放完成后的监听 mediaplayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { } }); //设置媒体文件加载完成后的监听 mediaplayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { //当视频加载完成后,隐藏加载进度条 pb.setVisibility(View.GONE); //判断是否有保存的播放位置,防止屏幕旋转时,界面被构建,播放位置丢失 if (position > 0) { mediaplayer.seekTo(position); position = -1;} mediaplayer.start(); //设置显示到屏幕上 mediaplayer.setDisplay(surfholder); //设置surfaceview保持在屏幕上 mediaplayer.setScreenOnWhilePlaying(true); surfholder.setKeepScreenOn(true); //设置进度条 sb.setProgress(0); sb.setMax(mediaplayer.getDuration()); //设置播放时间的显示 totalTime = getShowTime(mediaplayer.getDuration()); tv.setText("00:00:00" + totalTime); //设置拖动seekbar的监听事件 sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if(progress>0){ if(fromUser){ mediaplayer.seekTo(progress); } tv.setText(getShowTime(progress)+"/"+totalTime); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); seekBarAutoFlag = true; //开启子线程,刷新进度条 if(!thread.isAlive()){ thread.start(); } //开启弹幕 danView.enableDanmakuDrawingCache(true); danContext=DanmakuContext.create(); danView.prepare(parse,danContext); danView.setCallback(new DrawHandler.Callback() { @Override public void prepared() { showDanView=true; danView.start(); //随机生成一些弹幕内容测试 generateSomeMessage(); } @Override public void updateTimer(DanmakuTimer timer) { } @Override public void danmakuShown(BaseDanmaku danmaku) { } @Override public void drawingFinished() { } }); } }); //设置播放发生错误后的监听 mediaplayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { return false; } }); //设置缓存变化的监听 mediaplayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { @Override public void onBufferingUpdate(MediaPlayer mp, int percent) { } }); } //开启子线程,刷新进度条 Thread thread = new Thread() { @Override public void run() { super.run(); while (seekBarAutoFlag) { if(mediaplayer!=null&&mediaplayer.isPlaying()){ sb.setProgress(mediaplayer.getCurrentPosition()); } } } }; //设置按键的监听 @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt_pause://暂停 mediaplayer.pause(); break; case R.id.bt_replay://重播 position=0; mediaplayer.seekTo(0); mediaplayer.start(); break; case R.id.bt_fillscree://全屏 ViewGroup.LayoutParams params = sv.getLayoutParams(); params.height= RelativeLayout.LayoutParams.MATCH_PARENT; sv.setLayoutParams(params); break; case R.id.bt_screeshot: //播放 mediaplayer.start(); break; case R.id.btSend: //发弹幕 String context=et.getText().toString(); if(!TextUtils.isEmpty(context)){ addDan(context,true); et.setText(""); } break; } } //格式化播放时间 private String getShowTime(long duration) { Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(duration); SimpleDateFormat sdf = null; //判断是否大于一小时(60分钟) if (duration / 6000 > 60) { sdf = new SimpleDateFormat("hh:mm:ss"); } else { sdf = new SimpleDateFormat("mm:ss"); } return sdf.format(calendar.getTime()); } @Override protected void onPause() { super.onPause(); /*//如果当前页面暂停则保存当前的播放位置 position = vv_paler.getCurrentPosition(); //停止回放视频 vv_paler.stopPlayback();*/ position=mediaplayer.getCurrentPosition(); mediaplayer.stop(); mediaplayer=null; if(danView!=null&&danView.isPrepared()){ danView.pause(); } Log.i("show","activityL:onPause"); } /* 当再次进入播放页面时 */ @Override protected void onResume() { super.onResume(); if(danView!=null&&danView.isPrepared()&&danView.isPaused()){ danView.resume(); } } /* 当屏幕转向发送变化时 */ @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); int rot = getWindowManager().getDefaultDisplay().getRotation(); Log.i("show", "rot:" + rot); if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { ViewGroup.LayoutParams params =sv.getLayoutParams(); params.height=RelativeLayout.LayoutParams.MATCH_PARENT; params.width=RelativeLayout.LayoutParams.MATCH_PARENT; sv.setLayoutParams(params); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } else if (rot == Surface.ROTATION_0) { ViewGroup.LayoutParams params =sv.getLayoutParams(); params.height=720; params.width=RelativeLayout.LayoutParams.MATCH_PARENT; sv.setLayoutParams(params); } } @Override protected void onDestroy() { super.onDestroy(); if(mediaplayer!=null&&danView!=null){ mediaplayer.stop(); mediaplayer.release(); mediaplayer=null; showDanView=false; danView.release(); danView=null; } thread=null; }}