由于做资讯类的app,所以涉及到的与h5交互的情况比较多。。。由于项目以前用的是优酷的视频外链。app可以直接用webview 来播放,优酷那边已经做过处理。所以webview那儿可以直接播放。但是现在视屏都上传自己服务器,资讯视屏也用h5原生的。导致app端无法全屏播放视频。网上也有很多方法来解决不是全屏问题,但是曲线救国,有点。。。不予评论。。。
于是乎,决定自己写个简易播放器来全屏播放,一般有三种方式,1。直接用系统的播放器。2.用videoview+mediacontroller 来播放。3.用sufaceview+mediacontroller
由于需要纪录播放进度。所以第一种直接弃用,开发时间有限,所以就决定 用第二种。第三种方法适合定制性比较高。功能比较齐全的。但是相对复杂的,我也尝试过
只是做了简单的播放处理。关于第三种,网上有的博客忘记写了, 就是 media 发起异步准备的时候,一定要在onPrepared准备的方法里 start一下,否则无法播放。
在此 其他的不做过多的叙述,视屏链接如何获取也不予详细说明。网上有很多种。我的大致思路就是与h5开发人员 约定一个 超链接。我用webview 的方法截取超
链接。来解析获取url。
接下来,请欣赏核心代码 简易 视屏播放器。大神请绕道。思路是 这样的,(因为22版本sdk进度条特别的。。那啥。23版本的还阔以,但是项目的 build版本22 没办法,所以决定,设置控制器后,隐藏掉它自己的显示界面,自定义自己的控制器,加监听。加功能)
布局文件 很简单。
简易布局
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.myapplication.MainActivity"> android:id="@+id/vv" android:layout_width="match_parent" android:layout_height="match_parent" /> android:id="@+id/video_title_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:gravity="center" android:orientation="horizontal" android:padding="5dp"> android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:text="back" android:textColor="#666" /> android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:layout_weight="1" android:text="这是视屏的名称" android:textColor="#666" /> android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:text="下载" android:textColor="#666" /> android:id="@+id/video_ll" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:orientation="horizontal"> android:id="@+id/play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="10dp" android:gravity="center" android:text="暂停" android:textColor="#eee" android:textSize="16sp" /> android:id="@+id/now_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="00:00" /> android:id="@+id/video_seek_bar" android:layout_width="wrap_content" android:layout_height="20dp" android:layout_marginBottom="20dp" android:layout_weight="1" android:maxHeight="10dp" android:minHeight="10dp" /> android:id="@+id/total_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="00:00" />
下面是java核心代码。超级简单。。
public class MainActivity extends Activity implements View.OnClickListener, SeekBar.OnSeekBarChangeListener, MediaPlayer.OnCompletionListener { CustomVideoView videoView; Timer timer = new Timer(); MediaController m; SeekBar seekBar; TextView play, now_time, total_time; LinearLayout video_title_name, video_ll; ViewGroup.LayoutParams mVideoViewLayoutParams; RelativeLayout voide_layout; Uri uri; @Override protected void onCreate(Bundle savedInstanceState) { this.requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏 this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//去掉信息栏 Window window = getWindow(); WindowManager.LayoutParams params = window.getAttributes(); params.systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE; window.setAttributes(params); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initDatas(); initViews(); } private void initViews() { videoView = (CustomVideoView) findViewById(R.id.vv); videoView.setVideoURI(uri); seekBar = (SeekBar) this.findViewById(R.id.video_seek_bar); video_title_name = (LinearLayout) this.findViewById(R.id.video_title_name); video_ll = (LinearLayout) this.findViewById(R.id.video_ll); play = (TextView) this.findViewById(R.id.play); now_time = (TextView) this.findViewById(R.id.now_time); total_time = (TextView) this.findViewById(R.id.total_time); m = new MediaController(this); m.setVisibility(View.GONE); videoView.setMediaController(m); videoView.start(); videoView.setOnClickListener(this); play.setOnClickListener(this); //这儿是截取videoview的点击事件。直接setonclick 是不起作用。 videoView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (video_title_name.isShown()) { video_title_name.setVisibility(View.GONE); video_ll.setVisibility(View.GONE); } else { video_title_name.setVisibility(View.VISIBLE); video_ll.setVisibility(View.VISIBLE); } return false; } }); //初始化的时候设置进图条的最大值 videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { seekBar.setMax(mp.getDuration()); seekBar.setProgress(mp.getCurrentPosition()); } }); videoView.setOnCompletionListener(this); seekBar.setOnSeekBarChangeListener(this); timer.schedule(new TimerTask() { @Override public void run() { handler.sendEmptyMessage(isPlaying); } }, 300, 300); videoView.requestFocus(); } private void initDatas() { uri = Uri.parse("http://iplaymtgtest.oss-cn-beijing.aliyuncs.com/video/2016/08/29/b3592f52-bd2f-462b-99f6-c32bdc593493.mp4"); } public static int nowNumber = 0; public static final int isPlaying = 1; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case isPlaying: if (videoView.isPlaying()) { nowNumber = videoView.getCurrentPosition() / 1000; if (nowNumber > 0 && nowNumber < 60) { now_time.setText("00:" + getTimeS2(nowNumber)); } else if (nowNumber >= 60) { now_time.setText(getTimeS2(nowNumber)); } seekBar.setProgress(videoView.getCurrentPosition()); } break; } } }; @Override public void onBackPressed() { super.onBackPressed(); this.finish(); } @Override protected void onPause() { super.onPause(); videoView.pause(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.vv: break; case R.id.play: if (play.getText().toString().equals("暂停")) { play.setText("播放"); videoView.pause(); } else { play.setText("暂停"); videoView.start(); } break; } } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { videoView.seekTo(seekBar.getProgress()); } @Override public void onCompletion(MediaPlayer mp) { } Date d = new Date(); public String getTimeS2(long time) { SimpleDateFormat sdf1; if (3600000 < (time * 1000)) { sdf1 = new SimpleDateFormat("HH:mm:ss"); } else if (60000 <= (time * 1000)) { sdf1 = new SimpleDateFormat("mm:ss"); } else { sdf1 = new SimpleDateFormat("ss"); } d.setTime(time * 1000); return sdf1.format(d); } }
哦, 对了。最后别忘记在 manifest 里注册 activity 为横屏
android:screenOrientation="sensorLandscape"
一个简易的视频播放器 完成。。。
补充:
public class CustomVideoView extends VideoView { public static int mVideoWidth; public static int mVideoHeight; private Context context; public CustomVideoView(Context context) { super(context); this.context = context; // mGestureDetector = new GestureDetector(context, new LearnGestureListener()); // TODO Auto-generated constructor stub } public CustomVideoView(Context context, AttributeSet attrs) { super(context, attrs); // mGestureDetector = new GestureDetector(context, new LearnGestureListener()); // TODO Auto-generated constructor stub } public CustomVideoView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // mGestureDetector = new GestureDetector(context, new LearnGestureListener()); // TODO Auto-generated constructor stub } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub // Log.i("@@@@", "onMeasure"); //下面的代码是让视频的播放的长宽是根据你设置的参数来决定 int width = getDefaultSize(mVideoWidth, widthMeasureSpec); int height = getDefaultSize(mVideoHeight, heightMeasureSpec); setMeasuredDimension(width, height); } GestureDetector mGesture; @Override public boolean onTouchEvent(MotionEvent e) { if (mGesture == null) { mGesture = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDown(MotionEvent e) { 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); } }); mGesture.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() { @Override public boolean onSingleTapConfirmed(MotionEvent e) { return true; } @Override public boolean onDoubleTap(MotionEvent e) { return true; } @Override public boolean onDoubleTapEvent(MotionEvent e) { return false; } }); } GestureDetector mGestureDetector; // // private class LearnGestureListener extends GestureDetector.SimpleOnGestureListener { // @Override // public boolean onSingleTapUp(MotionEvent ev) { // Log.d("onSingleTapUp", ev.toString()); // return true; // } // // @Override // public boolean onDown(MotionEvent e) { // return true; // } // } return super.onTouchEvent(e); } }