github(三)android下視頻播放JiaoZiVideoPlayer源碼分析

 JiaoZiVideoPlayer是一個android下的視頻的播放軟件,主要功能是放在了播放上面,並沒有視頻的錄製和切片加水印效果,如果是想實現這種效果,需要參考其它開源框架。這款框架使用的人還是非常多的,屬於多媒體模塊,這裏將分析它的源碼,以便以後用上的時候好進行修改源碼。

一、視頻播放基礎控件介紹

TextureView控件,是一個支架性的控件,主要是用來實現承載視頻的顯示。

源碼分析

 JZTextureView類

這是一個繼承的TextureView的類,在這個類裏主要重寫了setRotation,和onMeasure,這兩個方法,並且增加了setVideoSize這個方法。

這個重寫類增加和重寫的方法,主要是爲了實現視頻的旋轉以及裁剪和寬和高的設定。

實現旋轉

  @Override
    public void setRotation(float rotation) {
        if (rotation != getRotation()) {
            super.setRotation(rotation);
            requestLayout();
        }
    }

 

 Jzvd 類 繼承了FrameLayout類

 在onTouch()方法中,實現了划動左邊亮度的增減,划動右邊聲音的增減,以及,左右滑動時進度的增減

  一、進入全屏,在這裏是重寫了onclick方法,在點擊右下角的全屏按鈕時,執行了以下的代碼,

if (i == R.id.fullscreen) {
            Log.i(TAG, "onClick fullscreen [" + this.hashCode() + "] ");
            if (state == STATE_AUTO_COMPLETE) return;
            if (screen == SCREEN_FULLSCREEN) {
                //quit fullscreen
                backPress();
            } else {
                Log.d(TAG, "toFullscreenActivity [" + this.hashCode() + "] ");
                gotoScreenFullscreen();
            }
        }

