com.google.android.exoplayer2.demo.MediaPlayerFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.google.android.exoplayer2.demo.MediaPlayerFragment.java

Source

/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.android.exoplayer2.demo;

import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.drm.FrameworkMediaDrm;
import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
import com.google.android.exoplayer2.drm.UnsupportedDrmException;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
import com.google.android.exoplayer2.source.BehindLiveWindowException;
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.dash.DashMediaSource;
import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource;
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource;
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.DebugTextViewHelper;
import com.google.android.exoplayer2.ui.PlaybackControlView;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.util.Util;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.util.UUID;
import net.gnu.explorer.Frag;
import net.gnu.explorer.R;
import java.io.File;
import net.gnu.explorer.ExplorerActivity;
import net.gnu.explorer.ExplorerApplication;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.util.DisplayMetrics;
import android.support.annotation.DrawableRes;
import android.content.Context;
import android.app.Activity;
import android.media.AudioManager;
import java.util.Formatter;
import android.provider.Settings;
import com.jarvanmo.exoplayerview.util.Permissions;
import java.util.Locale;
import android.view.animation.AnimationUtils;
import android.support.v4.content.ContextCompat;
import android.text.SpannableString;
import android.util.TypedValue;
import android.text.style.ForegroundColorSpan;
import android.text.Spanned;
import android.content.res.TypedArray;
import android.os.SystemClock;
import android.content.IntentFilter;
import static android.content.Context.AUDIO_SERVICE;
import android.content.BroadcastReceiver;
import java.util.Calendar;

/**
 * An activity that plays media using {@link SimpleExoPlayer}.
 */
