Android播放远程非流MP4文件
来源:互联网 发布:hadoop windows版本 编辑:程序博客网 时间:2024/04/20 10:05
保存备用:
由于Android自带的Mediaplayer类,只能播放本地或者远程流形式的MP4文件,所以在播放远程非流的MP4,而且MP4的moov数据在文件的末尾时,在下载时,需要我们在写文件时做特殊处理,这样才能实现下载一部分,播放一部视频,下面来看实现代码:
下载代码部分
[java] view plain copy
- public class Mp4DownloadUtils {
- /** 播放MP4消息 */
- private static final int PLAYER_MP4_MSG = 0x1001;
- /** 下载MP4完成 */
- private static final int DOWNLOAD_MP4_COMPLETION = 0x1002;
- /** 下载MP4失败 */
- private static final int DOWNLOAD_MP4_FAIL = 0x1003;
- /**
- * 下载MP4文件
- * @param url
- * @param fileName
- * @param handler
- * @return
- */
- public static File downloadMp4File(final String url, final String fileName,
- final Handler handler) {
- final File mp4File = new File(fileName);
- downloadVideoToFile(url, mp4File, handler);
- return mp4File;
- }
- /**
- * 下载视频数据到文件
- * @param url
- * @param dstFile
- * @param moovSize
- */
- private static void downloadVideoToFile(final String url, final File dstFile, final Handler handler) {
- Thread thread = new Thread() {
- @Override
- public void run() {
- super.run();
- try {
- URL request = new URL(url);
- HttpURLConnection httpConn = (HttpURLConnection) request.openConnection();
- httpConn.setConnectTimeout(3000);
- httpConn.setDoInput(true);
- httpConn.setDoOutput(true);
- httpConn.setDefaultUseCaches(false);
- httpConn.setRequestMethod("GET");
- httpConn.setRequestProperty("Charset", "UTF-8");
- httpConn.setRequestProperty("Accept-Encoding", "identity");
- int responseCode = httpConn.getResponseCode();
- if ((responseCode == HttpURLConnection.HTTP_OK)) {
- // 获取文件总长度
- int totalLength = httpConn.getContentLength();
- InputStream is = httpConn.getInputStream();
- if (dstFile.exists()) {
- dstFile.delete();
- }
- dstFile.createNewFile();
- RandomAccessFile raf = new RandomAccessFile(dstFile, "rw");
- BufferedInputStream bis = new BufferedInputStream(is);
- int readSize = 0;
- int mdatSize = 0;// mp4的mdat长度
- int headSize = 0;// mp4头长度
- byte[] boxSizeBuf = new byte[4];
- byte[] boxTypeBuf = new byte[4];
- // 由MP4的文件格式读取
- int boxSize = readBoxSize(bis, boxSizeBuf);
- String boxType = readBoxType(bis, boxTypeBuf);
- raf.write(boxSizeBuf);
- raf.write(boxTypeBuf);
- while (!boxType.equalsIgnoreCase("moov")) {
- int count = boxSize - 8;
- if (boxType.equalsIgnoreCase("ftyp")) {
- headSize += boxSize;
- byte[] ftyps = new byte[count];
- bis.read(ftyps, 0, count);
- raf.write(ftyps, 0, count);
- } else if (boxType.equalsIgnoreCase("mdat")) {
- // 标记mdat数据流位置,在后面reset时读取
- bis.mark(totalLength - headSize);
- // 跳过mdat数据
- skip(bis, count);
- mdatSize = count;
- byte[] mdatBuf = new byte[mdatSize];
- raf.write(mdatBuf);
- } else if (boxType.equalsIgnoreCase("free")) {
- headSize += boxSize;
- }
- boxSize = readBoxSize(bis, boxSizeBuf);
- boxType = readBoxType(bis, boxTypeBuf);
- raf.write(boxSizeBuf);
- raf.write(boxTypeBuf);
- }
- // 读取moov数据
- byte[] buffer = new byte[4096];
- int moovSize = 0;
- while ((readSize = bis.read(buffer)) != -1) {
- moovSize += readSize;
- raf.write(buffer, 0, readSize);
- }
- // 返回到mdat数据开始
- bis.reset();
- // 设置文件指针偏移到mdat位置
- long offset = raf.getFilePointer() - moovSize - mdatSize - 8;
- raf.seek(offset);
- // 读取mdat数据,设置mp4初始mdat的缓存大小
- int buf_size = 56 * 1024;// 56kb
- int downloadCount = 0;
- boolean viable = false;
- while (mdatSize > 0) {
- readSize = bis.read(buffer);
- raf.write(buffer, 0, readSize);
- mdatSize -= readSize;
- downloadCount += readSize;
- if (handler != null && !viable && downloadCount >= buf_size) {
- viable = true;
- // 发送开始播放视频消息
- sendMessage(handler, PLAYER_MP4_MSG, null);
- }
- }
- // 发送下载消息
- if (handler != null) {
- sendMessage(handler, DOWNLOAD_MP4_COMPLETION, null);
- }
- bis.close();
- is.close();
- raf.close();
- httpConn.disconnect();
- }
- } catch (Exception e) {
- e.printStackTrace();
- sendMessage(handler, DOWNLOAD_MP4_FAIL, null);
- }
- }
- };
- thread.start();
- thread = null;
- }
- /**
- * 发送下载消息
- * @param handler
- * @param what
- * @param obj
- */
- private static void sendMessage(Handler handler, int what, Object obj) {
- if (handler != null) {
- Message msg = new Message();
- msg.what = what;
- msg.obj = obj;
- handler.sendMessage(msg);
- }
- }
- /**
- * 跳转
- * @param is
- * @param count 跳转长度
- * @throws IOException
- */
- private static void skip(BufferedInputStream is, long count) throws IOException {
- while (count > 0) {
- long amt = is.skip(count);
- if (amt == -1) {
- throw new RuntimeException("inputStream skip exception");
- }
- count -= amt;
- }
- }
- /**
- * 读取mp4文件box大小
- * @param is
- * @param buffer
- * @return
- */
- private static int readBoxSize(InputStream is, byte[] buffer) {
- int sz = fill(is, buffer);
- if (sz == -1) {
- return 0;
- }
- return bytesToInt(buffer, 0, 4);
- }
- /**
- * 读取MP4文件box类型
- * @param is
- * @param buffer
- * @return
- */
- private static String readBoxType(InputStream is, byte[] buffer) {
- fill(is, buffer);
- return byteToString(buffer);
- }
- /**
- * byte转换int
- * @param buffer
- * @param pos
- * @param bytes
- * @return
- */
- private static int bytesToInt(byte[] buffer, int pos, int bytes) {
- /*
- * int intvalue = (buffer[pos + 0] & 0xFF) << 24 | (buffer[pos + 1] &
- * 0xFF) << 16 | (buffer[pos + 2] & 0xFF) << 8 | buffer[pos + 3] & 0xFF;
- */
- int retval = 0;
- for (int i = 0; i < bytes; ++i) {
- retval |= (buffer[pos + i] & 0xFF) << (8 * (bytes - i - 1));
- }
- return retval;
- }
- /**
- * byte数据转换String
- * @param buffer
- * @return
- */
- private static String byteToString(byte[] buffer) {
- assert buffer.length == 4;
- String retval = new String();
- try {
- retval = new String(buffer, 0, buffer.length, "ascii");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return retval;
- }
- private static int fill(InputStream stream, byte[] buffer) {
- return fill(stream, 0, buffer.length, buffer);
- }
- /**
- * 读取流数据
- * @param stream
- * @param pos
- * @param len
- * @param buffer
- * @return
- */
- private static int fill(InputStream stream, int pos, int len, byte[] buffer) {
- int readSize = 0;
- try {
- readSize = stream.read(buffer, pos, len);
- if (readSize == -1) {
- return -1;
- }
- assert readSize == len : String.format("len %d readSize %d", len,
- readSize);
- } catch (IOException e) {
- e.printStackTrace();
- }
- return readSize;
- }
- }
[cpp] view plain copy
- public class VideoPlayerActivity extends Activity implements OnClickListener,
- OnSeekBarChangeListener, OnPreparedListener, OnCompletionListener, OnTouchListener {
- private String url = null;// 播放地址
- private SurfaceView surfaceView = null;
- private SurfaceHolder surfaceHolder = null;
- private MediaPlayer mediaPlayer = null;
- private SeekBar seekBar = null;// 播放进度条
- private Button playBtn = null;// 播放
- private Button pauseBtn = null;// 暂停
- private TextView tv_current = null;
- private TextView tv_duration = null;
- private TextView divideTxt = null;
- private RelativeLayout controlLayout = null;// 操控界面布局
- private RelativeLayout mediaPlayerLayout = null;
- private LayoutParams mediaLayoutParams = null;
- private LinearLayout loadPrgLayout = null;
- private boolean isPlay = false;// 播放状态
- private boolean isPause = false;
- private boolean isShow = true;
- private boolean isEnd = false;
- private boolean isStartPlayer = false;
- private boolean isCustomStyle = false;// 开启自定义seekBar样式
- private int mDuration = 0;
- private int mSeekBarMax = 0;
- private int currentPosition = 0;// 当前播放位置
- private File mDownloadMP4File = null;
- private MediaPlayerCallback mCallback = null;
- private static final int playBtnID = 0x001;// 播放按钮id
- private static final int pauseBtnID = 0x002;// 暂停按钮id
- private static final int btnLayoutID = 0x003;// 按钮布局层id
- private static final int clockLayoutID = 0x004;// 计时布局层id
- private static final int surfaceViewID = 0x005;// surfaceView id
- /** 分秒 */
- private static final String DateFormatMS = "mm:ss";
- private static final int UPDATE_PROGRESS_MSG = 0x011;// 更新进度条和计时
- private static final int SHOW_CONTROL_MSG = 0x012;// 显示控制
- private static final int COMPLETION_PLAY_MSG = 0x013;// 播放完成
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN); // 全屏
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- // 测试视频地址
- url = "http://minisite.adsame.com/nodie/v2.mp4";
- String videoFileName = getRootPath() + getVideo(url);
- mDownloadMP4File = Mp4DownloadUtils.downloadMp4File(url, videoFileName, videoHandler);
- initPlayer();
- }
- /**
- * 获取外部存储根路径
- * @return
- */
- private String getRootPath() {
- String rootPath = Environment.getExternalStorageDirectory().getAbsolutePath();
- return rootPath;
- }
- /**
- * 获取视频文件名字
- * @param videoUrl
- * @return
- */
- private String getVideo(String videoUrl) {
- int startIndex = videoUrl.lastIndexOf("/");
- return url.substring(startIndex, videoUrl.length());
- }
- /**
- * 视频下载时的handler
- */
- private Handler videoHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- switch (msg.what) {
- // 有MP4的mdat数据时,创建播放器
- case Mp4DownloadUtils.PLAYER_MP4_MSG:
- isStartPlayer = true;
- createMediaPlayer(mDownloadMP4File);
- break;
- case Mp4DownloadUtils.DOWNLOAD_MP4_COMPLETION:
- break;
- case Mp4DownloadUtils.DOWNLOAD_MP4_FAIL:
- break;
- default:
- break;
- }
- }
- };
- @SuppressWarnings("deprecation")
- private void initPlayer() {
- if (surfaceView == null) {
- surfaceView = new SurfaceView(this);
- surfaceView.getHolder()
- .setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// 不缓冲
- surfaceView.getHolder().setKeepScreenOn(true);// 保持屏幕高亮
- surfaceView.getHolder().addCallback(new SurfaceViewCallback());
- surfaceView.setId(surfaceViewID);
- surfaceView.setOnClickListener(this);
- surfaceView.setEnabled(false);
- surfaceHolder = surfaceView.getHolder();
- }
- initPlayerButton();
- RelativeLayout btnLayout = new RelativeLayout(this);
- btnLayout.setId(btnLayoutID);
- btnLayout.setGravity(Gravity.CENTER);
- LayoutParams btnParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
- LayoutParams.WRAP_CONTENT);
- btnParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
- btnParams.addRule(RelativeLayout.CENTER_VERTICAL);
- btnLayout.setLayoutParams(btnParams);
- btnLayout.addView(playBtn);
- btnLayout.addView(pauseBtn);
- initClockTextView();
- LinearLayout clockLayout = new LinearLayout(this);
- clockLayout.setId(clockLayoutID);
- clockLayout.setOrientation(LinearLayout.HORIZONTAL);
- LayoutParams clockTVLayoutParams = new LayoutParams(
- LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- clockTVLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
- clockTVLayoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
- clockLayout.setLayoutParams(clockTVLayoutParams);
- clockLayout.addView(tv_duration);
- clockLayout.addView(divideTxt);
- clockLayout.addView(tv_current);
- // 进度条必须在btnLayout和prgLayout后面
- initProgressSeekBar();
- // 下载进度
- initProgressBar();
- controlLayout = new RelativeLayout(this);
- LayoutParams rlParams = new LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.WRAP_CONTENT);
- rlParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
- int marginLeft = 5;
- int marginRight = 5;
- rlParams.setMargins(marginLeft, 0, marginRight, 0);
- controlLayout.setLayoutParams(rlParams);
- controlLayout.setVisibility(View.GONE);
- controlLayout.setBackgroundColor(Color.GRAY);
- controlLayout.addView(btnLayout);
- controlLayout.addView(seekBar);
- controlLayout.addView(clockLayout);
- setViewDrawableStyle();
- mediaPlayerLayout = new RelativeLayout(this);
- mediaLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
- mediaLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
- mediaPlayerLayout.setLayoutParams(mediaLayoutParams);
- mediaPlayerLayout.addView(surfaceView);
- mediaPlayerLayout.addView(controlLayout);
- mediaPlayerLayout.addView(loadPrgLayout);
- RelativeLayout layout = new RelativeLayout(this);
- layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.MATCH_PARENT));
- layout.addView(mediaPlayerLayout);
- setContentView(layout);
- }
- private void initPlayerButton() {
- int btnWidth = 60;
- int btnHeight = 60;
- // 开始按钮
- playBtn = new Button(this);
- playBtn.setId(playBtnID);
- playBtn.setOnClickListener(this);
- LayoutParams playParams = new LayoutParams(btnWidth, btnHeight);
- playBtn.setLayoutParams(playParams);
- playBtn.setEnabled(false);
- // 暂停按钮
- pauseBtn = new Button(this);
- pauseBtn.setId(pauseBtnID);
- pauseBtn.setOnClickListener(this);
- LayoutParams pauseParams = new LayoutParams(btnWidth, btnHeight);
- pauseBtn.setLayoutParams(pauseParams);
- pauseBtn.setVisibility(View.GONE);
- }
- private void initClockTextView() {
- // 播放进度
- tv_current = new TextView(this);
- tv_current.setTextColor(Color.WHITE);
- tv_current.setText(getStringByFormat(currentPosition, DateFormatMS));
- // 播放持续时间
- tv_duration = new TextView(this);
- tv_duration.setTextColor(Color.WHITE);
- tv_duration.setText(getStringByFormat(mDuration, DateFormatMS));
- // 分隔线
- divideTxt = new TextView(this);
- divideTxt.setText("/");
- divideTxt.setTextColor(Color.WHITE);
- }
- private void initProgressSeekBar() {
- // 播放进度条
- seekBar = new SeekBar(this);
- seekBar.setOnSeekBarChangeListener(this);
- LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.WRAP_CONTENT);
- params.addRule(RelativeLayout.RIGHT_OF, btnLayoutID);
- params.addRule(RelativeLayout.LEFT_OF, clockLayoutID);
- params.addRule(RelativeLayout.CENTER_VERTICAL);
- int leftpadding = 15;
- int rightpadding = 15;
- seekBar.setLayoutParams(params);
- seekBar.setPadding(leftpadding, 0, rightpadding, 0);
- seekBar.setOnTouchListener(this);
- }
- private void initProgressBar() {
- LayoutParams layoutParams = new LayoutParams(
- LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
- loadPrgLayout = new LinearLayout(this);
- loadPrgLayout.setLayoutParams(layoutParams);
- loadPrgLayout.setOrientation(LinearLayout.VERTICAL);
- loadPrgLayout.setVisibility(View.VISIBLE);
- loadPrgLayout.setGravity(Gravity.CENTER);
- LayoutParams params = new LayoutParams(
- LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- ProgressBar loadPrgBar = new ProgressBar(this);
- loadPrgBar.setLayoutParams(params);
- loadPrgLayout.addView(loadPrgBar);
- }
- /**
- * 设置view的样式
- */
- private void setViewDrawableStyle() {
- try {
- // setBackground报错需要Android版本号在16以上
- playBtn.setBackground(createSelectorDrawable(
- getAssetDrawable(this, "btn_play_normal.png"),
- getAssetDrawable(this, "btn_play_pressed.png")));
- pauseBtn.setBackground(createSelectorDrawable(
- getAssetDrawable(this, "btn_pause_normal.png"),
- getAssetDrawable(this, "btn_pause_pressed.png")));
- if (isCustomStyle) {
- seekBar.setThumb(createSeekbarThumbDrawable(
- getAssetDrawable(this, "progress_thumb_normal.png"),
- getAssetDrawable(this, "progress_thumb_pressed.png")));
- seekBar.setProgressDrawable(createSeekbarProgressDrawable(
- getAssetDrawable(this, "progress_bg.png"),
- getAssetDrawable(this, "progress_secondary.png"),
- getAssetDrawable(this, "progress.png")));
- controlLayout.setBackground(getAssetDrawable(this, "ctrl_layout_bg.png"));
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 获取accets目录下的图片
- * @param context
- * @param imageName
- * @return
- * @throws IOException
- */
- public Drawable getAssetDrawable(Context context, String imageName) throws IOException {
- return BitmapDrawable.createFromStream(context.getAssets().open(imageName), imageName);
- }
- /**
- * 创建图片选择器
- * @param normal
- * @param pressed
- * @return
- */
- private Drawable createSelectorDrawable(Drawable normal, Drawable pressed) {
- StateListDrawable drawable = new StateListDrawable();
- drawable.addState(new int[] { android.R.attr.state_focused },
- normal);
- drawable.addState(new int[] { android.R.attr.state_pressed },
- pressed);
- drawable.addState(new int[] {}, normal);
- return drawable;
- }
- /**
- * 创建seekBar拖动点样式图
- *
- * @param normal
- * 正常
- * @param pressed
- * 下压
- * @return
- */
- private Drawable createSeekbarThumbDrawable(Drawable normal, Drawable pressed) {
- StateListDrawable drawable = new StateListDrawable();
- drawable.addState(new int[] { android.R.attr.state_pressed }, pressed);
- drawable.addState(new int[] { android.R.attr.state_focused }, normal);
- drawable.addState(new int[] {}, normal);
- return drawable;
- }
- /**
- * 创建seekBar进度样式图
- *
- * @param background
- * 背景图
- * @param secondaryProgress
- * 第二进度能量图
- * @param progress
- * 进度能量图
- * @return
- */
- private Drawable createSeekbarProgressDrawable(Drawable background,
- Drawable secondaryProgress, Drawable progress) {
- LayerDrawable progressDrawable = (LayerDrawable) seekBar
- .getProgressDrawable();
- int itmeSize = progressDrawable.getNumberOfLayers();
- Drawable[] outDrawables = new Drawable[itmeSize];
- for (int i = 0; i < itmeSize; i++) {
- switch (progressDrawable.getId(i)) {
- case android.R.id.background:// 设置进度条背景
- outDrawables[i] = background;
- break;
- case android.R.id.secondaryProgress:// 设置二级进度条
- outDrawables[i] = secondaryProgress;
- break;
- case android.R.id.progress:// 设置进度条
- ClipDrawable oidDrawable = (ClipDrawable) progressDrawable
- .getDrawable(i);
- Drawable drawable = progress;
- ClipDrawable proDrawable = new ClipDrawable(drawable,
- Gravity.LEFT, ClipDrawable.HORIZONTAL);
- proDrawable.setLevel(oidDrawable.getLevel());
- outDrawables[i] = proDrawable;
- break;
- default:
- break;
- }
- }
- progressDrawable = new LayerDrawable(outDrawables);
- return progressDrawable;
- }
- private class SurfaceViewCallback implements
- android.view.SurfaceHolder.Callback {
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- createMediaPlayer();
- }
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width,
- int height) {
- }
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- destroy();
- }
- }
- private void createMediaPlayer() {
- createMediaPlayer(null);
- }
- private void createMediaPlayer(File videoFile) {
- if (url == null && videoFile == null && !isStartPlayer) {
- return;
- }
- if (mediaPlayer == null) {
- mediaPlayer = new MediaPlayer();
- }
- mediaPlayer.reset();
- mediaPlayer.setOnCompletionListener(this);
- mediaPlayer.setOnPreparedListener(this);// 设置监听事件
- mediaPlayer.setDisplay(surfaceHolder);// 把视频显示到surfaceView上
- if (videoFile != null) {
- setDataSource(videoFile);
- } else {
- setDataSource(url);
- }
- mediaPlayer.prepareAsync();// 准备播放
- }
- private void setDataSource(String src) {
- try {
- if (src.startsWith("http://")) {
- mediaPlayer.setDataSource(this, Uri.parse(src));
- } else {
- setDataSource(new File(src));
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- private void setDataSource(File file) {
- try {
- FileInputStream fis = new FileInputStream(file);
- mediaPlayer.setDataSource(fis.getFD());// 设置播放路径
- fis.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- @Override
- public void onPrepared(MediaPlayer mp) {
- if (isPause) {
- } else {
- mediaPlayer.start();
- playBtn.setEnabled(true);
- playBtn.setVisibility(View.GONE);
- pauseBtn.setVisibility(View.VISIBLE);
- if (currentPosition > 0) {
- mediaPlayer.seekTo(currentPosition);
- }
- }
- loadPrgLayout.setVisibility(View.GONE);
- controlLayout.setVisibility(View.VISIBLE);
- surfaceView.setEnabled(true);
- mHandler.post(showControlRunnable);
- mHandler.post(updateProgressRunnable);
- if (mSeekBarMax == 0 || mDuration == 0) {
- mSeekBarMax = seekBar.getMax();
- mDuration = mediaPlayer.getDuration();
- mediaPlayerLayout.setMinimumHeight(520);
- mediaPlayerLayout.invalidate();
- }
- }
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- removeHandlerTask();
- }
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress,
- boolean fromUser) {
- if (fromUser) {
- int milliseconds = countPosition(progress);
- tv_current.setText(getStringByFormat(milliseconds, DateFormatMS));
- }
- }
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- if (mediaPlayer != null) {
- currentPosition = countPosition(seekBar.getProgress());
- mediaPlayer.seekTo(currentPosition);
- restartHandlerTack();
- }
- }
- private void start() {
- if (mediaPlayer != null && isPause) {
- isPlay = true;
- isPause = false;
- if (currentPosition > 0) {
- mediaPlayer.seekTo(currentPosition);
- }
- mediaPlayer.start();
- restartHandlerTack();
- playBtn.setVisibility(View.GONE);
- pauseBtn.setVisibility(View.VISIBLE);
- }
- }
- private void pause() {
- if (mediaPlayer != null && mediaPlayer.isPlaying()) {
- isPlay = false;
- isPause = true;
- mediaPlayer.pause();
- playBtn.setVisibility(View.VISIBLE);
- pauseBtn.setVisibility(View.GONE);
- controlLayout.setVisibility(View.VISIBLE);
- currentPosition = mediaPlayer.getCurrentPosition();
- removeHandlerTask();
- }
- }
- private void destroy() {
- if (mediaPlayer != null && isPlay) {
- mediaPlayer.pause();
- controlLayout.setVisibility(View.VISIBLE);
- currentPosition = mediaPlayer.getCurrentPosition();
- removeHandlerTask();
- }
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case playBtnID:// 播放
- if (mediaPlayer == null) {
- createMediaPlayer();
- } else {
- start();
- }
- break;
- case pauseBtnID:// 暂停
- pause();
- break;
- case surfaceViewID:
- // 先移除任务,如果显示,重新post一次任务
- mHandler.removeCallbacks(showControlRunnable);
- if (isShow) {
- controlLayout.setVisibility(View.GONE);
- isShow = false;
- } else {
- controlLayout.setVisibility(View.VISIBLE);
- isShow = true;
- mHandler.postDelayed(showControlRunnable, 5000);
- }
- break;
- default:
- break;
- }
- }
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (v == seekBar && isEnd) {
- return true;
- }
- return false;
- }
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- }
- @Override
- public void onCompletion(MediaPlayer mp) {
- // 完成播放
- try {
- isEnd = true;
- isPlay = false;
- seekBar.setProgress(countProgress(mDuration));
- tv_current.setText(getStringByFormat(mDuration, DateFormatMS));
- playBtn.setVisibility(View.VISIBLE);
- pauseBtn.setVisibility(View.GONE);
- controlLayout.setVisibility(View.VISIBLE);
- playBtn.setEnabled(false);
- removeHandlerTask();
- mHandler.sendEmptyMessageDelayed(COMPLETION_PLAY_MSG, 500);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public interface MediaPlayerCallback {
- public void onCompletion();
- }
- public void setMediaPlayerCallback(MediaPlayerCallback callback) {
- mCallback = callback;
- }
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- switch (msg.what) {
- case UPDATE_PROGRESS_MSG:// 更新播放进度和计时器
- if (mediaPlayer != null && mediaPlayer.isPlaying()) {
- isPlay = true;
- currentPosition = mediaPlayer.getCurrentPosition();
- seekBar.setProgress(countProgress(currentPosition));
- tv_current
- .setText(getStringByFormat(currentPosition, DateFormatMS));
- tv_duration.setText(getStringByFormat(mDuration, DateFormatMS));
- }
- break;
- case SHOW_CONTROL_MSG:// 显示播放控制控件
- if (isPlay) {
- isShow = false;
- controlLayout.setVisibility(View.GONE);
- mHandler.removeCallbacks(showControlRunnable);
- } else {
- isShow = true;
- controlLayout.setVisibility(View.VISIBLE);
- }
- break;
- case COMPLETION_PLAY_MSG:// 完成播放
- finish();
- if (mCallback != null) {
- mCallback.onCompletion();
- }
- Settings.System.getInt(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0);
- break;
- default:
- break;
- }
- }
- };
- /**
- * 重新启动任务
- */
- private void restartHandlerTack() {
- mHandler.post(updateProgressRunnable);
- mHandler.postDelayed(showControlRunnable, 5000);
- }
- /**
- * 移除任务
- */
- private void removeHandlerTask() {
- mHandler.removeCallbacks(showControlRunnable);
- mHandler.removeCallbacks(updateProgressRunnable);
- }
- /**
- * 更新进度条线程
- */
- private Runnable updateProgressRunnable = new Runnable() {
- @Override
- public void run() {
- mHandler.sendEmptyMessage(UPDATE_PROGRESS_MSG);
- mHandler.postDelayed(updateProgressRunnable, 1000);
- }
- };
- /**
- * 显示控制线程
- */
- private Runnable showControlRunnable = new Runnable() {
- @Override
- public void run() {
- mHandler.sendEmptyMessage(SHOW_CONTROL_MSG);
- mHandler.postDelayed(showControlRunnable, 5000);
- }
- };
- /**
- * 计算播放进度
- *
- * @param position
- * @return
- */
- private int countProgress(int position) {
- if (mDuration == 0) {
- return 0;
- }
- return position * mSeekBarMax / mDuration;
- }
- /**
- * 计算播放位置
- *
- * @param progress
- * @return
- */
- private int countPosition(int progress) {
- if (mSeekBarMax == 0) {
- return 0;
- }
- return progress * mDuration / mSeekBarMax;
- }
- /**
- * 描述:获取milliseconds表示的日期时间的字符串.
- *
- * @param milliseconds
- * @param format
- * 格式化字符串,如:"yyyy-MM-dd HH:mm:ss"
- * @return String 日期时间字符串
- */
- private String getStringByFormat(long milliseconds, String format) {
- String thisDateTime = null;
- try {
- SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format);
- mSimpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+0"));
- thisDateTime = mSimpleDateFormat.format(milliseconds);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return thisDateTime;
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (mediaPlayer != null) {
- mediaPlayer.stop();
- mediaPlayer.release();
- mediaPlayer = null;
- currentPosition = 0;
- }
- System.gc();
- }
- }
[html] view plain copy
- <uses-permission android:name="android.permission.INTERNET" />
0 0
- Android播放远程非流MP4文件
- Android视频播放器---播放远程非流MP4
- Android 播放MP4文件
- Android中播放MP4文件
- Cocos2dx播放mp4文件(IOS和Android)
- Cocos2dx播放mp4文件(IOS和Android)
- mp4文件播放不了
- 网页中播放mp4文件
- Mp4文件播放原理分析
- android 播放工程中的MP4
- Android VideoView播放MP4视频文件
- android 自定义MP4播放器
- Android GIF播放,MP4资源播放笔记
- ffmpeg 3.2版本播放ts流正常,但是录制成为MP4的文件播放黑屏
- GStreamer播放mp4文件所需插件
- html5 无法播放部分 mp4文件
- 播放res/raw文件(MP4)
- 实现MP4文件边下载边播放
- STM —— 软件事务性内存
- 曝国安苏宁争夺威尔士当红前锋 开价500万镑年薪
- Entry是什么类型?
- LVS 工作模式以及工作原理
- 杭电2544 dijkstra 最短路
- Android播放远程非流MP4文件
- queue,deque
- Eclipse插件卸载
- 从输入一个URL开始后台发生什么
- Android横竖屏切换总结
- JavaScript--事件模型
- 线程安全的单例模式
- 使用Hibernate生成数据库和连接数据库
- 解决Setting property 'source' to 'org.eclipse.jst.jee.server的问题