|  | @@ -0,0 +1,313 @@
 | 
	
		
			
				|  |  | +package com.haochuan.hciptvbasic.test;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import androidx.appcompat.app.AlertDialog;
 | 
	
		
			
				|  |  | +import androidx.appcompat.app.AppCompatActivity;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import android.app.Activity;
 | 
	
		
			
				|  |  | +import android.app.Application;
 | 
	
		
			
				|  |  | +import android.content.DialogInterface;
 | 
	
		
			
				|  |  | +import android.os.Bundle;
 | 
	
		
			
				|  |  | +import android.util.Log;
 | 
	
		
			
				|  |  | +import android.view.KeyEvent;
 | 
	
		
			
				|  |  | +import android.view.View;
 | 
	
		
			
				|  |  | +import android.widget.LinearLayout;
 | 
	
		
			
				|  |  | +import android.widget.ProgressBar;
 | 
	
		
			
				|  |  | +import android.widget.SeekBar;
 | 
	
		
			
				|  |  | +import android.widget.TextView;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import com.haochuan.hciptvbasic.R;
 | 
	
		
			
				|  |  | +import com.haochuan.hciptvbasic.Util.Logger;
 | 
	
		
			
				|  |  | +import com.haochuan.hciptvbasic.video.HCPlayer;
 | 
	
		
			
				|  |  | +import com.haochuan.hciptvbasic.video.IVideoPlayer;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import java.math.BigDecimal;
 | 
	
		
			
				|  |  | +import java.util.Formatter;
 | 
	
		
			
				|  |  | +import java.util.Locale;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +public class TestPlayerActivity extends AppCompatActivity implements IVideoPlayer {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //页面组件对象
 | 
	
		
			
				|  |  | +    private HCPlayer hcPlayer;
 | 
	
		
			
				|  |  | +    private ProgressBar loadingBar;
 | 
	
		
			
				|  |  | +    private LinearLayout bottomContainer;
 | 
	
		
			
				|  |  | +    private SeekBar videoProgressBar;
 | 
	
		
			
				|  |  | +    private TextView showTimeView;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //全局参数
 | 
	
		
			
				|  |  | +    private String testUrl = "https://gzhc-sxrj.oss-cn-shenzhen.aliyuncs.com/gzhc-djbl/djbl01.mp4";
 | 
	
		
			
				|  |  | +    private int duration = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    protected void onCreate(Bundle savedInstanceState) {
 | 
	
		
			
				|  |  | +        super.onCreate(savedInstanceState);
 | 
	
		
			
				|  |  | +        setContentView(R.layout.activity_test_player);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        hcPlayer = findViewById(R.id.hc_player);
 | 
	
		
			
				|  |  | +        loadingBar = findViewById(R.id.loading);
 | 
	
		
			
				|  |  | +        bottomContainer = findViewById(R.id.layout_bottom);
 | 
	
		
			
				|  |  | +        videoProgressBar = findViewById(R.id.progress_bar);
 | 
	
		
			
				|  |  | +        showTimeView = findViewById(R.id.current_total);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        loadingBar.setMax(100);
 | 
	
		
			
				|  |  | +        loadingBar.setProgress(0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        hcPlayer.setIVideoPlayerListener(this);
 | 
	
		
			
				|  |  | +        hcPlayer.play(testUrl);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public boolean dispatchKeyEvent(KeyEvent event) {
 | 
	
		
			
				|  |  | +        int keyCode = event.getKeyCode();
 | 
	
		
			
				|  |  | +        switch (keyCode){
 | 
	
		
			
				|  |  | +            case KeyEvent.KEYCODE_DPAD_LEFT:
 | 
	
		
			
				|  |  | +                if(event.getAction() == KeyEvent.ACTION_DOWN){
 | 
	
		
			
				|  |  | +                    seekForward();
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                return true;
 | 
	
		
			
				|  |  | +            case KeyEvent.KEYCODE_DPAD_RIGHT:
 | 
	
		
			
				|  |  | +                if(event.getAction() == KeyEvent.ACTION_DOWN){
 | 
	
		
			
				|  |  | +                    seekBack();
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                return true;
 | 
	
		
			
				|  |  | +            case KeyEvent.KEYCODE_DPAD_DOWN:
 | 
	
		
			
				|  |  | +                if(event.getAction() == KeyEvent.ACTION_DOWN){
 | 
	
		
			
				|  |  | +                    showBottomContainer();
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            case KeyEvent.KEYCODE_DPAD_CENTER:
 | 
	
		
			
				|  |  | +                if(event.getAction() == KeyEvent.ACTION_DOWN){
 | 
	
		
			
				|  |  | +                    playOrPause();
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            case KeyEvent.KEYCODE_ENTER:
 | 
	
		
			
				|  |  | +                if(event.getAction() == KeyEvent.ACTION_DOWN){
 | 
	
		
			
				|  |  | +                    playOrPause();
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            case KeyEvent.KEYCODE_BACK:
 | 
	
		
			
				|  |  | +                showExitDialog();
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            default:
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return super.dispatchKeyEvent(event);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /*------------------------------具体功能实现------------------------------*/
 | 
	
		
			
				|  |  | +    //向前拖动
 | 
	
		
			
				|  |  | +    private void seekForward(){
 | 
	
		
			
				|  |  | +        hcPlayer.seek(hcPlayer.getCurrentPlayPosition() + 1000);
 | 
	
		
			
				|  |  | +        showBottomContainer();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //向后拖动
 | 
	
		
			
				|  |  | +    private void seekBack(){
 | 
	
		
			
				|  |  | +        hcPlayer.seek(hcPlayer.getCurrentPlayPosition() - 1000);
 | 
	
		
			
				|  |  | +        showBottomContainer();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //暂停或者启动
 | 
	
		
			
				|  |  | +    private void playOrPause(){
 | 
	
		
			
				|  |  | +        if(hcPlayer.isPrePared()){
 | 
	
		
			
				|  |  | +            if(hcPlayer.isPlaying()){
 | 
	
		
			
				|  |  | +                hcPlayer.pause();
 | 
	
		
			
				|  |  | +                Logger.d("playOrPause,暂停");
 | 
	
		
			
				|  |  | +                showBottomContainer();
 | 
	
		
			
				|  |  | +            }else{
 | 
	
		
			
				|  |  | +                hcPlayer.resume();
 | 
	
		
			
				|  |  | +                Logger.d("playOrPause,恢复播放");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //显示底部容器
 | 
	
		
			
				|  |  | +    private void showBottomContainer(){
 | 
	
		
			
				|  |  | +        bottomContainer.setVisibility(View.VISIBLE);
 | 
	
		
			
				|  |  | +        //开始刷新底部容器里的进度条进度和播放时间
 | 
	
		
			
				|  |  | +        refreshProgressAndTimeImmed();
 | 
	
		
			
				|  |  | +        //延迟3秒后隐藏
 | 
	
		
			
				|  |  | +        hideBottomContainerDelay();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //立即刷新进度和时间
 | 
	
		
			
				|  |  | +    private void refreshProgressAndTimeImmed(){
 | 
	
		
			
				|  |  | +        hcPlayer.getRootView().post(showProgressAndTimeRunnable);
 | 
	
		
			
				|  |  | +        refreshProgressAndTime();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private void refreshProgressAndTime(){
 | 
	
		
			
				|  |  | +        hcPlayer.getRootView().postDelayed(showProgressAndTimeRunnable,500L);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //延迟三秒隐藏底部容器
 | 
	
		
			
				|  |  | +    private void hideBottomContainerDelay(){
 | 
	
		
			
				|  |  | +        hcPlayer.getRootView().postDelayed(new Runnable() {
 | 
	
		
			
				|  |  | +            @Override
 | 
	
		
			
				|  |  | +            public void run() {
 | 
	
		
			
				|  |  | +                hideBottomContainer();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        },5000L);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //隐藏底部容器
 | 
	
		
			
				|  |  | +    private void hideBottomContainer(){
 | 
	
		
			
				|  |  | +        bottomContainer.setVisibility(View.INVISIBLE);
 | 
	
		
			
				|  |  | +        //开始刷新底部容器里的进度条进度和播放时间
 | 
	
		
			
				|  |  | +        hcPlayer.getRootView().removeCallbacks(showProgressAndTimeRunnable);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //显示退出框
 | 
	
		
			
				|  |  | +    private void showExitDialog(){
 | 
	
		
			
				|  |  | +        new AlertDialog.Builder(this)
 | 
	
		
			
				|  |  | +                .setTitle("退出")
 | 
	
		
			
				|  |  | +                .setMessage("确认退出吗?")
 | 
	
		
			
				|  |  | +                .setNegativeButton("重播", new DialogInterface.OnClickListener() {
 | 
	
		
			
				|  |  | +            @Override
 | 
	
		
			
				|  |  | +            public void onClick(DialogInterface dialog, int which) {
 | 
	
		
			
				|  |  | +                hcPlayer.play(testUrl);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }).setPositiveButton("退出", new DialogInterface.OnClickListener() {
 | 
	
		
			
				|  |  | +            @Override
 | 
	
		
			
				|  |  | +            public void onClick(DialogInterface dialog, int which) {
 | 
	
		
			
				|  |  | +                TestPlayerActivity.this.runOnUiThread(() -> {
 | 
	
		
			
				|  |  | +                    android.os.Process.killProcess(android.os.Process.myPid());   //获取PID
 | 
	
		
			
				|  |  | +                    System.exit(0);
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }).show();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //将毫秒转为hh:mm:ss格式
 | 
	
		
			
				|  |  | +    public static String timeToString(long timeMs) {
 | 
	
		
			
				|  |  | +        if (timeMs <= 0 || timeMs >= 24 * 60 * 60 * 1000) {
 | 
	
		
			
				|  |  | +            return "00:00";
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        long totalSeconds = timeMs / 1000;
 | 
	
		
			
				|  |  | +        long seconds = totalSeconds % 60;
 | 
	
		
			
				|  |  | +        long minutes = (totalSeconds / 60) % 60;
 | 
	
		
			
				|  |  | +        long hours = totalSeconds / 3600;
 | 
	
		
			
				|  |  | +        StringBuilder stringBuilder = new StringBuilder();
 | 
	
		
			
				|  |  | +        Formatter mFormatter = new Formatter(stringBuilder, Locale.getDefault());
 | 
	
		
			
				|  |  | +        if (hours > 0) {
 | 
	
		
			
				|  |  | +            return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            return mFormatter.format("%02d:%02d", minutes, seconds).toString();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取比例
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param current 分子
 | 
	
		
			
				|  |  | +     * @param max     分母
 | 
	
		
			
				|  |  | +     * @return 比例(0-100)
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static int percent(long current, long max) {
 | 
	
		
			
				|  |  | +        Logger.d(String.format("current:%s,max:%s",current,max));
 | 
	
		
			
				|  |  | +        return (int) (halfUp((float) current / max, 2) * zeroCountToNum(2));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 根据count值得到1(count个数的0)的数。例如count为2,则得到100,count为1则得到10,count小于0则得到1
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param count 1后补增的0个数
 | 
	
		
			
				|  |  | +     * @return long
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static long zeroCountToNum(int count) {
 | 
	
		
			
				|  |  | +        long num = 1;
 | 
	
		
			
				|  |  | +        if (count <= 0) {
 | 
	
		
			
				|  |  | +            return num;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        for (int i = 1; i <= count; i++) {
 | 
	
		
			
				|  |  | +            num *= 10;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return num;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取四舍五入的值
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param value    需要转换的数值
 | 
	
		
			
				|  |  | +     * @param newScale 小数点保留位数
 | 
	
		
			
				|  |  | +     * @return 四舍五入后的值。
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static float halfUp(float value, int newScale) {
 | 
	
		
			
				|  |  | +        return getBigDecimal(value, newScale, BigDecimal.ROUND_HALF_UP);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private static float getBigDecimal(float value, int newScale, int roundingMode) {
 | 
	
		
			
				|  |  | +        BigDecimal bigDecimal = new BigDecimal(value);
 | 
	
		
			
				|  |  | +        return bigDecimal.setScale(newScale, roundingMode).floatValue();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /*------------------------Runnable--------------------------*/
 | 
	
		
			
				|  |  | +    private Runnable showProgressAndTimeRunnable =new Runnable() {
 | 
	
		
			
				|  |  | +        @Override
 | 
	
		
			
				|  |  | +        public void run() {
 | 
	
		
			
				|  |  | +            int currentPosition =hcPlayer.getCurrentPlayPosition();
 | 
	
		
			
				|  |  | +            Logger.d("currentPosition:" + currentPosition);
 | 
	
		
			
				|  |  | +            //显示右边时间进度
 | 
	
		
			
				|  |  | +            StringBuilder sb = new StringBuilder();
 | 
	
		
			
				|  |  | +            sb.append(timeToString(currentPosition));
 | 
	
		
			
				|  |  | +            sb.append("/");
 | 
	
		
			
				|  |  | +            sb.append(timeToString(duration));
 | 
	
		
			
				|  |  | +            showTimeView.setText(sb.toString());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //显示进度条
 | 
	
		
			
				|  |  | +            videoProgressBar.setProgress(percent(currentPosition,duration));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            refreshProgressAndTime();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /*--------------------IVideoPlayer 接口实现---------------------*/
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public void onPreparing() {
 | 
	
		
			
				|  |  | +        loadingBar.setVisibility(View.VISIBLE);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public void onPlaying() {
 | 
	
		
			
				|  |  | +        loadingBar.setVisibility(View.GONE);
 | 
	
		
			
				|  |  | +        duration = hcPlayer.getDuration();
 | 
	
		
			
				|  |  | +        Logger.d("duration:" + duration);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public void onResume() {
 | 
	
		
			
				|  |  | +        super.onResume();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public void onPause() {
 | 
	
		
			
				|  |  | +        super.onPause();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public void onDestroy() {
 | 
	
		
			
				|  |  | +        super.onDestroy();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public void onPlayingBuffering() {
 | 
	
		
			
				|  |  | +        loadingBar.setVisibility(View.VISIBLE);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public void onCompletion() {
 | 
	
		
			
				|  |  | +        showExitDialog();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public void onError(int what, int extra) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 |