美文网首页
Android list列表中的自定义视频播放器

Android list列表中的自定义视频播放器

作者: 黄海佳 | 来源:发表于2017-08-02 15:01 被阅读289次

    前言

    最近在写一个监控的项目,SDK是厂商提供的,但是Demo只提供NDK方法的简单调用,要自己去封装播放器和页面细节。有一些心得,写出来给大家分享指正一下。

    简单描述一下这个项目:

    • 根据后台返回的通道数在监控列表显示多少个播放窗口。
    • listView 中播放视频,并且支持横竖屏无缝切换。
    • 播放器可以多个同时打开,进行监控。
    • 如果点击某一个全屏,其他也不暂停。

    需要注意的地方

    1、可以的话为它分配更多空间
    <application
            ...
            android:largeHeap="true"
            ...>
    
    </application>
    
    2、手机状态的改变,不重新调用各个生命周期。
     <activity 
            android:name=".activity.MonitorRMActivity"
            android:screenOrientation="portrait"
            android:launchMode="singleTop"
            android:configChanges="keyboard|keyboardHidden|orientation|screenSize|
                                   screenLayout|smallestScreenSize|uiMode|navigation"/>
    
    3、在页面的根元素设置 屏幕常亮
    android:keepScreenOn="true"
    
    4、全屏样式与非全屏主题样式的切换
    private boolean isFull;//当前状态是否全屏
    private void setOrientation(){
            if(!isFull){//切成全屏
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
                        | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
               
                //TODO -->这里需要你去处理
                // 1 、选中的视频的全屏按钮变成回复小屏样式
                // 2 、选中的视频全屏展示(通过setLayoutParams来将视频设置为全屏,并设成最顶端或者隐藏其他)
                // 3、ActionBar的细节处理
            }else{//还原城小屏
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
                getWindow().addFlags(
                        WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN | 
                        WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
               
            }
            isFull = !isFull;
        }
    

    知识点补充

    //设置屏幕方向
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    
    //隐藏标题
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    
    //设置成全屏模式
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                         WindowManager.LayoutParams.FLAG_FULLSCREEN);
    
    5、播放器的状态控制(这里如果处理不好,容易出异常)

    根据厂家的SDK在各个生命周期的方法中加入相关的方法即可,自己另外做一些异常的捕获
    网上偷来一张图,展示mediaPlayer 各个状态之间的关系和转换方式

    6、onKeyDown方法中判断一下,如果是横屏点击返回键就让它退出横屏

    这里补充屏幕方向参数相关知识

      ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,//横屏
      ActivityInfo.SCREEN_ORIENTATION_PORTRAIT,//竖屏
      ActivityInfo.SCREEN_ORIENTATION_USER,//用户当前的首选方向
      ActivityInfo.SCREEN_ORIENTATION_BEHIND,//继承Activity堆栈中当前Activity下面的那个Activity的方向
      ActivityInfo.SCREEN_ORIENTATION_SENSOR,//由物理感应器决定显示方向
      ActivityInfo.SCREEN_ORIENTATION_NOSENSOR,//忽略物理感应器——即显示方向与物理感应器无关
      ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE,
      ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT,
      ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE,
      ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT,
      ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR,
    
    7、点击播放按钮的校验

    伪代码如下

    if ( NetworkError ){//判断网络状态
        //TODO
        return;
    }
    if (Check(url)) {//播放路径是否有误(包括字符串的校验以及后台是否有地址:即是否404)
         //TODO
          return;
    }
    if (Utils.isWifiConnected && !WIFI_TIP_DIALOG_SHOWED) {
         //判断当前是否wify链接并且是否有出现过提示,如果不是提示用户是否继续
         showWifiDialog();
         return;
    }
    prepareMediaPlayer();//开始播放
    
    
    8、横竖屏切换可添加动画,切换时判断一下当前播放器的状态

    播放状态大概是8种

        public static final int CURRENT_STATE_NORMAL = 0;
        public static final int CURRENT_STATE_PREPARING = 1;//准备播放
        public static final int CURRENT_STATE_PLAYING = 2;//播放中
        public static final int CURRENT_STATE_PLAYING_BUFFERING_START = 3;//播放缓冲状态
        public static final int CURRENT_STATE_PAUSE = 5;//暂停
        public static final int CURRENT_STATE_AUTO_COMPLETE = 6;
        public static final int CURRENT_STATE_ERROR = 7;//播放错误
    
    • 如果当前不是正常的状态则不进行全屏切换,或者直接隐藏全屏按钮
    • 如果横竖屏切换有动画,要判断动画是否完成再进行切换(同理监听返回键)
    9、如果使用了重力感应,则添加监听
    implements SensorEventListener{
            @Override
            public void onSensorChanged(SensorEvent event) {//可以得到传感器实时测量出来的变化值
                final float x = event.values[SensorManager.DATA_X];
                float y = event.values[SensorManager.DATA_Y];
                float z = event.values[SensorManager.DATA_Z];
                //过滤掉用力过猛会有一个反向的大数值
                if (((x > -15 && x < -10) || (x < 15 && x > 10)) && Math.abs(y) < 1.5) {
                    if ((System.currentTimeMillis() - lastAutoFullscreenTime) > 2000) {
                        if (VideoPlayerManager.getCurrent() != null) {
                            VideoPlayerManager.getCurrent().autoFullscreen(x);
                        }
                        lastAutoFullscreenTime = System.currentTimeMillis();
                    }
                }
            }
    
            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {
            }
    
    }
    
    10、另外补充获取状态栏高度、获取标题栏高度
    • 获取状态栏高度
      decorView是window中的最顶层view,可以从window中获取到decorView,然后decorView有个getWindowVisibleDisplayFrame方法可以获取到程序显示的区域,包括标题栏,但不包括状态栏。
    Rect frame = new Rect();
    
    getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
    
    int statusBarHeight = frame.top;
    
    Rect frame = new Rect();
    
    getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
    
    int statusBarHeight = frame.top;
    
    
    • 获取标题栏高度
      getWindow().findViewById(Window.ID_ANDROID_CONTENT) 这个方法获取到的view就是程序不包括标题栏的部分,然后就可以知道标题栏的高度了。
    int contentTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
    
    //statusBarHeight是上面所求的状态栏的高度
    
    int titleBarHeight = contentTop - statusBarHeight
    
    int contentTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
    
    int titleBarHeight = contentTop - statusBarHeight
    
    
    11、在整个Acitivity中有用到对象的地方都要细心的去进行异常处理,判断对象有没有空,防止应用闪退。
    12、最后 代码逻辑参考链接

    https://github.com/open-android/JieCaoVideoPlayer

    参考文章:
    http://www.jianshu.com/p/a48af7b23488
    http://www.jianshu.com/p/ffb647e15e33
    http://www.jianshu.com/p/871d93dbc98e
    https://github.com/LuckSiege/PictureSelector
    http://www.jianshu.com/p/cc5e71054993

    相关文章

      网友评论

          本文标题:Android list列表中的自定义视频播放器

          本文链接:https://www.haomeiwen.com/subject/tsujlxtx.html