功能情景:
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