Android开发-基于ijkplayer框架开发网络电视直播播放器的实现

  • Post author:
  • Post category:其他




前 言

ijkplayer框架是由B站在GitHub开源的一款比较好用的开源网络播放器框架,它能支持在Android、IOS等平台上编译移植使用。而且支持多种视频格式的播放,而且编码的速度比传统的开源网络播放器还要快。除此之外,ijkplayer框架支持网络视频播放时弹幕的推送等功能。



开发环境

Android Studio 3.1.2

JDK 1.8



开发前准备

在Android Studio新建的项目里引入ijkplayer框架(

ijkplayer框架GitHub下载地址

)作为依赖项,并在build.gradle(Module:app)引入文件。如下图所示。

这里写图片描述

implementation project(':ijkplayer-java')

在主项目的下\app\src\main\目录下新建一个jniLibs目录,并把ijkplayer框架需要支持的.so文件拷贝粘贴进去,如下图所示。

这里写图片描述



编码与实现

在Android Studio的\res\layout目录下新建一个activity_play.xml文件作为视频播放器的显示界面,布局代码如下。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_play"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black"
    android:gravity="center"
    android:keepScreenOn="true"
    tools:context=".player.PlayActivity">

    <FrameLayout
        android:id="@+id/fl_surface_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.fukaimei.cloudtv.widget.media.IjkVideoView
            android:id="@+id/video_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center" />

        <RelativeLayout
            android:id="@+id/rl_loading_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:id="@+id/tv_loading_info"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/pb_loading"
                android:layout_centerInParent="true"
                android:layout_marginTop="@dimen/dimen_12dp"
                android:textColor="@color/white"
                android:textSize="@dimen/dimen_32sp" />

            <!--android:indeterminate 表示不确定的进度-->
            <ProgressBar
                android:id="@+id/pb_loading"
                android:layout_width="@dimen/dimen_120dp"
                android:layout_height="@dimen/dimen_120dp"
                android:layout_centerInParent="true"
                android:layout_marginTop="@dimen/dimen_120dp"
                android:indeterminate="false"
                android:indeterminateDrawable="@drawable/video_loading"
                android:padding="@dimen/dimen_10dp" />


        </RelativeLayout>

        <TextView
            android:id="@+id/tv_horiontal_gesture"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:shadowColor="@color/black"
            android:shadowDx="1.0"
            android:shadowDy="1.0"
            android:textColor="@color/white"
            android:textSize="@dimen/dimen_64sp"
            android:textStyle="bold"
            android:visibility="gone" />

        <TextView
            android:id="@+id/tv_vertical_gesture"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:background="@drawable/black_bg"
            android:gravity="center_horizontal"
            android:paddingBottom="@dimen/dimen_40dp"
            android:paddingLeft="@dimen/dimen_100dp"
            android:paddingRight="@dimen/dimen_100dp"
            android:paddingTop="@dimen/dimen_40dp"
            android:textColor="@color/white"
            android:textSize="@dimen/dimen_64sp"
            android:textStyle="bold"
            android:visibility="gone" />

        <FrameLayout
            android:id="@+id/fl_player_top_container"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dimen_70dp"
            android:layout_gravity="top"
            android:background="@color/player_panel_background_color"
            android:paddingBottom="@dimen/dimen_10dp"
            android:paddingTop="@dimen/dimen_10dp">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:orientation="horizontal">

                <ImageView
                    android:id="@+id/iv_player_close"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:paddingLeft="@dimen/dimen_15dp"
                    android:paddingRight="@dimen/dimen_15dp"
                    android:src="@drawable/titlebar_return_white" />

                <TextView
                    android:id="@+id/tv_player_video_name"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:ellipsize="end"
                    android:singleLine="true"
                    android:textColor="@color/white"
                    android:textSize="@dimen/dimen_32sp" />

            </LinearLayout>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right|center_vertical"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/tv_sys_time"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:layout_marginRight="@dimen/dimen_10dp"
                    android:textColor="@color/white"
                    android:textSize="@dimen/dimen_32sp" />

                <ImageView
                    android:id="@+id/iv_battery"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:layout_marginRight="@dimen/dimen_10dp" />


            </LinearLayout>

        </FrameLayout>

        <ImageView
            android:id="@+id/iv_player_center_pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:background="@drawable/player_pause_selector"
            android:visibility="gone" />

    </FrameLayout>

    <LinearLayout
        android:id="@+id/ll_player_bottom_layout"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dimen_70dp"
        android:layout_alignParentBottom="true"
        android:background="@color/player_panel_background_color"
        android:gravity="center"
        android:orientation="horizontal">

        <CheckBox
            android:id="@+id/cb_play_pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/dimen_26dp"
            android:button="@drawable/player_playbtn_selector"
            android:checked="true" />

        <ImageView
            android:id="@+id/iv_next_video"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/dimen_10dp"
            android:src="@drawable/panel_next_selector" />

        <TextView
            android:id="@+id/tv_current_video_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:textColor="@color/white"
            android:textSize="@dimen/dimen_20sp" />

        <SeekBar
            android:id="@+id/sb_player_seekbar"
            style="@style/playerSeekBarStyle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="1.0"
            android:indeterminate="false"
            android:max="100"
            android:paddingLeft="@dimen/dimen_10dp"
            android:paddingRight="@dimen/dimen_10dp"
            android:progress="0"
            android:thumbOffset="@dimen/dimen_10dp" />

        <TextView
            android:id="@+id/tv_total_video_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/dimen_10dp"
            android:textColor="@color/white"
            android:textSize="@dimen/dimen_20sp" />

        <TextView
            android:id="@+id/tv_bitstream"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/dimen_10dp"
            android:layout_marginRight="@dimen/dimen_10dp"
            android:textColor="@color/white"
            android:textSize="@dimen/dimen_20sp" />

    </LinearLayout>
</RelativeLayout>

在Android Studio的app\src\main\java\目录下新建一个PlayActivity,java文件作为处理视频播放器的逻辑代码,逻辑代码如下。

package com.fukaimei.cloudtv.player;

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.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.preference.PreferenceManager;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;

import com.fukaimei.cloudtv.R;
import com.fukaimei.cloudtv.base.BaseActivity;
//import com.fukaimei.cloudtv.detail.AlbumDetailActivity;
//import com.fukaimei.cloudtv.model.sohu.Video;
import com.fukaimei.cloudtv.utils.DateUtils;
import com.fukaimei.cloudtv.utils.SysUtils;
import com.fukaimei.cloudtv.widget.media.IjkVideoView;

import java.text.NumberFormat;
import java.util.Formatter;
import java.util.Locale;

import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;

public class PlayActivity extends BaseActivity implements GestureDetectorController.IGestureListener {

    private static final String TAG = PlayActivity.class.getSimpleName();
    private static final int CHECK_TIME = 1;
    private static final int CHECK_BATTERY = 2;
    private static final int CHECK_PROGRESS = 3;
    private static final int AUTO_HIDE_TIME = 10000;
    private static final int AFTER_DRAGGLE_HIDE_TIME = 3000;
    private String mUrl;
    private int mStreamType;
    private int mCurrentPosition;
//    private Video mVideo;
    private IjkVideoView mVideoView;
    private RelativeLayout mLoadingLayout;
    private TextView mLoadingText;
    private FrameLayout mTopLayout;
    private LinearLayout mBottomLayout;
    private ImageView mBackButton;
    private TextView mVideoNameView;
    private TextView mSysTimeView;
    private ImageView mBigPauseButton;
    private CheckBox mPlayOrPauseButton;
    private TextView mVideoCurrentTime;
    private TextView mVideoTotalTime;
    private TextView mBitStreamView;
    private EventHandler mEventHandler;
    private boolean mIsPanelShowing = false;
    private int mBatteryLevel;
    private ImageView mBatteryView;
    private boolean mIsMove = false;//是否在屏幕上滑动
    private SeekBar mSeekBar;
    private Formatter mFormatter;
    private StringBuilder mFormatterBuilder;
    private boolean mIsDragging;
    private GestureDetectorController mGestureController;
    private TextView mDragHorizontalView;
    private TextView mDragVerticalView;
    private long mScrollProgress;
    private boolean mIsHorizontalScroll;
    private boolean mIsVerticalScroll;
    private int mCurrentLight;
    private int mMaxLight = 255;
    private int mCurrentVolume;
    private int mMaxVolume = 10;
    private AudioManager mAudioManager;
    private String mLiveTitle;//直播节目标题

