基于七牛播放器的直播

来源:互联网 发布:龙泉驾校网络上课流程 编辑:程序博客网 时间:2024/05/18 02:20

这个播放器是用的七牛的播放器,直播一般都是需要后台先推流,然后根据后台给的播放地址开始直播,我这里只是一个演示,自己在网上找了一个地址,可以直接播放。

1. 拷贝架包和so文件

复制pldroid-player-1.5.0.jar到libs目录以及复制相关so文件到libs目录下面,build.gradle文件里面添加,用于编译.so文件

 sourceSets{        main(){            jniLibs.srcDirs=['libs']        }    }

2. 布局中使用

 <com.pili.pldroid.player.widget.PLVideoView        android:id="@+id/id_video_view"        android:layout_width="match_parent"        android:layout_height="match_parent" />

3. 代码中使用
代码比较简单 直接拷贝全部代码了

package com.livevideo.zlc.ui;import android.content.Context;import android.content.pm.ActivityInfo;import android.content.res.Configuration;import android.media.AudioManager;import android.os.Bundle;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.os.PowerManager;import android.support.v4.content.ContextCompat;import android.view.OrientationEventListener;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.RelativeLayout;import android.widget.TextView;import com.livevideo.zlc.MyApp;import com.livevideo.zlc.R;import com.livevideo.zlc.utils.LogUtil;import com.livevideo.zlc.utils.NetworkStateUtil;import com.livevideo.zlc.utils.ScreenUtil;import com.livevideo.zlc.utils.StatusBarUtil;import com.pili.pldroid.player.AVOptions;import com.pili.pldroid.player.PLMediaPlayer;import com.pili.pldroid.player.widget.PLVideoView;//直播public class LiveActivity extends BaseActivity implements View.OnClickListener{    private ImageView im_zhuan_fangda;    private ImageView im_room_video_off;    private ImageView im_fanhui2;    private TextView id_tv_load;    private ImageView id_iv_load;    private RelativeLayout id_rl_video;    private PLVideoView mVideoView;    private LinearLayout id_ll_head;    private LinearLayout id_ll_bottom;    private LinearLayout id_ll_load;    private String TAG = "";    private PowerManager.WakeLock mWakeLock = null;    private String mVideoPath = "";    private int mDisplayAspectRatio = PLVideoView.ASPECT_RATIO_16_9;    private static final int MESSAGE_ID_RECONNECTING = 0x01;    boolean showF = true;    private boolean canChanged = true;     private boolean isVerticalScreen = true; // 是不是竖屏    private Handler handler = new Handler(Looper.getMainLooper());    private int canReconnect = 1; //1代表可以重新连接    //控制面板的显示与隐藏    final Runnable runnable = new Runnable() {        @Override        public void run() {            LogUtil.e("执行动画",showF+"");            if(showF){//隐藏动画                showView(View.GONE,id_ll_head,id_ll_bottom);            }else{ //显示动画                showView(View.VISIBLE,id_ll_head,id_ll_bottom);                show_or_hidden(3000);            }            showF = !showF;        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_live);        setVolumeControlStream(AudioManager.STREAM_MUSIC);        PowerManager pm = (PowerManager) this.getSystemService(POWER_SERVICE);        mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "Test");        TAG = this.getClass().getSimpleName();        initView();        initData();        initListener();    }    @Override    protected void onStart() {        super.onStart();        show_or_hidden(3000);    }    private void initView(){        im_room_video_off=  findView(R.id.id_iv_video_bg);        im_zhuan_fangda = findView(R.id.id_im_rotate);        mVideoView = findView(R.id.id_video_view);        im_fanhui2 =  findView(R.id.im_fanhui2);        id_tv_load =  findView(R.id.id_tv_load);        id_iv_load = findView(R.id.id_iv_load);        id_rl_video = findView(R.id.id_rl_video);        id_ll_head = findView(R.id.id_ll_head);        id_ll_bottom = findView(R.id.id_ll_bottom);        id_ll_load = findView(R.id.id_ll_load);        ViewGroup.LayoutParams params = id_rl_video.getLayoutParams();        int  width = params.width = ScreenUtil.getScreenWidth(this);        params.height = width*9 / 16 ;        id_rl_video.setLayoutParams(params);    }    private void initListener(){        im_fanhui2.setOnClickListener(this);        id_rl_video.setOnClickListener(this);        im_zhuan_fangda.setOnClickListener(this);        id_tv_load.setOnClickListener(this);    }    private void initData(){        mVideoPath = "rtmp://live.hkstv.hk.lxdns.com/live/hks";        LogUtil.e("mVideoPath",mVideoPath);        initVideo();    }    //初始化七牛视频播放器    private void initVideo(){        AVOptions options = new AVOptions();        int isLiveStreaming = getIntent().getIntExtra("liveStreaming", 1);        // the unit of timeout is ms        options.setInteger(AVOptions.KEY_PREPARE_TIMEOUT, 10 * 1000);        options.setInteger(AVOptions.KEY_GET_AV_FRAME_TIMEOUT, 10 * 1000);        // Some optimization with buffering mechanism when be set to 1        options.setInteger(AVOptions.KEY_LIVE_STREAMING, isLiveStreaming);        if (isLiveStreaming == 1) {            options.setInteger(AVOptions.KEY_DELAY_OPTIMIZATION, 1);        }        // 1 -> hw codec enable, 0 -> disable [recommended]        int codec = getIntent().getIntExtra("mediaCodec", AVOptions.MEDIA_CODEC_AUTO);  //0是软解,1是硬解,2是自动        options.setInteger(AVOptions.KEY_MEDIACODEC, codec);        // whether start play automatically after prepared, default value is 1        options.setInteger(AVOptions.KEY_START_ON_PREPARED, 0);        mVideoView.setAVOptions(options);        mVideoView.setDisplayAspectRatio(PLVideoView.ASPECT_RATIO_16_9);        // Set some listeners        mVideoView.setOnInfoListener(mOnInfoListener);      //  mVideoView.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);        mVideoView.setOnBufferingUpdateListener(mOnBufferingUpdateListener);        mVideoView.setOnCompletionListener(mOnCompletionListener);        mVideoView.setOnSeekCompleteListener(mOnSeekCompleteListener);        mVideoView.setOnErrorListener(mOnErrorListener);        mVideoView.setVideoPath(mVideoPath);    }    //直播相关    protected Handler mHandler = new Handler(Looper.getMainLooper()) {        @Override        public void handleMessage(Message msg) {            if (msg.what != MESSAGE_ID_RECONNECTING) {                return;            }            if (!NetworkStateUtil.instance().isNetworkConnected(MyApp.getContext())) {                sendReconnectMessage();                return;            }            mVideoView.setVideoPath(mVideoPath);            mVideoView.start();        }    };    private PLMediaPlayer.OnInfoListener mOnInfoListener = new PLMediaPlayer.OnInfoListener() {        @Override        public boolean onInfo(PLMediaPlayer plMediaPlayer, int what, int extra) {            LogUtil.e("OnInfoListener","Info");            return false;        }    };    private PLMediaPlayer.OnCompletionListener mOnCompletionListener = new PLMediaPlayer.OnCompletionListener() {        @Override        public void onCompletion(PLMediaPlayer plMediaPlayer) {            LogUtil.e("OnCompletionListener","播放完成");            canReconnect = 1;            showView(View.VISIBLE,im_room_video_off,id_ll_load);            id_tv_load.setBackgroundResource(R.drawable.shape_btn_main_k_5dp);            id_tv_load.setText("重新加载");        }    };    private PLMediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener = new PLMediaPlayer.OnBufferingUpdateListener() {        @Override        public void onBufferingUpdate(PLMediaPlayer plMediaPlayer, int precent) {            LogUtil.e("OnBufferingUpdateListener","在缓冲更新");            canReconnect = 0;            im_room_video_off.setVisibility(View.GONE);            showView(View.INVISIBLE,id_ll_load);        }    };    private PLMediaPlayer.OnSeekCompleteListener mOnSeekCompleteListener = new PLMediaPlayer.OnSeekCompleteListener() {        @Override        public void onSeekComplete(PLMediaPlayer plMediaPlayer) {            canReconnect = 0;            LogUtil.e("OnSeekCompleteListener","链接完成");            im_room_video_off.setVisibility(View.GONE);            showView(View.INVISIBLE,id_ll_load);        }    };    private PLMediaPlayer.OnErrorListener mOnErrorListener = new PLMediaPlayer.OnErrorListener() {        @Override        public boolean onError(PLMediaPlayer plMediaPlayer, int errorCode) {            LogUtil.e(TAG, "Error happened, errorCode = " + errorCode);            switch (errorCode) {                case PLMediaPlayer.ERROR_CODE_INVALID_URI:                    showToastTips("无效的播放地址 !",true);                    break;                case PLMediaPlayer.ERROR_CODE_404_NOT_FOUND:                    showToastTips("未找到资源 !",true);                    break;                case PLMediaPlayer.ERROR_CODE_CONNECTION_REFUSED:                    showToastTips("连接错误",true);                    break;                case PLMediaPlayer.ERROR_CODE_CONNECTION_TIMEOUT:                    showToastTips("连接超时 !",true);                    break;                case PLMediaPlayer.ERROR_CODE_EMPTY_PLAYLIST:                    showToastTips("空的播放列表 !",true);                    break;                case PLMediaPlayer.ERROR_CODE_STREAM_DISCONNECTED:                    showToastTips("断开连接 !",true);                    break;                case PLMediaPlayer.ERROR_CODE_IO_ERROR:                    showToastTips("网络IO错误 !",true);                    break;                case PLMediaPlayer.ERROR_CODE_UNAUTHORIZED:                    showToastTips("未经授权的错误 !",true);                    break;                case PLMediaPlayer.ERROR_CODE_PREPARE_TIMEOUT:                    showToastTips("请求超时 !",true);                    break;                case PLMediaPlayer.ERROR_CODE_READ_FRAME_TIMEOUT:                    showToastTips("读帧超时 !",false);                    break;                case PLMediaPlayer.MEDIA_ERROR_UNKNOWN:                    break;                default:                    showToastTips("未知错误 !",true);                    break;            }            return true;        }    };    private void showToastTips(final String tips,boolean isShow) {        LogUtil.e("Play==",tips);        if(isShow){            canReconnect = 1;            showView(View.VISIBLE,im_room_video_off,id_ll_load);            id_tv_load.setBackgroundResource(R.drawable.shape_btn_main_k_5dp);            id_tv_load.setText("重新加载");        }else{            canReconnect = 0;            sendReconnectMessage();        }    }    private void sendReconnectMessage() {        id_ll_load.setVisibility(View.VISIBLE);        id_tv_load.setBackgroundColor(ContextCompat.getColor(this,R.color.null_color));        id_tv_load.setText("正在加载...");        mHandler.removeCallbacksAndMessages(null);        mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ID_RECONNECTING), 3000);    }    boolean isFullScreen = false;    /**     * 当横竖屏切换时执行的一些操作     */    @Override    public void onConfigurationChanged(Configuration newConfig) {        super.onConfigurationChanged(newConfig);LogUtil.e("onConfigurationChanged",newConfig.orientation+"");        //全屏看视频        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {            if(StatusBarUtil.hasNavBar(this))                StatusBarUtil.hideBottomUIMenu(this);            int matchParent = ViewGroup.LayoutParams.MATCH_PARENT;            setVideoContainerParam(matchParent,matchParent);            mVideoView.setDisplayAspectRatio(PLVideoView.ASPECT_RATIO_PAVED_PARENT);            isFullScreen = true;            StatusBarUtil.fullscreen(true,this);        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { //从视频全屏界面恢复竖屏            if(StatusBarUtil.hasNavBar(this))                StatusBarUtil.showBottomUiMenu(this);            int screenWidth = ScreenUtil.getScreenWidth(this);            setVideoContainerParam(screenWidth,screenWidth * 9 / 16);            StatusBarUtil.fullscreen(false,this);            mVideoView.setDisplayAspectRatio(mDisplayAspectRatio);            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);            isFullScreen = false;        }    }    private void setVideoContainerParam(int w,int h) {        ViewGroup.LayoutParams params = id_rl_video.getLayoutParams();        params.width = w;        params.height = h;        id_rl_video.setLayoutParams(params);    }    MyOrientationDetector myOrientationDetector;    @Override    public void onResume() {        super.onResume();        mVideoView.start();        mWakeLock.acquire();        myOrientationDetector = new MyOrientationDetector(this);        myOrientationDetector.enable();    }    @Override    public void onPause() {        super.onPause();        mVideoView.pause();        mWakeLock.release();        myOrientationDetector.disable();    }    @Override    protected void onDestroy() {        super.onDestroy();        mVideoView.stopPlayback();        handler.removeCallbacks(runnable);    }    @Override    public void onBackPressed() {        if(isFullScreen){            canChanged = false;            LiveActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);        }else{            super.onBackPressed();        }    }    private void show_or_hidden(int time){        handler.removeCallbacks(runnable); //清理前一个轮询器        handler.postDelayed(runnable,time);    }    private void showView(int visible,View... views){        for (View v : views) {            v.setVisibility(visible);        }    }    @Override    public void onClick(View view) {        switch (view.getId()){            case R.id.im_fanhui2:                if(isFullScreen){                    canChanged = false;                    LiveActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);                }else{                    finish();                }                break;            case R.id.id_im_rotate:                if (isFullScreen) {// 如果当前是横屏,则切换为竖屏                    canChanged = false;                    LiveActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);                } else {// 如果当前是竖屏,则切换为横屏                    canChanged = false;                    LiveActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);                }                isFullScreen = !isFullScreen;                break;            case R.id.id_tv_load:                if(canReconnect==1){                    sendReconnectMessage();                }                break;            case R.id.id_rl_video:               show_or_hidden(0);                break;        }    }    //自定义加速度传感器的监听事件    public class MyOrientationDetector extends OrientationEventListener {        public MyOrientationDetector( Context context ) {            super(context );        }        @Override        public void onOrientationChanged(int orientation) {            if(orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {                return;  //手机平放时,检测不到有效的角度            }            //只检测是否有四个角度的改变            if( orientation > 350 || orientation< 10 ) { //0度                isVerticalScreen = true;                if(!canChanged){                    return;                }                LiveActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);            } else if( orientation > 80 &&orientation < 100 ) { //90度                isVerticalScreen = false;                if(!canChanged){                    return;                }                LiveActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);            } else if( orientation > 170 &&orientation < 190 ) { //180度                isVerticalScreen = true;                if(!canChanged){                    return;                }                LiveActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);            } else if( orientation > 260 &&orientation < 280  ) { //270度                isVerticalScreen = false;                if(!canChanged){                    return;                }                LiveActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);            } else {            }            //物理横屏            canChanged = (isFullScreen == !isVerticalScreen);        }    }}

4. 清单文件中添加权限

    <uses-permission android:name="android.permission.INTERNET" />    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />    <uses-permission android:name="android.permission.WAKE_LOCK" />    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

5. 联系方式

qq:1509815887 email : zlc921022@163.com phone : 18684732678

6. 下载地址

点击去下载

原创粉丝点击