public class MediaPlayerFragment extends Frag
        implements OnClickListener, ExoPlayer.EventListener, PlaybackControlView.VisibilityListener {
    private final String TAG = "MediaPlayerFragment";

    public static final int DEFAULT_FAST_FORWARD_MS = 15000;
    public static final int DEFAULT_REWIND_MS = 5000;
    public static final int DEFAULT_SHOW_TIMEOUT_MS = 5000;

    private static final int PROGRESS_BAR_MAX = 1000;
    private static final long MAX_POSITION_FOR_SEEK_TO_PREVIOUS = 3000;

    //Touch Events
    private static final int TOUCH_NONE = 0;
    private static final int TOUCH_VOLUME = 1;
    private static final int TOUCH_BRIGHTNESS = 2;
    private static final int TOUCH_SEEK = 3;

    //touch
    private int mTouchAction = TOUCH_NONE;
    private int mSurfaceYDisplayRange;
    private float mInitTouchY;
    private float touchX = -1f;
    private float touchY = -1f;

    //Volume
    private AudioManager mAudioManager;
    private int mAudioMax;
    private float mVol;

    // Brightness
    private boolean mIsFirstBrightnessGesture = true;

    //    private final Timeline.Window currentWindow;
    //    private final ComponentListener componentListener;
    //   private boolean isTimelineStatic;
    //    private Timeline.Window window;

    private final StringBuilder formatBuilder;
    private final Formatter formatter;

    public static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid";
    public static final String DRM_LICENSE_URL = "drm_license_url";
    public static final String DRM_KEY_REQUEST_PROPERTIES = "drm_key_request_properties";
    public static final String PREFER_EXTENSION_DECODERS = "prefer_extension_decoders";

    public static final String ACTION_VIEW = "com.google.android.exoplayer.demo.action.VIEW";
    public static final String EXTENSION_EXTRA = "extension";

    public static final String ACTION_VIEW_LIST = "com.google.android.exoplayer.demo.action.VIEW_LIST";
    public static final String URI_LIST_EXTRA = "uri_list";
    public static final String EXTENSION_LIST_EXTRA = "extension_list";

    private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
    private static final CookieManager DEFAULT_COOKIE_MANAGER;
    static {
        DEFAULT_COOKIE_MANAGER = new CookieManager();
        DEFAULT_COOKIE_MANAGER.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);
    }

    private Handler mainHandler;
    private EventLogger eventLogger;
    private SimpleExoPlayerView simpleExoPlayerView;
    private LinearLayout debugRootView;
    private TextView debugTextView;
    private Button retryButton;

    private DataSource.Factory mediaDataSourceFactory;
    private SimpleExoPlayer player;
    private DefaultTrackSelector trackSelector;
    private TrackSelectionHelper trackSelectionHelper;
    private DebugTextViewHelper debugViewHelper;
    private boolean needRetrySource;

    private boolean shouldAutoPlay;
    private int resumeWindow;
    private long resumePosition;
    private TextView centerInfo;

    //   private TextView localTime;
    //    private BatteryLevelView battery;

    //    private final BroadcastReceiver timeReceiver = new BroadcastReceiver() {
    //        @Override
    //        public void onReceive(Context context, Intent intent) {
    //            String action = intent.getAction();
    //            if (action.equals(Intent.ACTION_TIME_TICK)) {
    //                updateTime();
    //            }
    //        }
    //    };

    // Activity lifecycle
    public MediaPlayerFragment() {
        super();
        type = Frag.TYPE.MEDIA.ordinal();
        formatBuilder = new StringBuilder();
        formatter = new Formatter(formatBuilder, Locale.getDefault());

        //      currentWindow = new Timeline.Window();
        //        componentListener = new ComponentListener();
        //        window = new Timeline.Window();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView");
        super.onCreateView(inflater, container, savedInstanceState);
        setHasOptionsMenu(false);
        if (activity == null) {
            return inflater.inflate(R.layout.player_activity_nocommands, container, false);
        } else {
            return inflater.inflate(R.layout.player_activity, container, false);
        }
    }

    @Override
    public void onViewCreated(View v, Bundle savedInstanceState) {
        //@Override
        //public void onCreate(Bundle savedInstanceState) {
        super.onViewCreated(v, savedInstanceState);

        shouldAutoPlay = true;
        clearResumePosition();
        mediaDataSourceFactory = buildDataSourceFactory(true);
        mainHandler = new Handler();
        if (CookieHandler.getDefault() != DEFAULT_COOKIE_MANAGER) {
            CookieHandler.setDefault(DEFAULT_COOKIE_MANAGER);
        }

        //setContentView(R.layout.player_activity);
        View rootView = v.findViewById(R.id.root);
        rootView.setOnClickListener(this);
        debugRootView = (LinearLayout) v.findViewById(R.id.controls_root);
        debugTextView = (TextView) v.findViewById(R.id.debug_text_view);
        retryButton = (Button) v.findViewById(R.id.retry_button);
        retryButton.setOnClickListener(this);
        centerInfo = (TextView) v.findViewById(R.id.centerInfo);
        //        localTime = (TextView) v.findViewById(R.id.localTime);
        //        battery = (BatteryLevelView) v.findViewById(R.id.battery);

        simpleExoPlayerView = (SimpleExoPlayerView) v.findViewById(R.id.player_view);
        simpleExoPlayerView.setControllerVisibilityListener(this);
        simpleExoPlayerView.requestFocus();

        final Intent intent = getActivity().getIntent();
        if (intent != null) {
            Uri extras = intent.getData();
            if (extras != null) {
                CURRENT_PATH = extras.getPath();
                Log.d(TAG, "intent.getData() " + CURRENT_PATH);
            }
        }
        updateColor(rootView);
    }

    //@Override
    public void onNewIntent(Intent intent) {
        releasePlayer();
        shouldAutoPlay = true;
        clearResumePosition();
        fragActivity.setIntent(intent);
    }

    public void clone(final Frag fragO) {
    }

    public void load(String path) {
        Log.d(TAG, "path " + path);
        if (path != null) {
            //doCleanUp();
            //player.release();//.releaseMediaPlayer();
            this.CURRENT_PATH = path;
            File file = new File(path);
            MediaSource mediaSource = buildMediaSource(Uri.fromFile(file), null);//extensions[i]);
            boolean haveResumePosition = resumeWindow != C.INDEX_UNSET;
            if (haveResumePosition) {
                player.seekTo(resumeWindow, resumePosition);
            }
            player.prepare(mediaSource, !haveResumePosition, false);
            needRetrySource = false;
            updateButtonVisibilities();
        }
    }

    public void updateColor(View root) {
        getView().setBackgroundColor(ExplorerActivity.BASE_BACKGROUND);
        debugTextView.setTextColor(ExplorerActivity.TEXT_COLOR);
        //      debugRootView.setBackgroundColor(ExplorerfragActivity.BASE_BACKGROUND);
        root.setBackgroundColor(ExplorerActivity.BASE_BACKGROUND);
        simpleExoPlayerView.setBackgroundColor(ExplorerActivity.BASE_BACKGROUND);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //Log.d(TAG, "onTouch " + event);
        if (activity != null) {
            if (type == -1) {
                activity.slideFrag2.getCurrentFragment2().select(false);
            } else {
                activity.slideFrag2.getCurrentFragment2().select(true);
            }
        }
        dispatchCenterWrapperTouchEvent(event);
        return false;
    }

    private boolean dispatchCenterWrapperTouchEvent(MotionEvent event) {
        Log.d(TAG, "dispatchCenterWrapperTouchEvent " + event);

        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);

        DisplayMetrics screen = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(screen);

        if (mSurfaceYDisplayRange == 0) {
            mSurfaceYDisplayRange = Math.min(screen.widthPixels, screen.heightPixels);
        }

        float x_changed, y_changed;
        if (touchX != -1f && touchY != -1f) {
            y_changed = event.getRawY() - touchY;
            x_changed = event.getRawX() - touchX;
        } else {
            x_changed = 0f;
            y_changed = 0f;
        }

        //        Log.e("tag","x_c=" + x_changed + "screen_x =" + screen.xdpi +" screen_rawx" + event.getRawX());
        float coef = Math.abs(y_changed / x_changed);
        float xgesturesize = (((event.getRawX() - touchX) / screen.xdpi) * 2.54f);//2.54f

        float delta_y = Math.max(1f, (Math.abs(mInitTouchY - event.getRawY()) / screen.xdpi + 0.5f) * 2f);

        switch (event.getAction()) {

        case MotionEvent.ACTION_DOWN:
            mTouchAction = TOUCH_NONE;
            touchX = event.getRawX();
            mVol = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            touchY = mInitTouchY = event.getRawY();
            break;

        case MotionEvent.ACTION_MOVE:

            if (mTouchAction != TOUCH_SEEK && coef > 2) {
                if (Math.abs(y_changed / mSurfaceYDisplayRange) < 0.05) {
                    return false;
                }

                touchX = event.getRawX();
                touchY = event.getRawY();

                if (activity == null) {
                    if ((int) touchX > (4 * screen.widthPixels / 7)) {
                        doVolumeTouch(y_changed);
                        //                        hideCenterInfo();
                        //                            hideOverlay(true);
                    }
                    // Brightness (Up or Down - Left side)
                    if ((int) touchX < (3 * screen.widthPixels / 7)) {
                        doBrightnessTouch(y_changed);
                    }
                } else {
                    if (!activity.swap && activity.left.getVisibility() == View.VISIBLE
                            && activity.right.getVisibility() == View.VISIBLE) {
                        if ((int) touchX > (3 * screen.widthPixels / 4)) {
                            doVolumeTouch(y_changed);
                            //                        hideCenterInfo();
                            //                            hideOverlay(true);
                        }
                        // Brightness (Up or Down - Left side)
                        else if ((int) touchX >= (2 * screen.widthPixels / 4)) {
                            doBrightnessTouch(y_changed);
                        }
                    } else {
                        if ((int) touchX < (1 * screen.widthPixels / 4)) {
                            doBrightnessTouch(y_changed);
                            //                        hideCenterInfo();
                            //                            hideOverlay(true);
                        }
                        // Brightness (Up or Down - Left side)
                        else if ((int) touchX < (2 * screen.widthPixels / 4)) {
                            doVolumeTouch(y_changed);
                        }
                    }
                }

            } else {
                doSeekTouch(Math.round(delta_y), xgesturesize, false);
            }

            break;

        case MotionEvent.ACTION_UP:
            if (mTouchAction == TOUCH_SEEK) {
                doSeekTouch(Math.round(delta_y), xgesturesize, true);
            }

            if (mTouchAction != TOUCH_NONE) {
                hideCenterInfo();
            }

            touchX = -1f;
            touchY = -1f;
            break;
        default:
            break;
        }

        return mTouchAction != TOUCH_NONE;
    }

    //    private void updateTime() {
    //        final Calendar calendar = Calendar.getInstance();
    //
    //        int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY);
    //        int minute = calendar.get(Calendar.MINUTE);
    ////        int amOrPm = calendar.get(Calendar.AM_PM);
    ////        boolean is24HourFormat = DateFormat.is24HourFormat(getContext());
    //
    ////        Resources res = getResources();
    //        String timeResult = "";
    ////        hourOfDay = is24HourFormat ? hourOfDay : (hourOfDay > 12 ? hourOfDay - 12: hourOfDay);
    //        if (hourOfDay >= 10) {
    //            timeResult += Integer.toString(hourOfDay);
    //        } else {
    //            timeResult += "0" + hourOfDay;
    //        }
    //
    //        timeResult += ":";
    //
    //        if (minute >= 10) {
    //            timeResult += Integer.toString(minute);
    //        } else {
    //            timeResult += "0" + minute;
    //        }
    //
    //
    ////
    ////        if (!is24HourFormat) {
    ////            String str = amOrPm == Calendar.AM ? res.getString(R.string.time_am) : res.getString(R.string.time_pm);
    ////            timeResult = timeResult + " " + str;
    ////        }
    //        localTime.setText(timeResult);
    //    }

    //    @Override
    //    public void onAttachedToWindow() {
    //        super.onAttachedToWindow();
    //
    //        isAttachedToWindow = true;
    //
    //        registerBroadcast();
    //
    //        initVol();
    //
    //        if (hideAtMs != C.TIME_UNSET) {
    //            long delayMs = hideAtMs - SystemClock.uptimeMillis();
    //            if (delayMs <= 0) {
    //                hide();
    //            } else {
    //                postDelayed(hideAction, delayMs);
    //            }
    //        }
    //        updateAll();
    //    }

    //    @Override
    //    public void onDetachedFromWindow() {
    //        super.onDetachedFromWindow();
    //        isAttachedToWindow = false;
    //
    //        mAudioManager = null;
    //
    //        screenOrientationEventListener.disable();
    //
    //        unregisterBroadcast();
    //        removeCallbacks(updateProgressAction);
    //        removeCallbacks(hideAction);
    //    }

    private void initVol() {

        /* Services and miscellaneous */
        mAudioManager = (AudioManager) getContext().getApplicationContext().getSystemService(AUDIO_SERVICE);
        mAudioMax = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);

    }

    //    private void registerBroadcast() {
    //
    //        IntentFilter timeFilter = new IntentFilter(Intent.ACTION_TIME_TICK);
    //        getContext().registerReceiver(timeReceiver, timeFilter);
    //
    //    }
    //
    //    private void unregisterBroadcast() {
    //        getContext().unregisterReceiver(timeReceiver);
    //    }

    private void hideCenterInfo() {
        centerInfo.startAnimation(AnimationUtils.loadAnimation(getContext(), android.R.anim.fade_out));
        centerInfo.setVisibility(View.GONE);

    }

    private void doVolumeTouch(float y_changed) {
        if (mTouchAction != TOUCH_NONE && mTouchAction != TOUCH_VOLUME) {
            return;
        }

        int oldVol = (int) mVol;
        mTouchAction = TOUCH_VOLUME;
        float delta = -((y_changed / mSurfaceYDisplayRange) * mAudioMax);
        mVol += delta;
        int vol = (int) Math.min(Math.max(mVol, 0), mAudioMax);
        if (delta != 0f) {
            setAudioVolume(vol, vol > oldVol);
        }
    }

    private void setAudioVolume(int vol, boolean up) {
        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, vol, 0);

        /* Since android 4.3, the safe volume warning dialog is displayed only with the FLAG_SHOW_UI flag.
         * We don't want to always show the default UI volume, so show it only when volume is not set. */
        int newVol = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        if (vol != newVol) {
            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, vol, AudioManager.FLAG_SHOW_UI);
        }

        mTouchAction = TOUCH_VOLUME;
        vol = vol * 100 / mAudioMax;
        int drawableId;
        if (newVol == 0) {
            drawableId = R.drawable.ic_volume_mute_white_36dp;
        } else if (up) {
            drawableId = R.drawable.ic_volume_up_white_36dp;
        } else {
            drawableId = R.drawable.ic_volume_down_white_36dp;
        }
        setVolumeOrBrightnessInfo(getContext().getString(R.string.volume_changing, vol), drawableId);
        //        showInfoWithVerticalBar(getString(R.string.volume) + "\n" + Integer.toString(vol) + '%', 1000, vol);
    }

    private void doSeekTouch(int coef, float gesturesize, boolean seek) {

        if (coef == 0) {
            coef = 1;
        }

        // No seek action if coef > 0.5 and gesturesize < 1cm

        if (Math.abs(gesturesize) < 1) {// || !canSeek()
            return;
        }

        if (mTouchAction != TOUCH_NONE && mTouchAction != TOUCH_SEEK) {
            return;
        }

        mTouchAction = TOUCH_SEEK;

        long length = player.getDuration();
        long time = player.getCurrentPosition();

        // Size of the jump, 10 minutes max (600000), with a bi-cubic progression, for a 8cm gesture
        int jump = (int) ((Math.signum(gesturesize) * ((600000 * Math.pow((gesturesize / 8), 4)) + 3000)) / coef);

        // Adjust the jump
        if ((jump > 0) && ((time + jump) > length)) {
            jump = (int) (length - time);
        }

        if ((jump < 0) && ((time + jump) < 0)) {
            jump = (int) -time;
        }

        //Jump !
        if (seek && length > 0) {
            seek(time + jump);
        }

        if (length > 0) {
            //Show the jump's size
            setFastForwardOrRewind(time + jump,
                    jump > 0 ? R.drawable.ic_fast_forward_white_36dp : R.drawable.ic_fast_rewind_white_36dp);
        }
    }

    private void seek(long position) {
        if (player != null) {
            player.seekTo(position);
        }

    }

    private void setFastForwardOrRewind(long changingTime, @DrawableRes int drawableId) {
        centerInfo.setVisibility(View.VISIBLE);
        centerInfo.setText(generateFastForwardOrRewindTxt(changingTime));
        centerInfo.setCompoundDrawablesWithIntrinsicBounds(null,
                ContextCompat.getDrawable(getContext(), drawableId), null, null);
    }

    private CharSequence generateFastForwardOrRewindTxt(long changingTime) {

        long duration = player == null ? 0 : player.getDuration();
        String result = stringForTime(changingTime) + " / " + stringForTime(duration);

        int index = result.indexOf("/");

        SpannableString spannableString = new SpannableString(result);

        TypedValue typedValue = new TypedValue();
        TypedArray a = getContext().obtainStyledAttributes(typedValue.data, new int[] { R.attr.colorAccent });
        int color = a.getColor(0, 0);
        a.recycle();
        spannableString.setSpan(new ForegroundColorSpan(color), 0, index, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

        return spannableString;
    }

    private String stringForTime(long timeMs) {
        if (timeMs == C.TIME_UNSET) {
            timeMs = 0;
        }
        long totalSeconds = (timeMs + 500) / 1000;
        long seconds = totalSeconds % 60;
        long minutes = (totalSeconds / 60) % 60;
        long hours = totalSeconds / 3600;
        formatBuilder.setLength(0);
        return hours > 0 ? formatter.format("%d:%02d:%02d", hours, minutes, seconds).toString()
                : formatter.format("%02d:%02d", minutes, seconds).toString();
    }

    //    private boolean canSeek() {
    //
    //        Timeline currentTimeline = player != null ? player.getCurrentTimeline() : null;
    //        boolean haveNonEmptyTimeline = currentTimeline != null && !currentTimeline.isEmpty();
    //        boolean isSeekable = false;
    //        if (haveNonEmptyTimeline) {
    //            int currentWindowIndex = player.getCurrentWindowIndex();
    //            currentTimeline.getWindow(currentWindowIndex, currentWindow);
    //            isSeekable = currentWindow.isSeekable;
    ////            enablePrevious = currentWindowIndex > 0 || isSeekable || !currentWindow.isDynamic;
    //        }
    //
    //        return isSeekable && isTimelineStatic;
    //    }

    private void doBrightnessTouch(float y_changed) {
        if (mTouchAction != TOUCH_NONE && mTouchAction != TOUCH_BRIGHTNESS) {
            return;
        }

        mTouchAction = TOUCH_BRIGHTNESS;
        if (mIsFirstBrightnessGesture) {
            initBrightnessTouch();
        }

        mTouchAction = TOUCH_BRIGHTNESS;
        //
        // Set delta : 2f is arbitrary for now, it possibly will change in the future
        float delta = -y_changed / mSurfaceYDisplayRange;
        changeBrightness(delta);
    }

    private void initBrightnessTouch() {

        //        if (!(getContext() instanceof Activity)) {
        //            return;
        //        }
        Activity activity = fragActivity;//(Activity) getContext();

        WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
        float brightnesstemp = lp.screenBrightness != -1f ? lp.screenBrightness : 0.6f;
        // Initialize the layoutParams screen brightness
        try {
            if (Settings.System.getInt(activity.getContentResolver(),
                    Settings.System.SCREEN_BRIGHTNESS_MODE) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC) {
                if (!Permissions.canWriteSettings(activity)) {
                    return;
                }
                Settings.System.putInt(activity.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE,
                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
                //                restoreAutoBrightness = android.provider.Settings.System.getInt(activity.getContentResolver(),
                //                        android.provider.Settings.System.SCREEN_BRIGHTNESS) / 255.0f;
            } else if (brightnesstemp == 0.6f) {
                brightnesstemp = android.provider.Settings.System.getInt(activity.getContentResolver(),
                        android.provider.Settings.System.SCREEN_BRIGHTNESS) / 255.0f;
            }
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }
        lp.screenBrightness = brightnesstemp;
        activity.getWindow().setAttributes(lp);
        mIsFirstBrightnessGesture = false;
    }

    private void changeBrightness(float delta) {
        // Estimate and adjust Brightness
        //        if (!(getContext() instanceof Activity)) {
        //            return;
        //        }
        Activity activity = fragActivity;//(Activity) getContext();

        WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
        float brightness = Math.min(Math.max(lp.screenBrightness + delta, 0.01f), 1f);
        setWindowBrightness(brightness);
        brightness = Math.round(brightness * 100);

        int brightnessInt = (int) brightness;

        setVolumeOrBrightnessInfo(getContext().getString(R.string.brightness_changing, brightnessInt),
                whichBrightnessImageToUse(brightnessInt));
    }

    private void setWindowBrightness(float brightness) {
        //        if (!(getContext() instanceof Activity)) {
        //            return;
        //        }
        Activity activity = fragActivity;//(Activity) getContext();

        WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
        lp.screenBrightness = brightness;
        // Set Brightness
        activity.getWindow().setAttributes(lp);
    }

    @DrawableRes
    private int whichBrightnessImageToUse(int brightnessInt) {
        if (brightnessInt <= 15) {
            return R.drawable.ic_brightness_1_white_36dp;
        } else if (brightnessInt <= 30 && brightnessInt > 15) {
            return R.drawable.ic_brightness_2_white_36dp;
        } else if (brightnessInt <= 45 && brightnessInt > 30) {
            return R.drawable.ic_brightness_3_white_36dp;
        } else if (brightnessInt <= 60 && brightnessInt > 45) {
            return R.drawable.ic_brightness_4_white_36dp;
        } else if (brightnessInt <= 75 && brightnessInt > 60) {
            return R.drawable.ic_brightness_5_white_36dp;
        } else if (brightnessInt <= 90 && brightnessInt > 75) {
            return R.drawable.ic_brightness_6_white_36dp;
        } else {
            return R.drawable.ic_brightness_7_white_36dp;
        }

    }

    private void setVolumeOrBrightnessInfo(String txt, @DrawableRes int drawableId) {
        centerInfo.setVisibility(View.VISIBLE);
        centerInfo.setText(txt);
        centerInfo.setTextColor(ContextCompat.getColor(getContext(), android.R.color.white));
        centerInfo.setCompoundDrawablesWithIntrinsicBounds(null,
                ContextCompat.getDrawable(getContext(), drawableId), null, null);
    }

    @Override
    public void onStart() {
        super.onStart();
        if (Util.SDK_INT > 23) {
            initializePlayer();
            Log.d(TAG, "path " + CURRENT_PATH);
            load(CURRENT_PATH);
            initVol();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if ((Util.SDK_INT <= 23 || player == null)) {
            initializePlayer();
            Log.d(TAG, "path " + CURRENT_PATH);
            load(CURRENT_PATH);
            initVol();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        if (Util.SDK_INT <= 23) {
            releasePlayer();
            mAudioManager = null;
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (Util.SDK_INT > 23) {
            releasePlayer();
            mAudioManager = null;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            initializePlayer();
        } else {
            showToast(R.string.storage_permission_denied);
            fragActivity.finish();
        }
    }

    // Activity input

    //@Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        // Show the controls on any key event.
        //simpleExoPlayerView.showController();
        // If the event was not handled then see if the player view can handle it as a media key event.
        return /*super.dispatchKeyEvent(event) || */simpleExoPlayerView.dispatchKeyEvent(event);//dispatchMediaKeyEvent
    }

    // OnClickListener methods

    @Override
    public void onClick(View view) {
        if (view == retryButton) {
            initializePlayer();
        } else if (view.getParent() == debugRootView) {
            MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
            if (mappedTrackInfo != null) {
                trackSelectionHelper.showSelectionDialog(fragActivity, ((Button) view).getText(),
                        trackSelector.getCurrentMappedTrackInfo(), (int) view.getTag());
            }
        }
    }

    // PlaybackControlView.VisibilityListener implementation

    @Override
    public void onVisibilityChange(int visibility) {
        debugRootView.setVisibility(visibility);
        debugTextView.setVisibility(visibility);
    }

    // Internal methods

    private void initializePlayer() {
        Intent intent = fragActivity.getIntent();
        boolean needNewPlayer = player == null;
        if (needNewPlayer) {
            boolean preferExtensionDecoders = intent.getBooleanExtra(PREFER_EXTENSION_DECODERS, false);
            UUID drmSchemeUuid = intent.hasExtra(DRM_SCHEME_UUID_EXTRA)
                    ? UUID.fromString(intent.getStringExtra(DRM_SCHEME_UUID_EXTRA))
                    : null;
            DrmSessionManager<FrameworkMediaCrypto> drmSessionManager = null;
            if (drmSchemeUuid != null) {
                String drmLicenseUrl = intent.getStringExtra(DRM_LICENSE_URL);
                String[] keyRequestPropertiesArray = intent.getStringArrayExtra(DRM_KEY_REQUEST_PROPERTIES);
                try {
                    drmSessionManager = buildDrmSessionManager(drmSchemeUuid, drmLicenseUrl,
                            keyRequestPropertiesArray);
                } catch (UnsupportedDrmException e) {
                    int errorStringId = Util.SDK_INT < 18 ? R.string.error_drm_not_supported
                            : (e.reason == UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME
                                    ? R.string.error_drm_unsupported_scheme
                                    : R.string.error_drm_unknown);
                    showToast(errorStringId);
                    return;
                }
            }

            @SimpleExoPlayer.ExtensionRendererMode
            int extensionRendererMode = ((ExplorerApplication) fragActivity.getApplication())
                    .useExtensionRenderers()
                            ? (preferExtensionDecoders ? SimpleExoPlayer.EXTENSION_RENDERER_MODE_PREFER
                                    : SimpleExoPlayer.EXTENSION_RENDERER_MODE_ON)
                            : SimpleExoPlayer.EXTENSION_RENDERER_MODE_OFF;
            TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
            trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
            trackSelectionHelper = new TrackSelectionHelper(trackSelector, videoTrackSelectionFactory);
            player = ExoPlayerFactory.newSimpleInstance(fragActivity, trackSelector, new DefaultLoadControl(),
                    drmSessionManager, extensionRendererMode);
            player.addListener(this);

            eventLogger = new EventLogger(trackSelector);
            player.addListener(eventLogger);
            player.setAudioDebugListener(eventLogger);
            player.setVideoDebugListener(eventLogger);
            player.setMetadataOutput(eventLogger);

            simpleExoPlayerView.setPlayer(player);
            player.setPlayWhenReady(shouldAutoPlay);
            debugViewHelper = new DebugTextViewHelper(player, debugTextView);
            debugViewHelper.start();
        }
        if (needNewPlayer || needRetrySource) {
            String action = intent.getAction();
            Uri[] uris;
            String[] extensions;
            if (Intent.ACTION_VIEW.equals(action)) {
                uris = new Uri[] { intent.getData() };
                extensions = new String[] { intent.getStringExtra(EXTENSION_EXTRA) };
            } else if (ACTION_VIEW.equals(action)) {
                uris = new Uri[] { intent.getData() };
                extensions = new String[] { intent.getStringExtra(EXTENSION_EXTRA) };
            } else if (ACTION_VIEW_LIST.equals(action)) {
                String[] uriStrings = intent.getStringArrayExtra(URI_LIST_EXTRA);
                uris = new Uri[uriStrings.length];
                for (int i = 0; i < uriStrings.length; i++) {
                    uris[i] = Uri.parse(uriStrings[i]);
                }
                extensions = intent.getStringArrayExtra(EXTENSION_LIST_EXTRA);
                if (extensions == null) {
                    extensions = new String[uriStrings.length];
                }
            } else {
                if (!Intent.ACTION_MAIN.equals(action)) {
                    showToast(getString(R.string.unexpected_intent_action, action));
                }
                return;
            }
            if (Util.maybeRequestReadExternalStoragePermission(fragActivity, uris)) {
                // The player will be reinitialized if the permission is granted.
                return;
            }
            MediaSource[] mediaSources = new MediaSource[uris.length];
            for (int i = 0; i < uris.length; i++) {
                mediaSources[i] = buildMediaSource(uris[i], extensions[i]);
            }
            MediaSource mediaSource = mediaSources.length == 1 ? mediaSources[0]
                    : new ConcatenatingMediaSource(mediaSources);
            boolean haveResumePosition = resumeWindow != C.INDEX_UNSET;
            if (haveResumePosition) {
                player.seekTo(resumeWindow, resumePosition);
            }
            player.prepare(mediaSource, !haveResumePosition, false);
            needRetrySource = false;
            updateButtonVisibilities();
        }
    }

    private MediaSource buildMediaSource(Uri uri, String overrideExtension) {
        int type = TextUtils.isEmpty(overrideExtension) ? Util.inferContentType(uri)
                : Util.inferContentType("." + overrideExtension);
        switch (type) {
        case C.TYPE_SS:
            return new SsMediaSource(uri, buildDataSourceFactory(false),
                    new DefaultSsChunkSource.Factory(mediaDataSourceFactory), mainHandler, eventLogger);
        case C.TYPE_DASH:
            return new DashMediaSource(uri, buildDataSourceFactory(false),
                    new DefaultDashChunkSource.Factory(mediaDataSourceFactory), mainHandler, eventLogger);
        case C.TYPE_HLS:
            return new HlsMediaSource(uri, mediaDataSourceFactory, mainHandler, eventLogger);
        case C.TYPE_OTHER:
            return new ExtractorMediaSource(uri, mediaDataSourceFactory, new DefaultExtractorsFactory(),
                    mainHandler, eventLogger);
        default: {
            throw new IllegalStateException("Unsupported type: " + type);
        }
        }
    }

    private DrmSessionManager<FrameworkMediaCrypto> buildDrmSessionManager(UUID uuid, String licenseUrl,
            String[] keyRequestPropertiesArray) throws UnsupportedDrmException {
        if (Util.SDK_INT < 18) {
            return null;
        }
        HttpMediaDrmCallback drmCallback = new HttpMediaDrmCallback(licenseUrl, buildHttpDataSourceFactory(false));
        if (keyRequestPropertiesArray != null) {
            for (int i = 0; i < keyRequestPropertiesArray.length - 1; i += 2) {
                drmCallback.setKeyRequestProperty(keyRequestPropertiesArray[i], keyRequestPropertiesArray[i + 1]);
            }
        }
        return new DefaultDrmSessionManager<FrameworkMediaCrypto>(uuid, FrameworkMediaDrm.newInstance(uuid),
                drmCallback, null, mainHandler, eventLogger);
    }

    private void releasePlayer() {
        if (player != null) {
            debugViewHelper.stop();
            debugViewHelper = null;
            shouldAutoPlay = player.getPlayWhenReady();
            updateResumePosition();
            player.release();
            player = null;
            trackSelector = null;
            trackSelectionHelper = null;
            eventLogger = null;
        }
    }

    private void updateResumePosition() {
        resumeWindow = player.getCurrentWindowIndex();
        resumePosition = player.isCurrentWindowSeekable() ? Math.max(0, player.getCurrentPosition()) : C.TIME_UNSET;
    }

    private void clearResumePosition() {
        resumeWindow = C.INDEX_UNSET;
        resumePosition = C.TIME_UNSET;
    }

    /**
     * Returns a new DataSource factory.
     *
     * @param useBandwidthMeter Whether to set {@link #BANDWIDTH_METER} as a listener to the new
     *     DataSource factory.
     * @return A new DataSource factory.
     */
    private DataSource.Factory buildDataSourceFactory(boolean useBandwidthMeter) {
        return ((ExplorerApplication) fragActivity.getApplication())
                .buildDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null);
    }

    /**
     * Returns a new HttpDataSource factory.
     *
     * @param useBandwidthMeter Whether to set {@link #BANDWIDTH_METER} as a listener to the new
     *     DataSource factory.
     * @return A new HttpDataSource factory.
     */
    private HttpDataSource.Factory buildHttpDataSourceFactory(boolean useBandwidthMeter) {
        return ((ExplorerApplication) fragActivity.getApplication())
                .buildHttpDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null);
    }

    // ExoPlayer.EventListener implementation

    @Override
    public void onLoadingChanged(boolean isLoading) {
        // Do nothing.
    }

    @Override
    public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
        if (playbackState == ExoPlayer.STATE_ENDED) {
            showControls();
        }
        updateButtonVisibilities();
    }

    @Override
    public void onPositionDiscontinuity() {
        if (needRetrySource) {
            // This will only occur if the user has performed a seek whilst in the error state. Update the
            // resume position so that if the user then retries, playback will resume from the position to
            // which they seeked.
            updateResumePosition();
        }
    }

    @Override
    public void onTimelineChanged(Timeline timeline, Object manifest) {
        // Do nothing.
    }

    @Override
    public void onPlayerError(ExoPlaybackException e) {
        String errorString = null;
        if (e.type == ExoPlaybackException.TYPE_RENDERER) {
            Exception cause = e.getRendererException();
            if (cause instanceof DecoderInitializationException) {
                // Special case for decoder initialization failures.
                DecoderInitializationException decoderInitializationException = (DecoderInitializationException) cause;
                if (decoderInitializationException.decoderName == null) {
                    if (decoderInitializationException.getCause() instanceof DecoderQueryException) {
                        errorString = getString(R.string.error_querying_decoders);
                    } else if (decoderInitializationException.secureDecoderRequired) {
                        errorString = getString(R.string.error_no_secure_decoder,
                                decoderInitializationException.mimeType);
                    } else {
                        errorString = getString(R.string.error_no_decoder, decoderInitializationException.mimeType);
                    }
                } else {
                    errorString = getString(R.string.error_instantiating_decoder,
                            decoderInitializationException.decoderName);
                }
            }
        }
        if (errorString != null) {
            showToast(errorString);
        }
        needRetrySource = true;
        if (isBehindLiveWindow(e)) {
            clearResumePosition();
            initializePlayer();
        } else {
            updateResumePosition();
            updateButtonVisibilities();
            showControls();
        }
    }

    @Override
    public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
        updateButtonVisibilities();
        MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
        if (mappedTrackInfo != null) {
            if (mappedTrackInfo.getTrackTypeRendererSupport(
                    C.TRACK_TYPE_VIDEO) == MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
                showToast(R.string.error_unsupported_video);
            }
            if (mappedTrackInfo.getTrackTypeRendererSupport(
                    C.TRACK_TYPE_AUDIO) == MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
                showToast(R.string.error_unsupported_audio);
            }
        }
    }

    // User controls

    private void updateButtonVisibilities() {
        debugRootView.removeAllViews();

        retryButton.setVisibility(needRetrySource ? View.VISIBLE : View.GONE);
        debugRootView.addView(retryButton);

        if (player == null) {
            return;
        }

        MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
        if (mappedTrackInfo == null) {
            return;
        }

        for (int i = 0; i < mappedTrackInfo.length; i++) {
            TrackGroupArray trackGroups = mappedTrackInfo.getTrackGroups(i);
            if (trackGroups.length != 0) {
                Button button = new Button(fragActivity);
                int label;
                switch (player.getRendererType(i)) {
                case C.TRACK_TYPE_AUDIO:
                    label = R.string.audio;
                    break;
                case C.TRACK_TYPE_VIDEO:
                    label = R.string.video;
                    break;
                case C.TRACK_TYPE_TEXT:
                    label = R.string.text;
                    break;
                default:
                    continue;
                }
                button.setText(label);
                button.setTag(i);
                button.setOnClickListener(this);
                debugRootView.addView(button, debugRootView.getChildCount() - 1);
            }
        }
    }

    private void showControls() {
        debugRootView.setVisibility(View.VISIBLE);
    }

    private void showToast(int messageId) {
        showToast(getString(messageId));
    }

    private void showToast(String message) {
        Toast.makeText(fragActivity.getApplicationContext(), message, Toast.LENGTH_LONG).show();
    }

    private static boolean isBehindLiveWindow(ExoPlaybackException e) {
        if (e.type != ExoPlaybackException.TYPE_SOURCE) {
            return false;
        }
        Throwable cause = e.getSourceException();
        while (cause != null) {
            if (cause instanceof BehindLiveWindowException) {
                return true;
            }
            cause = cause.getCause();
        }
        return false;
    }

}