Android中使用SurfaceView+MediaPlayer+自定义的MediaController实现自定义的视屏播放器
效果图如下:
(PS本来是要给大家穿gif动态图的,无奈太大了,没法上传)
功能实现:暂停,播放,快进,快退,全屏,退出全屏,等基本功能
实现的思路:
在主布局中放置一个SurfaceView,在SurfaceView中放置一个MediaPlayer ,在其下方自定义一个MediaController,不过也不能称之为MediaController,使用的是PupupWindow来实现的,在PupupWindow布局中放置几个textView,Button,最重要的使我们的SeekBar控件,创建一个定时器,当用户触摸屏幕时,让其popupWindow显示5秒的时间,具体实现可以看代码(主程序的代码有点多,耐心点看啊)
主布局activity_main.xml文件
<RelativeLayout 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=".MainActivity" > <SurfaceView
android:layout_width="match_parent"
android:layout_height="260dp"
android:id="@+id/surfaceView_main"
/> <ImageView
android:onClick="clickButton"
android:id="@+id/imageView_main_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="100dp"
android:src="@drawable/ic_launcher" /> </RelativeLayout>
popupwindow.xml的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/bottom_layout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:orientation="horizontal"
android:background="@drawable/voip_toast_bg"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:weightSum="10" > <ImageView
android:id="@+id/imageView_play"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:src="@drawable/video_btn_on" /> <SeekBar
android:id="@+id/seekbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5.0"
android:max="100"
android:maxHeight="5dp"
android:minHeight="5dp"
android:layout_marginLeft="5dp"
android:progress="0"
android:thumbOffset="0dp" /> <TextView
android:id="@+id/textView_playtime"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.3"
android:gravity="center"
android:text="00:00"
android:textColor="@android:color/white"
android:textSize="12sp" /> <TextView
android:id="@+id/textView_playtime"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.2"
android:gravity="center"
android:text="/"
android:textColor="@android:color/white"
android:textSize="12sp" /> <TextView
android:id="@+id/textView_totaltime"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.3"
android:gravity="center"
android:text="00:00"
android:textColor="@android:color/white"
android:textSize="12sp" /> <ImageView
android:id="@+id/imageView_fullscreen"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:src="@drawable/video_full_screen" /> </LinearLayout>
主Activity中的代码:
package com.amy.day43_03_SurfaceViewMediaPlayer; import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask; import android.R.integer;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.MediaController;
import android.widget.PopupWindow;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView; public class MainActivity extends Activity {
private final static String TAG = "MainActivity";
private Context mContext = this;
private SurfaceView surfaceView = null;
private SurfaceHolder surfaceHolder = null;
private MediaPlayer mediaPlayer = null;
private ImageView imageView_main_show = null; // 自定义的控制条及其上的控件
private View controllerView;
private PopupWindow popupWindow; private ImageView imageView_play;
private ImageView imageView_fullscreen;
private SeekBar seekBar;
private TextView textView_playTime;
private TextView textView_duration;
private String filePath = null; private float densityRatio = 1.0f; // 密度比值系数(密度比值:一英寸中像素点除以160) private Runnable r = new Runnable() {
@Override
public void run() {
// 又回到了主线程
showOrHiddenController();
}
}; private MyVideoBroadcastReceiver receiver = null; // 设置定时器
private Timer timer = null;
private final static int WHAT = 0;
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case WHAT:
if (mediaPlayer != null) {
int currentPlayer = mediaPlayer.getCurrentPosition();
if (currentPlayer > 0) {
mediaPlayer.getCurrentPosition();
textView_playTime.setText(formatTime(currentPlayer)); // 让seekBar也跟随改变
int progress = (int) ((currentPlayer / (float) mediaPlayer
.getDuration()) * 100); seekBar.setProgress(progress);
} else {
textView_playTime.setText("00:00");
seekBar.setProgress(0);
}
} break; default:
break;
}
};
}; // 自动隐藏自定义播放器控制条的时间
private static final int HIDDEN_TIME = 5000; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initView(); initMediaPlayer(); initController(); // 动态注册广播接受者
receiver = new MyVideoBroadcastReceiver();
registerReceiver(receiver, new IntentFilter(
"com.amy.day43_03_SurfaceViewMediaPlayer"));
} private String formatTime(long time) {
SimpleDateFormat formatter = new SimpleDateFormat("mm:ss");
return formatter.format(new Date(time));
} private void initController() { controllerView = getLayoutInflater().inflate(
R.layout.popupwindow_mediacontroller, null); // 初始化popopWindow
popupWindow = new PopupWindow(controllerView,
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, true); imageView_play = (ImageView) controllerView
.findViewById(R.id.imageView_play);
imageView_fullscreen = (ImageView) controllerView
.findViewById(R.id.imageView_fullscreen); seekBar = (SeekBar) controllerView.findViewById(R.id.seekbar); textView_playTime = (TextView) controllerView
.findViewById(R.id.textView_playtime);
textView_duration = (TextView) controllerView
.findViewById(R.id.textView_totaltime); seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { // 表示手指拖动seekbar完毕,手指离开屏幕会触发以下方法
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// 让计时器延时执行
handler.postDelayed(r, HIDDEN_TIME);
} // 在手指正在拖动seekBar,而手指未离开屏幕触发的方法
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// 让计时器取消计时
handler.removeCallbacks(r);
} @Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if (fromUser) {
int playtime = progress * mediaPlayer.getDuration() / 100;
mediaPlayer.seekTo(playtime);
} }
}); // 点击播放的时候,判断是播放还是暂停
imageView_play.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
if (imageView_main_show.getVisibility() == View.VISIBLE) {
imageView_main_show.setVisibility(View.GONE);
} if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
imageView_play.setImageResource(R.drawable.video_btn_down);
} else {
mediaPlayer.start();
imageView_play.setImageResource(R.drawable.video_btn_on); } }
}); // 实现全屏和退出全屏(内容物横竖屏,不是屏幕的横竖屏)
imageView_fullscreen.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
imageView_fullscreen
.setImageResource(R.drawable.video_full_screen); // 重新设置surfaceView的高度和宽度
surfaceView.getLayoutParams().width = LayoutParams.MATCH_PARENT;
surfaceView.getLayoutParams().height = (int) (260 * densityRatio);
} else if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
imageView_fullscreen
.setImageResource(R.drawable.video_inner_screen); surfaceView.getLayoutParams().width = LayoutParams.MATCH_PARENT;
surfaceView.getLayoutParams().height = LayoutParams.MATCH_PARENT;
} surfaceView.setLayoutParams(surfaceView.getLayoutParams());
}
});
} private void showOrHiddenController() {
if (popupWindow.isShowing()) {
popupWindow.dismiss();
} else {
// 将dp转换为px
int controllerHeightPixel = (int) (densityRatio * 50);
popupWindow.showAsDropDown(surfaceView, 0, -controllerHeightPixel);
// 延时执行
handler.postDelayed(r, HIDDEN_TIME);
}
} private void initMediaPlayer() {
filePath = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()
+ File.separator + "myabc.mp4"; Log.i("==main==",
"==========="
+ Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS)
.getAbsolutePath());
if (mediaPlayer == null) {
// 1,创建MediaPlay对象
mediaPlayer = new MediaPlayer();
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(filePath);
mediaPlayer.prepare();
// mediaPlayer.start();
mediaPlayer.setLooping(false);
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} } mediaPlayer.setOnPreparedListener(new OnPreparedListener() { @Override
public void onPrepared(MediaPlayer mp) {
// 表示准备完成,设置总的时长,使用时间格式化工具 // String duration = mediaPlayer.getDuration() ;
textView_duration.setText(formatTime(mediaPlayer.getDuration()));
// 初始化定时器
timer = new Timer();
timer.schedule(new TimerTask() { @Override
public void run() {
handler.sendEmptyMessage(WHAT);
}
}, 0, 1000);
}
}); mediaPlayer.setOnErrorListener(new OnErrorListener() { @Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mp.reset(); return false;
}
}); mediaPlayer.setOnCompletionListener(new OnCompletionListener() { @Override
public void onCompletion(MediaPlayer mp) {
// 发送广播,播放下一首歌曲 Intent intent = new Intent();
intent.setAction("com.amy.day43_03_SurfaceViewMediaPlayer");
sendBroadcast(intent);
}
});
} private void initView() {
// TODO Auto-generated method stub
densityRatio = getResources().getDisplayMetrics().density; // 表示获取真正的密度 imageView_main_show = (ImageView) findViewById(R.id.imageView_main_play);
surfaceView = (SurfaceView) findViewById(R.id.surfaceView_main);
surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(new Callback() { @Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
}
} @Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
if (mediaPlayer != null) { mediaPlayer.setDisplay(surfaceHolder);
// mediaPlayer.start() ; } } @Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub }
}); // 设置屏幕的触摸监听
surfaceView.setOnTouchListener(new OnTouchListener() { @Override
public boolean onTouch(View v, MotionEvent event) {
// 表示在点击的瞬间就显示控制条
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
showOrHiddenController();
break; default:
break;
}
return true;
}
});
} /**
* 设置控件的监听事件
*
* @param v
*/
public void clickButton(View v) {
switch (v.getId()) {
case R.id.imageView_main_play: imageView_main_show.setVisibility(View.GONE);
mediaPlayer.start(); break; default:
break;
}
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} @Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy(); unregisterReceiver(receiver);
timer.cancel(); if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
} handler.removeCallbacksAndMessages(null);
} class MyVideoBroadcastReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(
"com.amy.day43_03_SurfaceViewMediaPlayer")) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setIcon(R.drawable.ic_launcher)
.setTitle("提示")
.setMessage("视屏播放完毕,是否播放")
.setNegativeButton("取消", null)
.setPositiveButton("确定",
new DialogInterface.OnClickListener() { @Override
public void onClick(DialogInterface dialog,
int which) {
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(filePath);
mediaPlayer.prepare();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mediaPlayer.setLooping(false); mediaPlayer.start();
}
}).show(); }
} } }
Android中使用SurfaceView+MediaPlayer+自定义的MediaController实现自定义的视屏播放器的更多相关文章
- android中使用surfaceview+MediaPlayer播放视频
Android中播放视频主要有两种方式: 使用其自带的播放器.指定Action为ACTION_VIEW,Data为Uri,Type为其MIME类型 使用android自带的VideoView,这种方法 ...
- android下面使用SurfaceView+ mediaPlayer播放视频
final SurfaceView surfaceView = new SurfaceView(StartupActivity.this); StartupActivity.this.mediaPla ...
- 【Android】利用安卓的数据接口、多媒体处理编写内存卡Mp3播放器app
通过调用安卓的MediaPlayer能够直接完毕Mp3等主流音频的播放,同一时候利用ContentResolver与Cursor能够直接读取安卓内在数据库的信息.直接获取当前sdcard中全部音频的列 ...
- Android中使用SurfaceView和Canvas来绘制动画
事实上每一个View中都有Canvas能够用来绘制动画.仅仅须要在这个View中重载onDraw()方法就能够,可是SurfaceView类是一个专门用来制动动画的类. Canvas(中文叫做&quo ...
- Android中surface,surfaceview,sufaceholder以及surface客户端的关系
这里以照相机camera功能的实现来解释surface,surfaceview,sufaceholder以及surface客户端(本例子中指的是camera)的关系,surface及其client(客 ...
- 【Android 应用开发】Android中使用ViewPager制作广告栏效果 - 解决ViewPager占满全屏页面适配问题
. 参考界面 : 携程app首页的广告栏, 使用ViewPager实现 自制页面效果图 : 源码下载地址: http://download.csdn.net/detail/han1202 ...
- Android中使用ViewPager制作广告栏效果 - 解决ViewPager占满全屏页面适配问题
. 参考界面 : 携程app首页的广告栏, 使用ViewPager实现 自制页面效果图 : 源码下载地址: http://download.csdn.net/detail/han1202 ...
- Android视屏播放兼容性问题分享
最近产品提了一个紧急需求:webview加载的URL,需要支持视频播放. 为了快速完成需求,功能实现上直接使用系统自带播放器播放视频.由于是自带播放器,需要进行兼容性测试,过程发现了不少问题,这里分享 ...
- android中VideoView播放sd卡上面的视频
(1)videoView组件只支持MP4和3gp格式的视屏播放,如果想播放其它视屏格式的文件,还得开发能够播放的视屏播放器 (2)videoView组件功能比较单一,如果想开发功能丰富的播放器,还得重 ...
随机推荐
- FW nexus docker
原文地址: http://www.cnblogs.com/wzy5223/p/5410990.html Nexus 3.0 可以创建三种docker仓库: 1. docker (proxy) ...
- Qt 之 自定义窗口标题栏(非常完善)
http://blog.csdn.net/goforwardtostep/article/details/53494800
- 报javax.servlet.ServletException: Servlet.init() for servlet springmvc threw exception异常 的解决方案
后台错误信息如下: javax.servlet.ServletException: Servlet.init() for servlet springmvc threw exception org.a ...
- php--yii框架中的ajax分页与yii框架自带的分页
要想使用Yii分页类 第一步:在控制器层加载分页类 use yii\data\Pagination; 第二步: 使用model层查询数据,并用分分页,限制每页的显示条数 $data = Zhao::f ...
- MongoDB聚合查询
1.count:查询记录条数 db.user.count() 它也跟find一样可以有条件的 db.user.count({}) 2.distinct:用来找出给定键的所有不同的值 db.user.d ...
- Jquery调用webService的四种方法
1.编写4种WebService方法 [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(Conf ...
- 利用ArcMap对tiff或jpg格式地图图片的配准步骤
原文:利用ArcMap对tiff或jpg格式地图图片的配准步骤 在实际应用中,经常会遇到提供一张高精度的地图图片文件,如何对将该图片进行配准(使图片具有经纬度坐标). 当然我们得有一些大概的参考图层, ...
- An Implementation of Double-Array Trie
Contents What is Trie? What Does It Take to Implement a Trie? Tripple-Array Trie Double-Array Trie S ...
- [LeetCode]题解(python):037-Sudoku Solver
题目来源 https://leetcode.com/problems/sudoku-solver/ Write a program to solve a Sudoku puzzle by fillin ...
- Java学习-032-JavaWeb_001 -- Tomcat环境部署及基本配置
首先到 Tomcat 官网,下载对应的版本,我本机的系统是 WIN7 64BIT 的,因而我选择的是64bit 的zip包,如下图所示: