Android SurfaceView+MediaPlayer 本地视频播放器

功能情景:

       1.播放视频文件

       2.上一首,下一首

       3.卡拉ok功能(只是单纯的用系统mediaplayer切换声道,资源必须要含有三种声道的mkv文件(2,1,1))

           也就是特定资源才有用,虽然是播客对我来说只是月度总结,但我不想误导别人

       4.播放模式(顺序,随机,循环)

效果图


功能的实现:

       1.伴唱功能:(这里是mkv文件切换声道),伴唱转AUDIO,原唱转VIDEO。当然前提是先获得mkv文件的所有声道。

我在视频准备的时候获取所有声道,然后判断是否有这个声道我再转。

    @Override
    public void onPrepared(MediaPlayer mediaPlayer) {
        //视频播放
        mMediaPlayer.start();
        //获取视屏的长度
        tv_video.setText(ProjectUtils.formatTime(mMediaPlayer.getDuration()));
        // mIsStopped = false;
        if (iv_play != null) {
            iv_play.setSelected(false);
        }

        //获取所有的音轨
        trackInfo = mMediaPlayer.getTrackInfo();

    }

       //伴唱与原唱
        RxView.clicks(iv_sing_state).throttleFirst(2, TimeUnit.SECONDS).subscribe(new Action1<Void>() {
            @Override
            public void call(Void aVoid) {
                int pos = fileName.lastIndexOf('.');
                if (pos != -1) {
                    String indexName = fileName.substring(pos);
                    if (indexName.equalsIgnoreCase(".mkv")) {
                        if (trackInfo != null) {
                            Logger.i("fileName" + fileName);
                            mMediaPlayer.selectTrack(MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO);

                        }
                        if (!iv_sing_state.isSelected()){
                            boolean flag=false;
                            for (int i = 0; i < trackInfo.length; i++) {
                                if (trackInfo[i].getTrackType()== MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO){
                                    flag=true;
                                }
                            }
                            if (flag){
                                //切换音轨(伴唱)
                                if (mMediaPlayer!=null){
                                    mMediaPlayer.selectTrack(MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO);
                                }
                            }
                            iv_sing_state.setSelected(true);
                            
                        }else{
                            boolean flag=false;
                            for (int i = 0; i < trackInfo.length; i++) {
                                if (trackInfo[i].getTrackType()== MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_VIDEO ){
                                    flag=true;
                                }
                            }

                            if (flag){
                                //原唱
                                if (mMediaPlayer!=null){
                                    mMediaPlayer.selectTrack(MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_VIDEO);
                                }
                            }
                            iv_sing_state.setSelected(false);

                        }
                        
                    }else{

                        Toast.makeText(VideoPalyActivity.this,"不是卡拉OK文件,不具备伴唱功能",Toast.LENGTH_SHORT).show();
                    }
                }
            }
        });

2.播放模式

          随机模式的算法:当切换到随机模式时,先移除掉当前播放的数据,然后播放下一首的时候,从剩余的随机一条,然后再移除,再随机。知道没有数据,没有数据的时候再从新复制总数据。这里注意的是,可移除的数据集合必然是克隆原先数据集合的,而不是简单的复制(注意java的数据存储)

        //播放模式的切换
        RxView.clicks(iv_state).throttleFirst(2, TimeUnit.SECONDS).subscribe(new Action1<Void>() {
            @Override
            public void call(Void aVoid) {

                if (playMode == 1) {
                    playMode = 2;//随机模式
                    Toast.makeText(VideoPalyActivity.this, "随机模式", Toast.LENGTH_SHORT).show();
                    iv_state.setImageResource(R.drawable.iv_state_suiji_press);
                } else if (playMode == 2) {
                    playMode = 3;//循环模式
                    Toast.makeText(VideoPalyActivity.this, "循环模式", Toast.LENGTH_SHORT).show();

                    iv_state.setImageResource(R.drawable.iv_state_xunhuan_press);
                } else if (playMode == 3) {
                    playMode = 1;//顺序模式
                    Toast.makeText(VideoPalyActivity.this, "顺序模式", Toast.LENGTH_SHORT).show();
                    iv_state.setImageResource(R.drawable.iv_state_shunxu_press);
                }

            }
        });


播放模式要有效果必然要在播放完成下写算法


 @Override
    public void onCompletion(MediaPlayer mp) {
        Toast.makeText(VideoPalyActivity.this, "播放完毕", Toast.LENGTH_SHORT).show();
        seekBar.setProgress(100);
        RxUtils.unsubscribe(seekBarSubscription);
        if (iv_play != null) {
            iv_play.setSelected(true);
        }
        
        if (playMode == 1) {
            Logger.i(TAG, "播放完毕进入顺序模式");
            if (currentPos < data.size()) {
                currentPos++;
                Logger.i("随机::666" + "currentPos=" + currentPos);

                if (currentPos<data.size()){
                    mVideoPath = data.get(currentPos).getAbsolutePath();
                    Logger.i("随机::666" + "mVideoPath=" + mVideoPath);
                    fileName = data.get(currentPos).getName();
                }

            }

        } else if (playMode == 2) {
            Logger.i(TAG, "播放完毕进入随机模式");

            if (copydata.size() != 0) {
                int pos = -1;
                for (int i = 0; i < copydata.size(); i++) {
                    if (copydata.get(i).getAbsolutePath().equals(mVideoPath)) {
                        pos = i;
                    }
                }

                if (pos != -1 && pos < copydata.size()) {
                    copydata.remove(pos);
                }

                int max = copydata.size();
                int min = 0;
                Random random = new Random();
                int rNum = random.nextInt(max) % (max - min + 1) + min;
                mVideoPath = copydata.get(rNum).getAbsolutePath();
                fileName = copydata.get(rNum).getName();

                // mVideoPath = copydata.get(rNum).getFilepath();
                for (int i = 0; i < data.size(); i++) {
                    if (data.get(i).getAbsolutePath().equals(copydata.get(rNum).getAbsolutePath())) {
                        currentPos = i;
                    }
                }
                Logger.i("随机::555" + "currentPos=" + currentPos);
                mVideoPath = data.get(currentPos).getAbsolutePath();
                fileName = data.get(currentPos).getName();
                Logger.i("随机::555" + "mVideoPath=" + mVideoPath);
                copydata.remove(rNum);

            } else {
                copydata = (ArrayList<File>) data.clone();
            }


        } else if (playMode == 3) {
            Logger.i(TAG, "播放完毕进入循环模式");
            Logger.i("随机::777" + "currentPos=" + currentPos);
            Logger.i("随机::777" + "mVideoPath=" + mVideoPath);

        }
        prepare();
    }



附件:完整代码:

package com.wyt.hcy.leyuanindustryproject;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.jakewharton.rxbinding.view.RxView;
import com.orhanobut.logger.Logger;
import com.wyt.db.bean.BrowseLog;

import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import database.DbUtils;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
import utils.ActivityUtils;
import utils.ProjectUtils;
import utils.RxUtils;

/**
 * 屏保不执行任何activity的生命周期
 */


public class VideoPalyActivity extends BaseActivity implements SurfaceHolder.Callback, MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, MediaPlayer.OnInfoListener, MediaPlayer.OnBufferingUpdateListener {

    private ImageView iv_back;
    private ImageView iv_battery;
    private SurfaceView mSurfaceView;
    private MediaPlayer mMediaPlayer;
    private static final String TAG = "VideoPalyActivity";
    private String mVideoPath;
    private TextView tv_video;
    private ImageView iv_play;
    private ImageView iv_previous;
    private ImageView iv_next;
    private static int currentPos = 0;
    private ArrayList<File> data;
    private ArrayList<File> copydata;
    private ImageView 
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你好,关于使用MediaPlayerSurfaceView播放视频,可以按照以下步骤进行: 1. 在XML布局文件中添加SurfaceView控件: ``` <SurfaceView android:id="@+id/surface_view" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 2. 在Java代码中获取SurfaceView控件,创建MediaPlayer对象,并设置相关监听器: ``` // 获取SurfaceView控件 SurfaceView surfaceView = findViewById(R.id.surface_view); // 创建MediaPlayer对象 MediaPlayer mediaPlayer = new MediaPlayer(); // 设置SurfaceView作为MediaPlayer的显示界面 mediaPlayer.setDisplay(surfaceView.getHolder()); // 设置MediaPlayer的一些监听器 mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { // 视频准备完成后自动播放 mp.start(); } }); mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { // 视频播放完成后的处理 } }); mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { // MediaPlayer出错时的处理 return false; } }); ``` 3. 设置MediaPlayer的数据源、准备视频等操作: ``` try { // 设置MediaPlayer的数据源 mediaPlayer.setDataSource("video_path"); // 准备视频 mediaPlayer.prepare(); } catch (IOException e) { e.printStackTrace(); } ``` 4. 在需要的地方控制视频的播放、暂停、停止操作: ``` // 播放视频 mediaPlayer.start(); // 暂停视频 mediaPlayer.pause(); // 停止视频 mediaPlayer.stop(); ``` 希望以上步骤能帮到您。若有疑问,请随时咨询。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值