然後執行gotoScreenFullscreen()方法,進入視頻全屏播放模式,在這裏可以看到,通過getParent()它會得到父控件,然後移動控件的所有組件,把自己的寬和高設爲match_layout,再次返回時其它控件會沒有了,因此儘量把它單獨放到一個父類中,然後再去隱藏狀態欄和虛擬鍵盤,並且修改屏幕爲橫向顯示。

 public void gotoScreenFullscreen() {
        ViewGroup vg = (ViewGroup) getParent();
        vg.removeView(this);
        cloneAJzvd(vg);
        CONTAINER_LIST.add(vg);
        vg = (ViewGroup) (JZUtils.scanForActivity(getContext())).getWindow().getDecorView();//和他也沒有關係
        vg.addView(this, new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        
        setScreenFullscreen();
        //隱藏狀態欄
        JZUtils.hideStatusBar(getContext());
        //修改屏幕爲橫向
        JZUtils.setRequestedOrientation(getContext(), FULLSCREEN_ORIENTATION);
        隱藏虛擬鍵盤
        JZUtils.hideSystemUI(getContext());//華爲手機和有虛擬鍵的手機全屏時可隱藏虛擬鍵 issue:1326

    }

            二、 左側:上下滑動修改亮度,右側:上下滑動修改聲音,左右滑動修改進度

在這裏是只是給出了MotionEvent.ACTION_MOVE的源碼,這塊內容的實現就是onTouch方法,看這個方法就可以了,這裏只是一個小bug的,就是切換橫屏後,沒有修改mScreenWidth這個值,造成修改亮度不是一半,

float deltaX = x - mDownX;
                    float deltaY = y - mDownY;
                    float absDeltaX = Math.abs(deltaX);
                    float absDeltaY = Math.abs(deltaY);
                    if (screen == SCREEN_FULLSCREEN) {
                        if (!mChangePosition && !mChangeVolume && !mChangeBrightness) {
                            if (absDeltaX > THRESHOLD || absDeltaY > THRESHOLD) {
                                cancelProgressTimer();
                                if (absDeltaX >= THRESHOLD) {
                                    // 全屏模式下的CURRENT_STATE_ERROR狀態下,不響應進度拖動事件.
                                    // 否則會因爲mediaplayer的狀態非法導致App Crash
                                    if (state != STATE_ERROR) {
                                        mChangePosition = true;
                                        mGestureDownPosition = getCurrentPositionWhenPlaying();
                                    }
                                } else {
                                    //如果y軸滑動距離超過設置的處理範圍,那麼進行滑動事件處理
                                    if (mDownX < mScreenWidth * 0.5f) {//左側改變亮度
                                        mChangeBrightness = true;
                                        WindowManager.LayoutParams lp = JZUtils.getWindow(getContext()).getAttributes();
                                        if (lp.screenBrightness < 0) {
                                            try {
                                                mGestureDownBrightness = Settings.System.getInt(getContext().getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);
                                                Log.i(TAG, "current system brightness: " + mGestureDownBrightness);
                                            } catch (Settings.SettingNotFoundException e) {
                                                e.printStackTrace();
                                            }
                                        } else {
                                            mGestureDownBrightness = lp.screenBrightness * 255;
                                            Log.i(TAG, "current activity brightness: " + mGestureDownBrightness);
                                        }
                                    } else {//右側改變聲音
                                        mChangeVolume = true;
                                        mGestureDownVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
                                    }
                                }
                            }
                        }
                    }
                    if (mChangePosition) {
                        long totalTimeDuration = getDuration();
                        mSeekTimePosition = (int) (mGestureDownPosition + deltaX * totalTimeDuration / mScreenWidth);
                        if (mSeekTimePosition > totalTimeDuration)
                            mSeekTimePosition = totalTimeDuration;
                        String seekTime = JZUtils.stringForTime(mSeekTimePosition);
                        String totalTime = JZUtils.stringForTime(totalTimeDuration);

                        showProgressDialog(deltaX, seekTime, mSeekTimePosition, totalTime, totalTimeDuration);
                    }
                    if (mChangeVolume) {
                        deltaY = -deltaY;
                        int max = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
                        int deltaV = (int) (max * deltaY * 3 / mScreenHeight);
                        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mGestureDownVolume + deltaV, 0);
                        //dialog中顯示百分比
                        int volumePercent = (int) (mGestureDownVolume * 100 / max + deltaY * 3 * 100 / mScreenHeight);
                        showVolumeDialog(-deltaY, volumePercent);
                    }

                    if (mChangeBrightness) {
                        deltaY = -deltaY;
                        int deltaV = (int) (255 * deltaY * 3 / mScreenHeight);
                        WindowManager.LayoutParams params = JZUtils.getWindow(getContext()).getAttributes();
                        if (((mGestureDownBrightness + deltaV) / 255) >= 1) {//這和聲音有區別,必須自己過濾一下負值
                            params.screenBrightness = 1;
                        } else if (((mGestureDownBrightness + deltaV) / 255) <= 0) {
                            params.screenBrightness = 0.01f;
                        } else {
                            params.screenBrightness = (mGestureDownBrightness + deltaV) / 255;
                        }
                        JZUtils.getWindow(getContext()).setAttributes(params);
                        //dialog中顯示百分比
                        int brightnessPercent = (int) (mGestureDownBrightness * 100 / 255 + deltaY * 3 * 100 / mScreenHeight);
                        showBrightnessDialog(brightnessPercent);
//                        mDownY = y;
                    }

          JzvdStd類,添加了視頻播放的佈局getLayoutId

根據廣播來顯示電量,利用 level * 100 / scale來計算當前電量的百分比。

 private BroadcastReceiver battertReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
                //當前電量
                int level = intent.getIntExtra("level", 0);
                //總電量
                int scale = intent.getIntExtra("scale", 100);
                //電量所佔的百分比計算
                int percent = level * 100 / scale;
                LAST_GET_BATTERYLEVEL_PERCENT = percent;
                setBatteryLevel();
                try {
                    getContext().unregisterReceiver(battertReceiver);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    };

   利用廣播來修改電量的圖標,實現視頻上的圖片來發生變化 

   public void setBatteryLevel() {
        int percent = LAST_GET_BATTERYLEVEL_PERCENT;
        if (percent < 15) {
            batteryLevel.setBackgroundResource(R.drawable.jz_battery_level_10);
        } else if (percent >= 15 && percent < 40) {
            batteryLevel.setBackgroundResource(R.drawable.jz_battery_level_30);
        } else if (percent >= 40 && percent < 60) {
            batteryLevel.setBackgroundResource(R.drawable.jz_battery_level_50);
        } else if (percent >= 60 && percent < 80) {
            batteryLevel.setBackgroundResource(R.drawable.jz_battery_level_70);
        } else if (percent >= 80 && percent < 95) {
            batteryLevel.setBackgroundResource(R.drawable.jz_battery_level_90);
        } else if (percent >= 95 && percent <= 100) {
            batteryLevel.setBackgroundResource(R.drawable.jz_battery_level_100);
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章