    @Override
    protected int getLayoutId() {
        return R.layout.activity_play;
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mBatteryReceiver != null) {
            unregisterReceiver(mBatteryReceiver);
            mBatteryReceiver = null;
        }
        //释放audiofocus
        mAudioManager.abandonAudioFocus(null);
    }

    /**
     * 通过广播获取系统电量情况
     */
    private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            mBatteryLevel = intent.getIntExtra("level", 0);
            Log.d(TAG, ">> mBatteryReceiver onReceive mBatteryLevel=" + mBatteryLevel);
        }
    };

    @Override
    public void onScrollStart(GestureDetectorController.ScrollType type) {
        mIsMove = true;
        switch (type) {
            case HORIZONTAL:
                mDragHorizontalView.setVisibility(View.VISIBLE);
                mScrollProgress = -1;
                mIsHorizontalScroll = true;//水平滑动标识
                break;
            case VERTICAL_LEFT:
                setComposeDrawableAndText(mDragVerticalView, R.drawable.ic_light, this);
                mDragVerticalView.setVisibility(View.VISIBLE);
                updateVerticalText(mCurrentLight, mMaxLight);
                mIsVerticalScroll = true;
                break;
            case VERTICAL_RIGH:
                if (mCurrentVolume > 0) {
                    setComposeDrawableAndText(mDragVerticalView, R.drawable.volume_normal, this);
                } else {
                    setComposeDrawableAndText(mDragVerticalView, R.drawable.volume_no, this);
                }
                mDragVerticalView.setVisibility(View.VISIBLE);
                updateVerticalText(mCurrentVolume, mMaxVolume);
                mIsVerticalScroll = true;
                break;
        }
    }

    //用于组合图片及文字
    private void setComposeDrawableAndText(TextView textView, int drawableId, Context context) {
        Drawable drawable = context.getResources().getDrawable(drawableId);
        //这四个参数表示把drawable绘制在矩形区域
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        //设置图片在文字的上方
        //The Drawables must already have had drawable.setBounds called.
        textView.setCompoundDrawables(null, drawable, null, null);
    }

    //更新垂直方向上滑动时的百分比
    private void updateVerticalText(int current, int total) {
        NumberFormat formater = NumberFormat.getPercentInstance();
        formater.setMaximumFractionDigits(0);//设置整数部分允许最大小数位 66.5%->66%
        String percent = formater.format((double) (current) / (double) total);
        mDragVerticalView.setText(percent);
    }

    //更新水平方向seek的进度, duration表示变化后的duration
    private void updateHorizontalText(long duration) {
        String text = stringForTime((int) duration) + "/" + stringForTime(mVideoView.getDuration());
        mDragHorizontalView.setText(text);
    }

    // 更新进度
    @Override
    public void onScrollHorizontal(float x1, float x2) {
        int width = getResources().getDisplayMetrics().widthPixels;
        int MAX_SEEK_STEP = 300000;//最大滑动5分钟
        int offset = (int) (x2 / width * MAX_SEEK_STEP) + mVideoView.getCurrentPosition();
        long progress = Math.max(0, Math.min(mVideoView.getDuration(), offset));
        mScrollProgress = progress;
        updateHorizontalText(progress);
    }

    @Override
    public void onScrollVerticalLeft(float y1, float y2) {
        int height = getResources().getDisplayMetrics().heightPixels;
        int offset = (int) (mMaxLight * y1) / height;
        if (Math.abs(offset) > 0) {
            mCurrentLight += offset;//得到变化后的亮度
            mCurrentLight = Math.max(0, Math.min(mMaxLight, mCurrentLight));
            // 更新系统亮度
            SysUtils.setBrightness(this, mCurrentLight);
            SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
            editor.putInt("shared_preferences_light", mCurrentLight);
            editor.commit();
            updateVerticalText(mCurrentLight, mMaxLight);
        }
    }

    @Override
    public void onScrollVerticalRight(float y1, float y2) {
        int height = getResources().getDisplayMetrics().heightPixels;
        int offset = (int) (mMaxVolume * y1) / height;
        if (Math.abs(offset) > 0) {
            mCurrentVolume += offset;//得到变化后的声音
            mCurrentVolume = Math.max(0, Math.min(mMaxVolume, mCurrentVolume));
            // 更新系统声音
            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mCurrentVolume / 10, 0);
            updateVerticalText(mCurrentVolume, mMaxVolume);
        }
    }

    class EventHandler extends Handler {
        public EventHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case CHECK_TIME:
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mSysTimeView.setText(DateUtils.getCurrentTime());
                        }
                    });
                    break;
                case CHECK_BATTERY:
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            setCurrentBattery();
                        }
                    });
                    break;
                case CHECK_PROGRESS:
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            long duration = mVideoView.getDuration();
                            long nowduration = (mSeekBar.getProgress() * duration) / 1000L;
                            mVideoCurrentTime.setText(stringForTime((int) nowduration));
                        }
                    });
                    break;
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            if (mIsMove == false) {
                toggleTopAndBottomLayout();
            } else {
                mIsMove = false;
            }
            //水平方向,up时,seek到对应位置播放
            if (mIsHorizontalScroll) {
                mIsHorizontalScroll = false;
                mVideoView.seekTo((int) mScrollProgress);
                //一次down,up结束后mDragHorizontalView隐藏
                mDragHorizontalView.setVisibility(View.GONE);
            }
            if (mIsVerticalScroll) {
                mDragVerticalView.setVisibility(View.GONE);
                mIsVerticalScroll = false;
            }
        }
        return mGestureController.onTouchEvent(event);
    }

    @Override
    protected void initView() {
        mUrl = getIntent().getStringExtra("url");
//        mUrl = "http://ivi.bupt.edu.cn/hls/cctv1.m3u8";
//        mLiveTitle = "CCTV-1综合";
        mLiveTitle = getIntent().getStringExtra("title");
        mStreamType = getIntent().getIntExtra("type", 0);
        mCurrentPosition = getIntent().getIntExtra("currentPosition", 0);
//        mVideo = getIntent().getParcelableExtra("video");
//        Log.d(TAG, ">> ulr " + mUrl + ", mStreamType " + mStreamType + ", mCurrentPosition " + mCurrentPosition);
//        Log.d(TAG, ">> video " + mVideo);
        mEventHandler = new EventHandler(Looper.myLooper());
        initAudio();
        initLight();
        initGesture();
        initTopAndBottomView();
        initCenterView();
        initListener();
        //init player
        mVideoView = bindViewId(R.id.video_view);
        IjkMediaPlayer.loadLibrariesOnce(null);
        IjkMediaPlayer.native_profileBegin("libijkplayer.so");
        mLoadingLayout = bindViewId(R.id.rl_loading_layout);
        mLoadingText = bindViewId(R.id.tv_loading_info);
        mLoadingText.setText("正在加载中...");
        mVideoView.setVideoURI(Uri.parse(mUrl));
        mVideoView.setOnPreparedListener(new IMediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(IMediaPlayer mp) {
                mVideoView.start();
            }
        });
        mVideoView.setOnInfoListener(new IMediaPlayer.OnInfoListener() {
            @Override
            public boolean onInfo(IMediaPlayer mp, int what, int extra) {
                switch (what) {
                    case IjkMediaPlayer.MEDIA_INFO_BUFFERING_START:
                        mLoadingLayout.setVisibility(View.VISIBLE);
                        break;
                    case IjkMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:
                    case IjkMediaPlayer.MEDIA_INFO_BUFFERING_END:
                        mLoadingLayout.setVisibility(View.GONE);
                        break;
                }
                return false;
            }
        });
        registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
        toggleTopAndBottomLayout();
    }

    private void initCenterView() {
        mDragHorizontalView = bindViewId(R.id.tv_horiontal_gesture);
        mDragVerticalView = bindViewId(R.id.tv_vertical_gesture);
    }

    private void initAudio() {
        mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
        setVolumeControlStream(AudioManager.STREAM_MUSIC);
        mAudioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
        mMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) * 10;// 系统声音取值是0-10,*10为了和百分比相关
        mCurrentVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC) * 10;
    }

    private void initLight() {
        mCurrentLight = SysUtils.getDefaultBrightness(this);
        if (mCurrentLight == -1) {//获取不到亮度sharedpreferences文件
            mCurrentLight = SysUtils.getBrightness(this);
        }
    }

    private void initGesture() {
        mGestureController = new GestureDetectorController(this, this);
    }

    private void initTopAndBottomView() {
        mTopLayout = bindViewId(R.id.fl_player_top_container);
        mBottomLayout = bindViewId(R.id.ll_player_bottom_layout);
        mBackButton = bindViewId(R.id.iv_player_close);//返回按钮
        mVideoNameView = bindViewId(R.id.tv_player_video_name);//video标题
        mBatteryView = bindViewId(R.id.iv_battery);
        mSysTimeView = bindViewId(R.id.tv_sys_time);//系统时间
        mBigPauseButton = bindViewId(R.id.iv_player_center_pause);//屏幕中央暂停按钮
        mPlayOrPauseButton = bindViewId(R.id.cb_play_pause);//底部播放暂停按钮
        mVideoCurrentTime = bindViewId(R.id.tv_current_video_time);//当前播放进度
        mVideoTotalTime = bindViewId(R.id.tv_total_video_time);//视频总时长
        mBitStreamView = bindViewId(R.id.tv_bitstream);//码流
        mSeekBar = bindViewId(R.id.sb_player_seekbar);
        mSeekBar.setMax(1000);
        mSeekBar.setOnSeekBarChangeListener(mSeekBarChangeListener);
        mFormatterBuilder = new StringBuilder();
        mFormatter = new Formatter(mFormatterBuilder, Locale.getDefault());
    }

    private void initListener() {
        mBackButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        mBigPauseButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mVideoView.start();
                updatePlayPauseStatus(true);
            }
        });
        mPlayOrPauseButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                handlePlayPause();
            }
        });
    }

    private void toggleTopAndBottomLayout() {
        if (mIsPanelShowing) {
            hideTopAndBottomLayout();
        } else {
            showTopAndBottomLayout();
            //先显示,没有任何操作,就5s后隐藏
            mEventHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    hideTopAndBottomLayout();
                }
            }, AUTO_HIDE_TIME);
        }
    }

    private void showTopAndBottomLayout() {
        mIsPanelShowing = true;
        mTopLayout.setVisibility(View.VISIBLE);
        mBottomLayout.setVisibility(View.VISIBLE);
        updateProgress();
        if (mEventHandler != null) {
            mEventHandler.removeMessages(CHECK_TIME);
            Message msg = mEventHandler.obtainMessage(CHECK_TIME);
            mEventHandler.sendMessage(msg);

            mEventHandler.removeMessages(CHECK_BATTERY);
            Message batterymsg = mEventHandler.obtainMessage(CHECK_BATTERY);
            mEventHandler.sendMessage(batterymsg);

            mEventHandler.removeMessages(CHECK_PROGRESS);
            Message progressmsg = mEventHandler.obtainMessage(CHECK_PROGRESS);
            mEventHandler.sendMessage(progressmsg);
        }
        switch (mStreamType) {
//            case AlbumDetailActivity.StreamType.SUPER:
//                mBitStreamView.setText(getResources().getString(R.string.stream_super));
//                break;
//            case AlbumDetailActivity.StreamType.NORMAL:
//                mBitStreamView.setText(getResources().getString(R.string.stream_normal));
//                break;
//            case AlbumDetailActivity.StreamType.HIGH:
//                mBitStreamView.setText(getResources().getString(R.string.stream_high));
//                break;
            default:
                break;
        }
    }

    private void hideTopAndBottomLayout() {
        if (mIsDragging == true) {
            return;
        }
        mIsPanelShowing = false;
        mTopLayout.setVisibility(View.GONE);
        mBottomLayout.setVisibility(View.GONE);
    }

    private void handlePlayPause() {
        //TODO
        if (mVideoView.isPlaying()) {//视频正在播放
            mVideoView.pause();
            updatePlayPauseStatus(false);
        } else {
            mVideoView.start();
            updatePlayPauseStatus(true);
        }
    }

    private void updatePlayPauseStatus(boolean isPlaying) {
        mBigPauseButton.setVisibility(isPlaying ? View.GONE : View.VISIBLE);
        mPlayOrPauseButton.invalidate();
        mPlayOrPauseButton.setChecked(isPlaying);
        mPlayOrPauseButton.refreshDrawableState();
    }


    @Override
    protected void initData() {
//        Log.d(TAG, ">> initData mVideo=" + mVideo);
//        if (mVideo != null) {
//            Log.d(TAG, ">> initData mVideoName" + mVideo.getVideoName());
//            mVideoNameView.setText(mVideo.getVideoName());
//        }
        if (mLiveTitle != null) {
            mVideoNameView.setText(mLiveTitle);
        }
    }

    private void setCurrentBattery() {
        Log.d(TAG, ">> setCurrentBattery level " + mBatteryLevel);
        if (0 < mBatteryLevel && mBatteryLevel <= 10) {
            mBatteryView.setBackgroundResource(R.drawable.ic_battery_10);
        } else if (10 < mBatteryLevel && mBatteryLevel <= 20) {
            mBatteryView.setBackgroundResource(R.drawable.ic_battery_20);
        } else if (20 < mBatteryLevel && mBatteryLevel <= 50) {
            mBatteryView.setBackgroundResource(R.drawable.ic_battery_50);
        } else if (50 < mBatteryLevel && mBatteryLevel <= 80) {
            mBatteryView.setBackgroundResource(R.drawable.ic_battery_80);
        } else if (80 < mBatteryLevel && mBatteryLevel <= 100) {
            mBatteryView.setBackgroundResource(R.drawable.ic_battery_100);
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mVideoView != null) {
            mVideoView.stopPlayback();
        }
    }

    private SeekBar.OnSeekBarChangeListener mSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
        // seekbar进度发生变化时回调
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            if (!fromUser) {
                return;
            }
            long duration = mVideoView.getDuration();//视频时长
            long nowPosition = (duration * progress) / 1000L;
            mVideoCurrentTime.setText(stringForTime((int) nowPosition));
        }

        // seekbar开始拖动时回调
        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            mIsDragging = true;
        }

        // seekbar拖动完成后回调
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            mIsDragging = false;
            int progress = seekBar.getProgress();//最后拖动停止的进度
            long duration = mVideoView.getDuration();//视频时长
            long newPosition = (duration * progress) / 1000L;//当前的进度
            mVideoView.seekTo((int) newPosition);
            mEventHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    hideTopAndBottomLayout();
                }
            }, AFTER_DRAGGLE_HIDE_TIME);
        }
    };

    private void updateProgress() {
        int currentPosition = mVideoView.getCurrentPosition();//当前的视频位置
        int duration = mVideoView.getDuration();//视频时长
        if (mSeekBar != null) {
            if (duration > 0) {
                //转成long型,避免溢出
                long pos = currentPosition * 1000L / duration;
                mSeekBar.setProgress((int) pos);
            }
            int perent = mVideoView.getBufferPercentage();//已经缓冲的进度
            mSeekBar.setSecondaryProgress(perent);//设置缓冲进度
            mVideoCurrentTime.setText(stringForTime(currentPosition));
            mVideoTotalTime.setText(stringForTime(duration));
        }
    }


    private String stringForTime(int timeMs) {
        int totalSeconds = timeMs / 1000;
        int seconds = totalSeconds % 60; //换成秒
        int minutes = (totalSeconds / 60) % 60;
        int hours = (totalSeconds / 3600);
        mFormatterBuilder.setLength(0);
        if (hours > 0) {
            return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
        } else {
            return mFormatter.format("%02d:%02d", minutes, seconds).toString();
        }
    }

    //从直播模块跳转过来
    public static void launch(Activity activity, String url, String title) {
        Intent intent = new Intent(activity, PlayActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.putExtra("url", url);
        intent.putExtra("title", title);
        activity.startActivity(intent);
    }

}

在该文件的逻辑代码中onScrollStart()方法主要实现的是对一些手势在设备屏幕上滑动进行进行监听,比如在设备横屏的情况左下上下滑调节屏幕的亮度,右上下滑调节音量的大小;setComposeDrawableAndText()方法主要实现的是用于组合图片及文字;updateVerticalText()方法主要实现的是用于更新垂直方向上滑动时的百分比;onScrollHorizontal()方法主要实现的是更新播放视频的进度。



测试与运行截图

这里写图片描述

这里写图片描述

这里写图片描述




版权声明:本文为fukaimei原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。