diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index 96cc43e..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
deleted file mode 100644
index e7bedf3..0000000
--- a/.idea/copyright/profiles_settings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 5d19981..dc34569 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,18 +1,16 @@
-
-
-
@@ -27,17 +25,7 @@
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/README.md b/README.md
index 7922add..19e6a65 100644
--- a/README.md
+++ b/README.md
@@ -400,6 +400,7 @@ The programmatic configuration options shown above can also be configured direct
app:bvp_themeColor="@color/color_primary"
app:bvp_captionSize="22sp"
app:bvp_captionColor="@color/caption_color"
+ app:bvp_gestureType="SwipeGesture"
app:bvp_loadingStyle="DoubleBounce"
app:bvp_loop="false" />
```
diff --git a/app/build.gradle b/app/build.gradle
index 7146b50..a737063 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -20,9 +20,9 @@ android {
}
dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
- compile 'com.github.halilozercan:BetterVideoPlayer:1.1.0'
- compile "com.android.support:appcompat-v7:$project.googleAPIsVersion"
- compile "com.android.support:support-compat:$project.googleAPIsVersion"
- compile "com.android.support:support-v4:$project.googleAPIsVersion"
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(path: ":bettervideoplayer")
+ implementation "com.android.support:appcompat-v7:$project.googleAPIsVersion"
+ implementation "com.android.support:support-compat:$project.googleAPIsVersion"
+ implementation "com.android.support:support-v4:$project.googleAPIsVersion"
}
diff --git a/app/src/main/java/com/halilibo/sample/BackgroundActivity.java b/app/src/main/java/com/halilibo/sample/BackgroundActivity.java
index 0e43cdd..c6fac8e 100644
--- a/app/src/main/java/com/halilibo/sample/BackgroundActivity.java
+++ b/app/src/main/java/com/halilibo/sample/BackgroundActivity.java
@@ -3,6 +3,8 @@
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
+import android.view.View;
+import android.widget.Toast;
import com.halilibo.bettervideoplayer.BetterVideoCallback;
import com.halilibo.bettervideoplayer.BetterVideoPlayer;
@@ -14,7 +16,7 @@ protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_background);
- BetterVideoPlayer bvp = (BetterVideoPlayer) findViewById(R.id.bvp);
+ BetterVideoPlayer bvp = findViewById(R.id.bvp);
bvp.setSource(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.video));
bvp.setCallback(new BetterVideoCallback() {
@Override
@@ -57,5 +59,15 @@ public void onToggleControls(BetterVideoPlayer player, boolean isShowing) {
}
});
+
+ findViewById(R.id.example_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Toast.makeText(getApplicationContext(),
+ "You can put a background video on your login page ;)",
+ Toast.LENGTH_LONG)
+ .show();
+ }
+ });
}
}
diff --git a/app/src/main/java/com/halilibo/sample/MainActivity.java b/app/src/main/java/com/halilibo/sample/MainActivity.java
index 6ddc643..de61b1f 100644
--- a/app/src/main/java/com/halilibo/sample/MainActivity.java
+++ b/app/src/main/java/com/halilibo/sample/MainActivity.java
@@ -36,7 +36,7 @@ public void onClick(View view) {
}
});
- bvp = (BetterVideoPlayer) findViewById(R.id.bvp);
+ bvp = findViewById(R.id.bvp);
if(savedInstanceState == null) {
bvp.setAutoPlay(true);
@@ -52,10 +52,13 @@ public void onClick(View view) {
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
case R.id.action_enable_swipe:
- bvp.enableSwipeGestures();
+ bvp.enableSwipeGestures(getWindow());
+ break;
+ case R.id.action_enable_double_tap:
+ bvp.enableDoubleTapGestures(5000);
break;
case R.id.action_disable_swipe:
- bvp.disableSwipeGestures();
+ bvp.disableGestures();
break;
case R.id.action_show_bottombar:
bvp.setBottomProgressBarVisibility(true);
@@ -63,6 +66,11 @@ public boolean onMenuItemClick(MenuItem item) {
case R.id.action_hide_bottombar:
bvp.setBottomProgressBarVisibility(false);
break;
+ case R.id.action_show_captions:
+ bvp.setCaptions(R.raw.sub, CaptionsView.CMime.SUBRIP);
+ break;
+ case R.id.action_hide_captions:
+ bvp.removeCaptions();
}
return false;
}
diff --git a/app/src/main/res/layout/activity_background.xml b/app/src/main/res/layout/activity_background.xml
index e984692..9983ee1 100644
--- a/app/src/main/res/layout/activity_background.xml
+++ b/app/src/main/res/layout/activity_background.xml
@@ -22,9 +22,18 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CONTENT"
+ android:id="@+id/example_textview"
android:textSize="30sp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"/>
+
+
diff --git a/app/src/main/res/menu/menu_dizi.xml b/app/src/main/res/menu/menu_dizi.xml
index 35ab173..34f0fa5 100644
--- a/app/src/main/res/menu/menu_dizi.xml
+++ b/app/src/main/res/menu/menu_dizi.xml
@@ -2,10 +2,16 @@
xmlns:app="http://schemas.android.com/apk/res-auto">
-
+
+
+
diff --git a/app/src/main/res/raw/sub.srt b/app/src/main/res/raw/sub.srt
index d28261c..de89302 100644
--- a/app/src/main/res/raw/sub.srt
+++ b/app/src/main/res/raw/sub.srt
@@ -1,53 +1,33 @@
0
-00:00:04,170 --> 00:00:05,838
-Subtitle 1
-
-1
-00:00:05,840 --> 00:00:06,772
-Subtitle 2
-
-2
-00:00:06,774 --> 00:00:08,440
-Subtitle 3
-
-3
-00:00:08,442 --> 00:00:10,109
-Subtitle 4
-
-4
-00:00:10,111 --> 00:00:11,610
-Subtitle 5
+00:00:04,170 --> 00:00:11,610
+A beautiful sky and forest
5
-00:00:11,612 --> 00:00:12,678
-Subtitle 6
-
-6
-00:00:12,680 --> 00:00:14,446
-Subtitle 7
+00:00:12,000 --> 00:00:14,446
+Dank river
7
-00:00:14,448 --> 00:00:18,283
-Subtitle 8
+00:00:15,448 --> 00:00:17,000
+Bird singing Take on me ♬
8
-00:00:18,285 --> 00:00:23,789
-Subtitle 9
+00:00:20,000 --> 00:00:22,000
+360 NO SCOPE
9
00:00:23,791 --> 00:00:26,392
-Subtitle 10
+Here are more captions
10
00:00:26,791 --> 00:00:29,392
-Subtitle 11
-New line
+What do you
+want me to say
11
-00:00:29,791 --> 00:00:45,392
-Subtitle 12
-
-New line
-Another new line
+00:00:29,791 --> 00:00:33,392
+Preparing captions is hard
-Final line
\ No newline at end of file
+12
+00:00:36,791 --> 00:00:43,392
+Holy shit, is that a bunny?
+I'm out!!
\ No newline at end of file
diff --git a/bettervideoplayer/build.gradle b/bettervideoplayer/build.gradle
index eccca27..f8b15eb 100644
--- a/bettervideoplayer/build.gradle
+++ b/bettervideoplayer/build.gradle
@@ -22,13 +22,13 @@ android {
}
dependencies {
- compile "com.android.support:appcompat-v7:$project.googleAPIsVersion"
- compile "com.android.support:support-compat:$project.googleAPIsVersion"
- compile "com.android.support:design:$project.googleAPIsVersion"
- compile 'me.zhanghai.android.materialprogressbar:library:1.1.6'
- compile 'org.adw.library:discrete-seekbar:1.0.1'
- compile 'com.devbrackets.android:exomedia:3.0.1'
- compile 'com.github.ybq:Android-SpinKit:1.1.0'
+ implementation "com.android.support:appcompat-v7:$project.googleAPIsVersion"
+ implementation "com.android.support:support-compat:$project.googleAPIsVersion"
+ implementation "com.android.support:design:$project.googleAPIsVersion"
+ implementation 'me.zhanghai.android.materialprogressbar:library:1.1.7'
+ implementation 'org.adw.library:discrete-seekbar:1.0.1'
+ implementation 'com.devbrackets.android:exomedia:3.0.1'
+ implementation 'com.github.ybq:Android-SpinKit:1.1.0'
}
// build a jar with source files
diff --git a/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/BetterVideoCallback.java b/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/BetterVideoCallback.java
index 9987ded..3105f6e 100644
--- a/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/BetterVideoCallback.java
+++ b/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/BetterVideoCallback.java
@@ -6,19 +6,55 @@
*/
public interface BetterVideoCallback {
+ /**
+ * Called right after Android MediaPlayer is started
+ * @param player
+ */
void onStarted(BetterVideoPlayer player);
+ /**
+ * Called right after Android MediaPlayer is paused
+ * @param player
+ */
void onPaused(BetterVideoPlayer player);
+ /**
+ * Called just before setting the source of Android MediaPlayer
+ * @param player
+ */
void onPreparing(BetterVideoPlayer player);
+ /**
+ * Called when Android MediaPlayer is prepared
+ * @param player
+ */
void onPrepared(BetterVideoPlayer player);
+ /**
+ * Called whenever Android MediaPlayer fires a BufferUpdate.
+ * @param percent
+ */
void onBuffering(int percent);
+ /**
+ * Exception occurred in the player.
+ * @param player
+ * @param e
+ */
void onError(BetterVideoPlayer player, Exception e);
+ /**
+ * Called after video is completed and every action is taken by the player.
+ * @param player
+ */
void onCompletion(BetterVideoPlayer player);
+ /**
+ * New: Control toggling might be of importance especially when using fullscreen.
+ * You might also adjust your layout or overlays according to controls' visibility.
+ * This method is called whenever visibility of controls is changed.
+ * @param player
+ * @param isShowing : True if controls are visible.
+ */
void onToggleControls(BetterVideoPlayer player, boolean isShowing);
}
\ No newline at end of file
diff --git a/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/BetterVideoPlayer.java b/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/BetterVideoPlayer.java
index e3cff64..5dfc0e1 100644
--- a/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/BetterVideoPlayer.java
+++ b/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/BetterVideoPlayer.java
@@ -70,1233 +70,1227 @@
* @author Aidan Follestad
* Modified and improved by Halil Ozercan
*/
-@SuppressWarnings("ALL")
public class BetterVideoPlayer extends RelativeLayout implements IUserMethods,
- TextureView.SurfaceTextureListener, MediaPlayer.OnPreparedListener,
- MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener,
- MediaPlayer.OnVideoSizeChangedListener, MediaPlayer.OnErrorListener,
- View.OnClickListener, SeekBar.OnSeekBarChangeListener{
-
- private static final String BETTER_VIDEO_PLAYER_BRIGHTNESS = "BETTER_VIDEO_PLAYER_BRIGHTNESS";
- private static final int UPDATE_INTERVAL = 100;
-
- private SpinKitView mProgressBar;
- private TextView mPositionTextView, viewForward, viewBackward;
-
- private CaptionsView mSubView;
- private AudioManager am;
- private Toolbar mToolbar;
- private String mTitle;
- private int mSubViewTextSize;
- private int mSubViewTextColor;
- private Context context;
-
- /**
- * Window that hold the player. Necessary for setting brightness.
- */
- private Window mWindow;
-
- private static final int DOUBLE_BOUNCE = 0;
- private static final int ROTATING_PLANE = 1;
- private static final int WAVE = 2;
- private static final int WANDERING_CUBES = 3;
- private static final int PULSE = 4;
- private static final int CHASING_DOTS = 5;
- private static final int THREE_BOUNCE = 6;
- private static final int CIRCLE = 7;
- private static final int CUBE_GRID = 8;
- private static final int FADING_CIRCLE = 9;
- private static final int ROTATING_CIRCLE = 10;
-
- @IntDef({DOUBLE_BOUNCE, ROTATING_PLANE, WAVE,
- WANDERING_CUBES, PULSE, CHASING_DOTS,
- THREE_BOUNCE, CIRCLE, CUBE_GRID,
- FADING_CIRCLE, ROTATING_CIRCLE})
- @Retention(RetentionPolicy.SOURCE)
- public @interface LoadingStyle {
- }
-
- private static final int PLAY_BUTTON = 0;
- private static final int PAUSE_BUTTON = 1;
- private static final int RESTART_BUTTON = 2;
-
- @IntDef({PLAY_BUTTON, PAUSE_BUTTON, RESTART_BUTTON})
- @Retention(RetentionPolicy.SOURCE)
- public @interface ButtonType {
- }
-
- public BetterVideoPlayer(Context context) {
- super(context);
- init(context, null);
- }
-
- public BetterVideoPlayer(Context context, AttributeSet attrs) {
- super(context, attrs);
- init(context, attrs);
- }
-
- public BetterVideoPlayer(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init(context, attrs);
- }
-
- private View mControlsFrame;
- private View mProgressFrame;
- private View mClickFrame;
- private View mToolbarFrame;
-
- private MediaPlayer mPlayer;
- private TextureView mTextureView;
- private Surface mSurface;
- private SeekBar mSeeker;
- private ProgressBar mBottomProgressBar;
- private TextView mLabelPosition;
- private TextView mLabelDuration;
- private ImageButton mBtnPlayPause;
-
- private boolean mSurfaceAvailable;
- private boolean mIsPrepared;
- private boolean mWasPlaying;
- private int mInitialTextureWidth;
- private int mInitialTextureHeight;
- private Handler mHandler;
-
- private int viewVisibility;
-
- private Uri mSource;
- private Map headers;
-
- private BetterVideoCallback mCallback;
- private BetterVideoProgressCallback mProgressCallback;
-
- private Drawable mPlayDrawable;
- private Drawable mPauseDrawable;
- private Drawable mRestartDrawable;
-
- private boolean mLoop = false;
- private boolean mHideControlsOnPlay = false;
- private boolean mShowTotalDuration = true;
- private boolean mBottomProgressBarVisibility = false;
- private boolean mShowToolbar = true;
- private boolean mSwipeEnabled = false;
- private boolean mAutoPlay = false;
- private boolean mControlsDisabled = false;
- private int mLoadingStyle = CHASING_DOTS;
- private int mInitialPosition = -1;
- private int mHideControlsDuration = 2000; // defaults to 2 seconds.
-
-
- private void init(Context context, AttributeSet attrs) {
- setBackgroundColor(Color.BLACK);
- this.context = context;
- if (attrs != null) {
- TypedArray a = context.getTheme().obtainStyledAttributes(
- attrs,
- R.styleable.BetterVideoPlayer,
- 0, 0);
- try {
-
- String source = a.getString(R.styleable.BetterVideoPlayer_bvp_source);
- if (source != null && !source.trim().isEmpty())
- mSource = Uri.parse(source);
-
- String title = a.getString(R.styleable.BetterVideoPlayer_bvp_title);
- if (title != null && !title.trim().isEmpty())
- mTitle = title;
-
- mPlayDrawable = a.getDrawable(
- R.styleable.BetterVideoPlayer_bvp_playDrawable);
- mPauseDrawable = a.getDrawable(
- R.styleable.BetterVideoPlayer_bvp_pauseDrawable);
- mRestartDrawable = a.getDrawable(
- R.styleable.BetterVideoPlayer_bvp_restartDrawable);
- mLoadingStyle = a.getInt(
- R.styleable.SpinKitView_SpinKit_Style, 0);
- mHideControlsDuration = a.getInteger(
- R.styleable.BetterVideoPlayer_bvp_hideControlsDuration, mHideControlsDuration);
-
- mHideControlsOnPlay = a.getBoolean(
- R.styleable.BetterVideoPlayer_bvp_hideControlsOnPlay, false);
- mAutoPlay = a.getBoolean(
- R.styleable.BetterVideoPlayer_bvp_autoPlay, false);
- mLoop = a.getBoolean(
- R.styleable.BetterVideoPlayer_bvp_loop, false);
- mShowTotalDuration = a.getBoolean(
- R.styleable.BetterVideoPlayer_bvp_showTotalDuration, false);
- mBottomProgressBarVisibility = a.getBoolean(
- R.styleable.BetterVideoPlayer_bvp_showBottomProgressBar, false);
- mSwipeEnabled = a.getBoolean(
- R.styleable.BetterVideoPlayer_bvp_swipeGesturesEnabled, false);
- mShowToolbar = a.getBoolean(
- R.styleable.BetterVideoPlayer_bvp_showToolbar, true);
- mControlsDisabled = a.getBoolean(
- R.styleable.BetterVideoPlayer_bvp_disableControls, false);
- mSubViewTextSize = a.getDimensionPixelSize(
- R.styleable.BetterVideoPlayer_bvp_captionSize,
- getResources().getDimensionPixelSize(R.dimen.bvp_subtitle_size));
- mSubViewTextColor = a.getColor(
- R.styleable.BetterVideoPlayer_bvp_captionColor,
- ContextCompat.getColor(context, R.color.bvp_subtitle_color));
-
- }
- catch (Exception e){
- LOG("Exception " + e.getMessage());
- e.printStackTrace();
- }
- finally {
- a.recycle();
- }
- } else {
- mSubViewTextSize = getResources().getDimensionPixelSize(R.dimen.bvp_subtitle_size);
- mSubViewTextColor = ContextCompat.getColor(context, R.color.bvp_subtitle_color);
+ TextureView.SurfaceTextureListener, MediaPlayer.OnPreparedListener,
+ MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener,
+ MediaPlayer.OnVideoSizeChangedListener, MediaPlayer.OnErrorListener,
+ View.OnClickListener, SeekBar.OnSeekBarChangeListener {
+
+ private static final String BETTER_VIDEO_PLAYER_BRIGHTNESS = "BETTER_VIDEO_PLAYER_BRIGHTNESS";
+ private static final int UPDATE_INTERVAL = 100;
+
+ private SpinKitView mProgressBar;
+ private TextView mPositionTextView, viewForward, viewBackward;
+
+ private CaptionsView mSubView;
+ private AudioManager am;
+ private Toolbar mToolbar;
+ private String mTitle;
+ private int mSubViewTextSize;
+ private int mSubViewTextColor;
+ private Context context;
+
+ /**
+ * Window that hold the player. Necessary for setting brightness.
+ */
+ private Window mWindow;
+
+ private static final int DOUBLE_BOUNCE = 0;
+ private static final int ROTATING_PLANE = 1;
+ private static final int WAVE = 2;
+ private static final int WANDERING_CUBES = 3;
+ private static final int PULSE = 4;
+ private static final int CHASING_DOTS = 5;
+ private static final int THREE_BOUNCE = 6;
+ private static final int CIRCLE = 7;
+ private static final int CUBE_GRID = 8;
+ private static final int FADING_CIRCLE = 9;
+ private static final int ROTATING_CIRCLE = 10;
+
+ @IntDef({DOUBLE_BOUNCE, ROTATING_PLANE, WAVE,
+ WANDERING_CUBES, PULSE, CHASING_DOTS,
+ THREE_BOUNCE, CIRCLE, CUBE_GRID,
+ FADING_CIRCLE, ROTATING_CIRCLE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LoadingStyle {
+ }
+
+ private static final int PLAY_BUTTON = 0;
+ private static final int PAUSE_BUTTON = 1;
+ private static final int RESTART_BUTTON = 2;
+
+ @IntDef({PLAY_BUTTON, PAUSE_BUTTON, RESTART_BUTTON})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ButtonType {
+ }
+
+ private static final int NO_GESTURE = 0;
+ private static final int SWIPE_GESTURE = 1;
+ private static final int DOUBLETAP_GESTURE = 2;
+
+ @IntDef({NO_GESTURE, SWIPE_GESTURE, DOUBLETAP_GESTURE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface GestureType {
+ }
+
+ public BetterVideoPlayer(Context context) {
+ super(context);
+ init(context, null);
+ }
+
+ public BetterVideoPlayer(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context, attrs);
+ }
+
+ public BetterVideoPlayer(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(context, attrs);
+ }
+
+ private View mControlsFrame;
+ private View mProgressFrame;
+ private View mClickFrame;
+ private View mToolbarFrame;
+
+ private MediaPlayer mPlayer;
+ private TextureView mTextureView;
+ private Surface mSurface;
+ private SeekBar mSeeker;
+ private ProgressBar mBottomProgressBar;
+ private TextView mLabelPosition;
+ private TextView mLabelDuration;
+ private ImageButton mBtnPlayPause;
+
+ private boolean mSurfaceAvailable;
+ private boolean mIsPrepared;
+ private boolean mWasPlaying;
+ private int mInitialTextureWidth;
+ private int mInitialTextureHeight;
+ private Handler mHandler;
+
+ private int viewVisibility;
+
+ private Uri mSource;
+ private Map headers;
+
+ private BetterVideoCallback mCallback;
+ private BetterVideoProgressCallback mProgressCallback;
+
+ private Drawable mPlayDrawable;
+ private Drawable mPauseDrawable;
+ private Drawable mRestartDrawable;
+
+ private boolean mLoop = false;
+ private boolean mHideControlsOnPlay = false;
+ private boolean mShowTotalDuration = true;
+ private boolean mBottomProgressBarVisibility = false;
+ private boolean mShowToolbar = true;
+ private int mGestureType = NO_GESTURE;
+ private boolean mAutoPlay = false;
+ private boolean mControlsDisabled = false;
+ private int mLoadingStyle = CHASING_DOTS;
+ private int mInitialPosition = -1;
+ private int mHideControlsDuration = 2000; // defaults to 2 seconds.
+ private int mDoubleTapSeekDuration;
+
+
+ private void init(Context context, AttributeSet attrs) {
+ setBackgroundColor(Color.BLACK);
+ this.context = context;
+ if (attrs != null) {
+ TypedArray a = context.getTheme().obtainStyledAttributes(
+ attrs,
+ R.styleable.BetterVideoPlayer,
+ 0, 0);
+ try {
+
+ String source = a.getString(R.styleable.BetterVideoPlayer_bvp_source);
+ if (source != null && !source.trim().isEmpty())
+ mSource = Uri.parse(source);
+
+ String title = a.getString(R.styleable.BetterVideoPlayer_bvp_title);
+ if (title != null && !title.trim().isEmpty())
+ mTitle = title;
+
+ mPlayDrawable = a.getDrawable(
+ R.styleable.BetterVideoPlayer_bvp_playDrawable);
+ mPauseDrawable = a.getDrawable(
+ R.styleable.BetterVideoPlayer_bvp_pauseDrawable);
+ mRestartDrawable = a.getDrawable(
+ R.styleable.BetterVideoPlayer_bvp_restartDrawable);
+ mLoadingStyle = a.getInt(
+ R.styleable.SpinKitView_SpinKit_Style, 0);
+ mHideControlsDuration = a.getInteger(
+ R.styleable.BetterVideoPlayer_bvp_hideControlsDuration, mHideControlsDuration);
+
+ mHideControlsOnPlay = a.getBoolean(
+ R.styleable.BetterVideoPlayer_bvp_hideControlsOnPlay, false);
+ mAutoPlay = a.getBoolean(
+ R.styleable.BetterVideoPlayer_bvp_autoPlay, false);
+ mLoop = a.getBoolean(
+ R.styleable.BetterVideoPlayer_bvp_loop, false);
+ mShowTotalDuration = a.getBoolean(
+ R.styleable.BetterVideoPlayer_bvp_showTotalDuration, false);
+ mBottomProgressBarVisibility = a.getBoolean(
+ R.styleable.BetterVideoPlayer_bvp_showBottomProgressBar, false);
+ mGestureType = a.getInt(
+ R.styleable.BetterVideoPlayer_bvp_gestureType, 0);
+ mShowToolbar = a.getBoolean(
+ R.styleable.BetterVideoPlayer_bvp_showToolbar, true);
+ mControlsDisabled = a.getBoolean(
+ R.styleable.BetterVideoPlayer_bvp_disableControls, false);
+ mSubViewTextSize = a.getDimensionPixelSize(
+ R.styleable.BetterVideoPlayer_bvp_captionSize,
+ getResources().getDimensionPixelSize(R.dimen.bvp_subtitle_size));
+ mSubViewTextColor = a.getColor(
+ R.styleable.BetterVideoPlayer_bvp_captionColor,
+ ContextCompat.getColor(context, R.color.bvp_subtitle_color));
+
+ } catch (Exception e) {
+ LOG("Exception " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ a.recycle();
+ }
+ } else {
+ mSubViewTextSize = getResources().getDimensionPixelSize(R.dimen.bvp_subtitle_size);
+ mSubViewTextColor = ContextCompat.getColor(context, R.color.bvp_subtitle_color);
+ }
+
+ if (mPlayDrawable == null)
+ mPlayDrawable = ContextCompat.getDrawable(context, R.drawable.bvp_action_play);
+ if (mPauseDrawable == null)
+ mPauseDrawable = ContextCompat.getDrawable(context, R.drawable.bvp_action_pause);
+ if (mRestartDrawable == null)
+ mRestartDrawable = ContextCompat.getDrawable(context, R.drawable.bvp_action_restart);
+
+ // Have a default callback. setCallback will change this
+ mCallback = new EmptyCallback();
+ }
+
+ @Override
+ public void setSource(@NonNull Uri source) {
+ mSource = source;
+ if (mPlayer != null) prepare();
+ }
+
+ @Override
+ public void setSource(@NonNull Uri source, @NonNull Map headers) {
+ this.headers = headers;
+ setSource(source);
+ }
+
+ @Override
+ public void setCallback(@NonNull BetterVideoCallback callback) {
+ mCallback = callback;
+ }
+
+ @Override
+ public void setCaptionLoadListener(@Nullable CaptionsView.CaptionsViewLoadListener listener) {
+ mSubView.setCaptionsViewLoadListener(listener);
+ }
+
+ @Override
+ public void setProgressCallback(@NonNull BetterVideoProgressCallback callback) {
+ mProgressCallback = callback;
+ }
+
+ @Override
+ public void setButtonDrawable(@BetterVideoPlayer.ButtonType int type,
+ @NonNull Drawable drawable) {
+ switch (type) {
+ case PLAY_BUTTON:
+ mPlayDrawable = drawable;
+ if (!isPlaying()) {
+ mBtnPlayPause.setImageDrawable(drawable);
}
-
- if (mPlayDrawable == null)
- mPlayDrawable = ContextCompat.getDrawable(context, R.drawable.bvp_action_play);
- if (mPauseDrawable == null)
- mPauseDrawable = ContextCompat.getDrawable(context, R.drawable.bvp_action_pause);
- if (mRestartDrawable == null)
- mRestartDrawable = ContextCompat.getDrawable(context, R.drawable.bvp_action_restart);
-
- // Have a default callback. setCallback will change this
- mCallback = new EmptyCallback();
- }
-
- @Override
- public void setSource(@NonNull Uri source) {
- mSource = source;
- if (mPlayer != null) prepare();
- }
-
- @Override
- public void setSource(@NonNull Uri source, @NonNull Map headers) {
- this.headers = headers;
- setSource(source);
- }
-
- @Override
- public void setCallback(@NonNull BetterVideoCallback callback) {
- mCallback = callback;
- }
-
- @Override
- public void setCaptionLoadListener(@Nullable CaptionsView.CaptionsViewLoadListener listener) {
- mSubView.setCaptionsViewLoadListener(listener);
- }
-
- @Override
- public void setProgressCallback(@NonNull BetterVideoProgressCallback callback) {
- mProgressCallback = callback;
- }
-
- @Override
- public void setButtonDrawable(@BetterVideoPlayer.LoadingStyle int type,
- @NonNull Drawable drawable) {
- switch (type){
- case PLAY_BUTTON:
- mPlayDrawable = drawable;
- if (!isPlaying()) {
- mBtnPlayPause.setImageDrawable(drawable);
- }
- break;
- case PAUSE_BUTTON:
- mPauseDrawable = drawable;
- if (isPlaying()) {
- mBtnPlayPause.setImageDrawable(drawable);
- }
- break;
- case RESTART_BUTTON:
- mPauseDrawable = drawable;
- if (mPlayer != null && mPlayer.getCurrentPosition() >= mPlayer.getDuration()) {
- mBtnPlayPause.setImageDrawable(drawable);
- }
- break;
+ break;
+ case PAUSE_BUTTON:
+ mPauseDrawable = drawable;
+ if (isPlaying()) {
+ mBtnPlayPause.setImageDrawable(drawable);
}
- }
-
- @Override
- public void setHideControlsOnPlay(boolean hide) {
- mHideControlsOnPlay = hide;
- }
-
- @Override
- public void setAutoPlay(boolean autoPlay) {
- mAutoPlay = autoPlay;
- }
-
- @Override
- public void enableSwipeGestures() {
- mSwipeEnabled = true;
- }
-
- @Override
- public void enableSwipeGestures(@NonNull Window window) {
- mSwipeEnabled = true;
- mWindow = window;
- }
-
- @Override
- public void disableSwipeGestures() {
- mSwipeEnabled = false;
- }
-
- @Override
- public void showToolbar() {
- mShowToolbar = true;
- }
-
- @Override
- public void hideToolbar() {
- mShowToolbar = false;
- hideToolbarWithAnimation();
- }
-
- @Override
- public void setInitialPosition(@IntRange(from = 0, to = Integer.MAX_VALUE) int pos) {
- mInitialPosition = pos;
- }
-
- private void prepare() {
- if (!mSurfaceAvailable || mSource == null || mPlayer == null || mIsPrepared)
- return;
- try {
- hideControls();
- mCallback.onPreparing(this);
- mPlayer.setSurface(mSurface);
- if (mSource.getScheme().equals("http") || mSource.getScheme().equals("https")) {
- LOG("Loading web URI: " + mSource.toString());
- mPlayer.setDataSource(getContext(), mSource, headers);
- } else {
- LOG("Loading local URI: " + mSource.toString());
- mPlayer.setDataSource(getContext(), mSource, headers);
- }
- mPlayer.prepareAsync();
- } catch (IOException e) {
- throwError(e);
+ break;
+ case RESTART_BUTTON:
+ mPauseDrawable = drawable;
+ if (mPlayer != null && mPlayer.getCurrentPosition() >= mPlayer.getDuration()) {
+ mBtnPlayPause.setImageDrawable(drawable);
}
- }
-
- public void setDoubleTap(final int seek) {
- mClickFrame.setOnTouchListener(new View.OnTouchListener() {
-
- int screenWidthHalf = Util.getScreenWidth(context)/2;
-
- private GestureDetector gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
- @Override
- public boolean onDoubleTap(MotionEvent e) {
- int seekSec = seek/1000;
- viewForward.setText(seekSec + " seconds");
- viewBackward.setText(seekSec + " seconds");
- if(e.getX() > screenWidthHalf) {
- animateViewFade(viewForward, 1);
- seekTo(getCurrentPosition() + seek);
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- animateViewFade(viewForward, 0);
- }
- }, 500);
- } else {
- animateViewFade(viewBackward, 1);
- seekTo(getCurrentPosition() - seek);
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- animateViewFade(viewBackward, 0);
- }
- }, 500);
- }
- return true;
- }
-
- @Override
- public boolean onSingleTapConfirmed(MotionEvent e) {
- toggleControls();
- return true;
- }
- });
-
- @Override
- public boolean onTouch(View view, MotionEvent motionEvent) {
- gestureDetector.onTouchEvent(motionEvent);
- return true;
- }
+ break;
+ }
+ }
+
+ @Override
+ public void setHideControlsOnPlay(boolean hide) {
+ mHideControlsOnPlay = hide;
+ }
+
+ @Override
+ public void setAutoPlay(boolean autoPlay) {
+ mAutoPlay = autoPlay;
+ }
+
+ @Override
+ public void enableSwipeGestures() {
+ mGestureType = SWIPE_GESTURE;
+ }
+
+ @Override
+ public void enableSwipeGestures(@NonNull Window window) {
+ mGestureType = SWIPE_GESTURE;
+ mWindow = window;
+ }
+
+ @Override
+ public void enableDoubleTapGestures(int seek) {
+ mDoubleTapSeekDuration = seek;
+ mGestureType = DOUBLETAP_GESTURE;
+ }
+
+ @Override
+ public void disableGestures() {
+ mGestureType = NO_GESTURE;
+ }
+
+ private void animateViewFade(final View view, final int alpha) {
+ viewVisibility = alpha > 0 ? View.VISIBLE : View.INVISIBLE;
+ view.animate()
+ .alpha(alpha)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ view.setVisibility(viewVisibility);
+ }
});
- }
-
- private void animateViewFade(final View view, final int alpha) {
- viewVisibility = alpha > 0 ? View.VISIBLE : View.INVISIBLE;
- view.animate()
- .alpha(alpha)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- view.setVisibility(viewVisibility);
- }
- });
- }
-
- private void setControlsEnabled(boolean enabled) {
- if (mSeeker == null)
- return;
-
- mSeeker.setEnabled(enabled);
- mBtnPlayPause.setEnabled(enabled);
-
- final float disabledAlpha = .4f;
- mBtnPlayPause.setAlpha(enabled ? 1f : disabledAlpha);
-
- mClickFrame.setEnabled(enabled);
- }
-
- @Override
- public void showControls() {
- mCallback.onToggleControls(this, true);
- if (mControlsDisabled || isControlsShown() || mSeeker == null)
- return;
- mControlsFrame.animate().cancel();
- mControlsFrame.setAlpha(0f);
- mControlsFrame.setVisibility(View.VISIBLE);
- mControlsFrame.animate().alpha(1f).translationY(0).setListener(null)
- .setInterpolator(new DecelerateInterpolator()).start();
-
- final View subViewParent = (View) mSubView.getParent();
- subViewParent.animate().cancel();
- subViewParent.setTranslationY(mControlsFrame.getHeight());
- subViewParent.animate()
- .translationY(0)
- .setInterpolator(new DecelerateInterpolator())
- .start();
-
- if(mBottomProgressBarVisibility) {
- mBottomProgressBar.animate().cancel();
- mBottomProgressBar.setAlpha(1f);
- mBottomProgressBar.animate().alpha(0f).start();
- }
-
- if(mShowToolbar) {
- mToolbarFrame.animate().cancel();
- mToolbarFrame.setAlpha(0f);
- mToolbarFrame.setVisibility(View.VISIBLE);
- mToolbarFrame.animate().alpha(1f).setListener(null)
- .setInterpolator(new DecelerateInterpolator()).start();
- }
- }
-
- @Override
- public void hideControls() {
- mCallback.onToggleControls(this, false);
- if (mControlsDisabled || !isControlsShown() || mSeeker == null)
- return;
- mControlsFrame.animate().cancel();
- mControlsFrame.setAlpha(1f);
- mControlsFrame.setTranslationY(0f);
- mControlsFrame.setVisibility(View.VISIBLE);
- mControlsFrame.animate()
- .alpha(0f)
- .translationY(mControlsFrame.getHeight())
- .setInterpolator(new DecelerateInterpolator())
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (mControlsFrame != null)
- mControlsFrame.setVisibility(View.GONE);
- }
- }).start();
-
- final View subViewParent = (View) mSubView.getParent();
- subViewParent.animate().cancel();
- subViewParent.animate()
- .translationY(mControlsFrame.getHeight())
- .setInterpolator(new DecelerateInterpolator())
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- subViewParent.setTranslationY(0);
- }
- }).start();
-
- if(mBottomProgressBarVisibility) {
- mBottomProgressBar.animate().cancel();
- mBottomProgressBar.setAlpha(0f);
- mBottomProgressBar.animate().alpha(1f).start();
- }
-
- hideToolbarWithAnimation();
- }
-
- private void hideToolbarWithAnimation() {
- if(mToolbarFrame.getVisibility() == VISIBLE) {
- mToolbarFrame.animate().cancel();
- mToolbarFrame.setAlpha(1f);
- mToolbarFrame.setVisibility(View.VISIBLE);
- mToolbarFrame.animate().alpha(0f)
- .setInterpolator(new DecelerateInterpolator())
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (mToolbarFrame != null)
- mToolbarFrame.setVisibility(View.GONE);
- }
- }).start();
- }
- }
-
- @CheckResult
- @Override
- public boolean isControlsShown() {
- return !mControlsDisabled && mControlsFrame != null && mControlsFrame.getAlpha() > .5f;
- }
-
- @Override
- public void toggleControls() {
- if (mControlsDisabled)
- return;
- if (isControlsShown()) {
- hideControls();
- } else {
- if(mHideControlsDuration >= 0) {
- mHandler.removeCallbacks(hideControlsRunnable);
- mHandler.postDelayed(hideControlsRunnable, mHideControlsDuration);
+ }
+
+ @Override
+ public void showToolbar() {
+ mShowToolbar = true;
+ }
+
+ @Override
+ public void hideToolbar() {
+ mShowToolbar = false;
+ hideToolbarWithAnimation();
+ }
+
+ @Override
+ public void setInitialPosition(@IntRange(from = 0, to = Integer.MAX_VALUE) int pos) {
+ mInitialPosition = pos;
+ }
+
+ private void prepare() {
+ if (!mSurfaceAvailable || mSource == null || mPlayer == null || mIsPrepared)
+ return;
+ try {
+ hideControls();
+ mCallback.onPreparing(this);
+ mPlayer.setSurface(mSurface);
+ if (mSource.getScheme().equals("http") || mSource.getScheme().equals("https")) {
+ LOG("Loading web URI: " + mSource.toString());
+ mPlayer.setDataSource(getContext(), mSource, headers);
+ } else {
+ LOG("Loading local URI: " + mSource.toString());
+ mPlayer.setDataSource(getContext(), mSource, headers);
+ }
+ mPlayer.prepareAsync();
+ } catch (IOException e) {
+ throwError(e);
+ }
+ }
+
+ private void setControlsEnabled(boolean enabled) {
+ if (mSeeker == null)
+ return;
+
+ mSeeker.setEnabled(enabled);
+ mBtnPlayPause.setEnabled(enabled);
+
+ final float disabledAlpha = .4f;
+ mBtnPlayPause.setAlpha(enabled ? 1f : disabledAlpha);
+
+ mClickFrame.setEnabled(enabled);
+ }
+
+ @Override
+ public void showControls() {
+ mCallback.onToggleControls(this, true);
+ if (mControlsDisabled || isControlsShown() || mSeeker == null)
+ return;
+ mControlsFrame.animate().cancel();
+ mControlsFrame.setAlpha(0f);
+ mControlsFrame.setVisibility(View.VISIBLE);
+ mControlsFrame.animate().alpha(1f).translationY(0).setListener(null)
+ .setInterpolator(new DecelerateInterpolator()).start();
+
+ final View subViewParent = (View) mSubView.getParent();
+ subViewParent.animate().cancel();
+ subViewParent.setTranslationY(mControlsFrame.getHeight());
+ subViewParent.animate()
+ .translationY(0)
+ .setInterpolator(new DecelerateInterpolator())
+ .start();
+
+ if (mBottomProgressBarVisibility) {
+ mBottomProgressBar.animate().cancel();
+ mBottomProgressBar.setAlpha(1f);
+ mBottomProgressBar.animate().alpha(0f).start();
+ }
+
+ if (mShowToolbar) {
+ mToolbarFrame.animate().cancel();
+ mToolbarFrame.setAlpha(0f);
+ mToolbarFrame.setVisibility(View.VISIBLE);
+ mToolbarFrame.animate().alpha(1f).setListener(null)
+ .setInterpolator(new DecelerateInterpolator()).start();
+ }
+ }
+
+ @Override
+ public void hideControls() {
+ mCallback.onToggleControls(this, false);
+ if (mControlsDisabled || !isControlsShown() || mSeeker == null)
+ return;
+ mControlsFrame.animate().cancel();
+ mControlsFrame.setAlpha(1f);
+ mControlsFrame.setTranslationY(0f);
+ mControlsFrame.setVisibility(View.VISIBLE);
+ mControlsFrame.animate()
+ .alpha(0f)
+ .translationY(mControlsFrame.getHeight())
+ .setInterpolator(new DecelerateInterpolator())
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mControlsFrame != null)
+ mControlsFrame.setVisibility(View.GONE);
+ }
+ }).start();
+
+ final View subViewParent = (View) mSubView.getParent();
+ subViewParent.animate().cancel();
+ subViewParent.animate()
+ .translationY(mControlsFrame.getHeight())
+ .setInterpolator(new DecelerateInterpolator())
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ subViewParent.setTranslationY(0);
+ }
+ }).start();
+
+ if (mBottomProgressBarVisibility) {
+ mBottomProgressBar.animate().cancel();
+ mBottomProgressBar.setAlpha(0f);
+ mBottomProgressBar.animate().alpha(1f).start();
+ }
+
+ hideToolbarWithAnimation();
+ }
+
+ private void hideToolbarWithAnimation() {
+ if (mToolbarFrame.getVisibility() == VISIBLE) {
+ mToolbarFrame.animate().cancel();
+ mToolbarFrame.setAlpha(1f);
+ mToolbarFrame.setVisibility(View.VISIBLE);
+ mToolbarFrame.animate().alpha(0f)
+ .setInterpolator(new DecelerateInterpolator())
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mToolbarFrame != null)
+ mToolbarFrame.setVisibility(View.GONE);
}
- showControls();
- }
- }
-
- @Override
- public void setBottomProgressBarVisibility(boolean isShowing) {
- this.mBottomProgressBarVisibility = isShowing;
- if(isShowing) {
- mBottomProgressBar.setVisibility(View.VISIBLE);
- } else {
- mBottomProgressBar.setVisibility(View.GONE);
- }
- }
-
- @Override
- public void setHideControlsDuration(int hideControlsDuration) {
- this.mHideControlsDuration = hideControlsDuration;
- }
-
- @Override
- public int getHideControlsDuration(){
- return mHideControlsDuration;
- }
-
- @Override
- public void enableControls() {
- mControlsDisabled = false;
- mClickFrame.setClickable(true);
- mClickFrame.setOnTouchListener(clickFrameSwipeListener);
- }
-
- @Override
- public void disableControls() {
- mControlsDisabled = true;
- mControlsFrame.setVisibility(View.GONE);
- mToolbarFrame.setVisibility(View.GONE);
- mClickFrame.setOnTouchListener(null);
- mClickFrame.setClickable(false);
- }
-
- @Override
- public boolean isPrepared() {
- return mPlayer != null && mIsPrepared;
- }
-
- @Override
- public boolean isPlaying() {
- return mPlayer != null && mPlayer.isPlaying();
- }
-
- @Override
- public int getCurrentPosition() {
- if (mPlayer == null) return -1;
- return mPlayer.getCurrentPosition();
- }
-
- @Override
- public int getDuration() {
- if (mPlayer == null) return -1;
- return mPlayer.getDuration();
- }
-
- @Override
- public void start() {
- if (mPlayer == null) return;
- mPlayer.start();
- mCallback.onStarted(this);
- if (mHandler == null) mHandler = new Handler();
- mHandler.post(mUpdateCounters);
- mBtnPlayPause.setImageDrawable(mPauseDrawable);
- }
-
- @Override
- public void seekTo(@IntRange(from = 0, to = Integer.MAX_VALUE) int pos) {
- if (mPlayer == null) {
- return;
- }
- mPlayer.seekTo(pos);
- }
-
- public void setVolume(@FloatRange(from = 0f, to = 1f) float leftVolume,
- @FloatRange(from = 0f, to = 1f) float rightVolume) {
- if (mPlayer == null || !mIsPrepared) {
- throw new IllegalStateException(
- "You cannot use setVolume(float, float) until the player is prepared.");
- }
- mPlayer.setVolume(leftVolume, rightVolume);
- }
-
- @Override
- public void pause() {
- if (mPlayer == null || !isPlaying()) {
- return;
- }
- mPlayer.pause();
- mCallback.onPaused(this);
- if (mHandler == null) {
- return;
- }
- mHandler.removeCallbacks(hideControlsRunnable);
- mHandler.removeCallbacks(mUpdateCounters);
- mBtnPlayPause.setImageDrawable(mPlayDrawable);
- }
-
- @Override
- public void stop() {
- if (mPlayer == null) return;
- try {
- mPlayer.stop();
- } catch (Throwable ignored) {
- }
- if (mHandler == null) return;
+ }).start();
+ }
+ }
+
+ @CheckResult
+ @Override
+ public boolean isControlsShown() {
+ return !mControlsDisabled && mControlsFrame != null && mControlsFrame.getAlpha() > .5f;
+ }
+
+ @Override
+ public void toggleControls() {
+ if (mControlsDisabled)
+ return;
+ if (isControlsShown()) {
+ hideControls();
+ } else {
+ if (mHideControlsDuration >= 0) {
mHandler.removeCallbacks(hideControlsRunnable);
- mHandler.removeCallbacks(mUpdateCounters);
- mBtnPlayPause.setImageDrawable(mPauseDrawable);
- }
-
- @Override
- public void reset() {
- if (mPlayer == null) return;
- mIsPrepared = false;
- mPlayer.reset();
- mIsPrepared = false;
- }
-
- @Override
- public void release() {
- mIsPrepared = false;
-
- if (mPlayer != null) {
- try {
- mPlayer.release();
- } catch (Throwable ignored) {
- }
- mPlayer = null;
- }
-
- if (mHandler != null) {
- mHandler.removeCallbacks(mUpdateCounters);
- mHandler = null;
- }
-
- LOG("Released player and Handler");
- }
-
- @Override
- public void setCaptions(Uri source, CaptionsView.CMime cMime) {
- mSubView.setCaptionsSource(source, cMime);
- }
-
+ mHandler.postDelayed(hideControlsRunnable, mHideControlsDuration);
+ }
+ showControls();
+ }
+ }
+
+ @Override
+ public void setBottomProgressBarVisibility(boolean isShowing) {
+ this.mBottomProgressBarVisibility = isShowing;
+ if (isShowing) {
+ mBottomProgressBar.setVisibility(View.VISIBLE);
+ } else {
+ mBottomProgressBar.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public void setHideControlsDuration(int hideControlsDuration) {
+ this.mHideControlsDuration = hideControlsDuration;
+ }
+
+ @Override
+ public int getHideControlsDuration() {
+ return mHideControlsDuration;
+ }
+
+ @Override
+ public void enableControls() {
+ mControlsDisabled = false;
+ mClickFrame.setClickable(true);
+ mClickFrame.setOnTouchListener(clickFrameSwipeListener);
+ }
+
+ @Override
+ public void disableControls() {
+ mControlsDisabled = true;
+ mControlsFrame.setVisibility(View.GONE);
+ mToolbarFrame.setVisibility(View.GONE);
+ mClickFrame.setOnTouchListener(null);
+ mClickFrame.setClickable(false);
+ }
+
+ @Override
+ public boolean isPrepared() {
+ return mPlayer != null && mIsPrepared;
+ }
+
+ @Override
+ public boolean isPlaying() {
+ return mPlayer != null && mPlayer.isPlaying();
+ }
+
+ @Override
+ public int getCurrentPosition() {
+ if (mPlayer == null) return -1;
+ return mPlayer.getCurrentPosition();
+ }
+
+ @Override
+ public int getDuration() {
+ if (mPlayer == null) return -1;
+ return mPlayer.getDuration();
+ }
+
+ @Override
+ public void start() {
+ if (mPlayer == null) return;
+ mPlayer.start();
+ mCallback.onStarted(this);
+ if (mHandler == null) mHandler = new Handler();
+ mHandler.post(mUpdateCounters);
+ mBtnPlayPause.setImageDrawable(mPauseDrawable);
+ }
+
+ @Override
+ public void seekTo(@IntRange(from = 0, to = Integer.MAX_VALUE) int pos) {
+ if (mPlayer == null) {
+ return;
+ }
+ if(Build.VERSION.SDK_INT >= 26) {
+ mPlayer.seekTo(pos, MediaPlayer.SEEK_CLOSEST);
+ }
+ else {
+ mPlayer.seekTo(pos);
+ }
+ }
+
+ public void setVolume(@FloatRange(from = 0f, to = 1f) float leftVolume,
+ @FloatRange(from = 0f, to = 1f) float rightVolume) {
+ if (mPlayer == null || !mIsPrepared) {
+ throw new IllegalStateException(
+ "You cannot use setVolume(float, float) until the player is prepared.");
+ }
+ mPlayer.setVolume(leftVolume, rightVolume);
+ }
+
+ @Override
+ public void pause() {
+ if (mPlayer == null || !isPlaying()) {
+ return;
+ }
+ mPlayer.pause();
+ mCallback.onPaused(this);
+ if (mHandler == null) {
+ return;
+ }
+ mHandler.removeCallbacks(hideControlsRunnable);
+ mHandler.removeCallbacks(mUpdateCounters);
+ mBtnPlayPause.setImageDrawable(mPlayDrawable);
+ }
+
+ @Override
+ public void stop() {
+ if (mPlayer == null) return;
+ try {
+ mPlayer.stop();
+ } catch (Throwable ignored) {
+ }
+ if (mHandler == null) return;
+ mHandler.removeCallbacks(hideControlsRunnable);
+ mHandler.removeCallbacks(mUpdateCounters);
+ mBtnPlayPause.setImageDrawable(mPauseDrawable);
+ }
+
+ @Override
+ public void reset() {
+ if (mPlayer == null) return;
+ mIsPrepared = false;
+ mPlayer.reset();
+ mIsPrepared = false;
+ }
+
+ @Override
+ public void release() {
+ mIsPrepared = false;
+
+ if (mPlayer != null) {
+ try {
+ mPlayer.release();
+ } catch (Throwable ignored) {
+ }
+ mPlayer = null;
+ }
+
+ if (mHandler != null) {
+ mHandler.removeCallbacks(mUpdateCounters);
+ mHandler = null;
+ }
+
+ LOG("Released player and Handler");
+ }
+
+ @Override
+ public void setCaptions(Uri source, CaptionsView.CMime cMime) {
+ mSubView.setCaptionsSource(source, cMime);
+ }
+
+ @Override
+ public void setCaptions(@RawRes int resId, CaptionsView.CMime cMime) {
+ mSubView.setCaptionsSource(resId, cMime);
+ }
+
+ @Override
+ public void removeCaptions() {
+ setCaptions(null, null);
+ }
+
+ @Override
+ public Toolbar getToolbar() {
+ return mToolbar;
+ }
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
+ LOG("Surface texture available: %dx%d", width, height);
+ mInitialTextureWidth = width;
+ mInitialTextureHeight = height;
+ mSurfaceAvailable = true;
+ mSurface = new Surface(surfaceTexture);
+ if (mIsPrepared) {
+ LOG("Surface texture available and media player is prepared");
+ mPlayer.setSurface(mSurface);
+ } else {
+ prepare();
+ }
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {
+ LOG("Surface texture changed: %dx%d", width, height);
+ adjustAspectRatio(width, height, mPlayer.getVideoWidth(), mPlayer.getVideoHeight());
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+ LOG("Surface texture destroyed");
+ mSurfaceAvailable = false;
+ mSurface = null;
+ return false;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
+ }
+
+ // Media player listeners
+
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+ @Override
+ public void onPrepared(MediaPlayer mediaPlayer) {
+ LOG("onPrepared()");
+ mProgressBar.setVisibility(View.INVISIBLE);
+ showControls();
+ mIsPrepared = true;
+
+ if (mCallback != null) {
+ mCallback.onPrepared(this);
+ }
+
+ mLabelPosition.setText(Util.getDurationString(0, false));
+ mLabelDuration.setText(Util.getDurationString(mediaPlayer.getDuration(), false));
+ mSeeker.setProgress(0);
+ mSeeker.setMax(mediaPlayer.getDuration());
+ setControlsEnabled(true);
+
+ if (mAutoPlay) {
+ if (!mControlsDisabled && mHideControlsOnPlay) {
+ mHandler.postDelayed(hideControlsRunnable, 500);
+ }
+ start();
+ if (mInitialPosition > 0) {
+ seekTo(mInitialPosition);
+ mInitialPosition = -1;
+ }
+ } else {
+ // Hack to show first frame, is there another way?
+ mPlayer.start();
+ mPlayer.pause();
+ }
+ }
+
+ @Override
+ public void onBufferingUpdate(MediaPlayer mediaPlayer, int percent) {
+ LOG("Buffering: %d%%", percent);
+ if (mCallback != null) {
+ mCallback.onBuffering(percent);
+ }
+ if (mSeeker != null) {
+ if (percent == 100) {
+ mSeeker.setSecondaryProgress(0);
+ mBottomProgressBar.setSecondaryProgress(0);
+ } else {
+ float percentage = percent / 100f;
+ int secondaryProgress = (int) (mSeeker.getMax() * percentage);
+ mSeeker.setSecondaryProgress(secondaryProgress);
+ mBottomProgressBar.setSecondaryProgress(secondaryProgress);
+ }
+ }
+ }
+
+ @Override
+ public void onCompletion(MediaPlayer mediaPlayer) {
+ LOG("onCompletion()");
+ mBtnPlayPause.setImageDrawable(mRestartDrawable);
+ if (mHandler != null)
+ mHandler.removeCallbacks(mUpdateCounters);
+ int currentProgress = mSeeker.getMax();
+ mSeeker.setProgress(currentProgress);
+ mBottomProgressBar.setProgress(currentProgress);
+ if (!mLoop) {
+ showControls();
+ } else {
+ start();
+ }
+ if (mCallback != null)
+ mCallback.onCompletion(this);
+ }
+
+ @Override
+ public void onVideoSizeChanged(MediaPlayer mediaPlayer, int width, int height) {
+ LOG("Video size changed: %dx%d", width, height);
+ adjustAspectRatio(mInitialTextureWidth, mInitialTextureHeight, width, height);
+
+ }
+
+ @Override
+ public boolean onError(MediaPlayer mediaPlayer, int what, int extra) {
+ if (what == -38) {
+ // Error code -38 happens on some Samsung devices
+ // Just ignore it
+ return false;
+ }
+ String errorMsg = "Preparation/playback error (" + what + "): ";
+ switch (what) {
+ default:
+ errorMsg += "Unknown error";
+ break;
+ case MediaPlayer.MEDIA_ERROR_IO:
+ errorMsg += "I/O error";
+ break;
+ case MediaPlayer.MEDIA_ERROR_MALFORMED:
+ errorMsg += "Malformed";
+ break;
+ case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
+ errorMsg += "Not valid for progressive playback";
+ break;
+ case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
+ errorMsg += "Server died";
+ break;
+ case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
+ errorMsg += "Timed out";
+ break;
+ case MediaPlayer.MEDIA_ERROR_UNSUPPORTED:
+ errorMsg += "Unsupported";
+ break;
+ }
+ throwError(new Exception(errorMsg));
+ return false;
+ }
+
+ // View events
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ setKeepScreenOn(true);
+
+ mHandler = new Handler();
+ mPlayer = new MediaPlayer();
+ mPlayer.setOnPreparedListener(this);
+ mPlayer.setOnBufferingUpdateListener(this);
+ mPlayer.setOnCompletionListener(this);
+ mPlayer.setOnVideoSizeChangedListener(this);
+ mPlayer.setOnErrorListener(this);
+ mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+
+ am = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
+
+ // Instantiate and add TextureView for rendering
+ final LayoutInflater li = LayoutInflater.from(getContext());
+ View mTextureFrame = li.inflate(R.layout.bvp_include_surface, this, false);
+ addView(mTextureFrame);
+
+ mTextureView = mTextureFrame.findViewById(R.id.textureview);
+ mTextureView.setSurfaceTextureListener(this);
+
+ viewForward = mTextureFrame.findViewById(R.id.view_forward);
+ viewBackward = mTextureFrame.findViewById(R.id.view_backward);
+
+ // Inflate and add progress
+ mProgressFrame = li.inflate(R.layout.bvp_include_progress, this, false);
+ mProgressBar = mProgressFrame.findViewById(R.id.spin_kit);
+ mBottomProgressBar = mProgressFrame.findViewById(R.id.progressBarBottom);
+
+ TypedValue typedValue = new TypedValue();
+ Resources.Theme theme = getContext().getTheme();
+ theme.resolveAttribute(R.attr.colorAccent, typedValue, true);
+ int color = typedValue.data;
+ mProgressBar.setColor(color);
+ setLoadingStyle(mLoadingStyle);
+
+ mPositionTextView = mProgressFrame.findViewById(R.id.position_textview);
+ mPositionTextView.setShadowLayer(3, 3, 3, Color.BLACK);
+ addView(mProgressFrame);
+
+ // Instantiate and add click frame (used to toggle controls)
+ mClickFrame = new FrameLayout(getContext());
+ //noinspection RedundantCast
+ ((FrameLayout) mClickFrame).setForeground(
+ Util.resolveDrawable(getContext(), R.attr.selectableItemBackground));
+ addView(mClickFrame, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+
+ // Inflate controls
+ mControlsFrame = li.inflate(R.layout.bvp_include_controls, this, false);
+ LayoutParams mControlsLp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ mControlsLp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+ addView(mControlsFrame, mControlsLp);
+
+ // Add topbar
+ mToolbarFrame = li.inflate(R.layout.bvp_include_topbar, this, false);
+ mToolbar = mToolbarFrame.findViewById(R.id.toolbar);
+ mToolbar.setTitle(mTitle);
+ mToolbarFrame.setVisibility(mShowToolbar ? VISIBLE : GONE);
+ addView(mToolbarFrame);
+
+ // Inflate subtitles
+ View mSubtitlesFrame = li.inflate(R.layout.bvp_include_subtitle, this, false);
+ LayoutParams mSubtitlesLp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ mSubtitlesLp.addRule(RelativeLayout.ABOVE, R.id.bvp_include_relativelayout);
+ mSubtitlesLp.alignWithParent = true;
+
+ mSubView = mSubtitlesFrame.findViewById(R.id.subs_box);
+ mSubView.setPlayer(mPlayer);
+
+ mSubView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mSubViewTextSize);
+ mSubView.setTextColor(mSubViewTextColor);
+
+ addView(mSubtitlesFrame, mSubtitlesLp);
+
+ // Retrieve controls
+ mSeeker = mControlsFrame.findViewById(R.id.seeker);
+ mSeeker.setOnSeekBarChangeListener(this);
+
+ mLabelPosition = mControlsFrame.findViewById(R.id.position);
+ mLabelPosition.setText(Util.getDurationString(0, false));
+
+ mLabelDuration = mControlsFrame.findViewById(R.id.duration);
+ mLabelDuration.setText(Util.getDurationString(0, true));
+ mLabelDuration.setOnClickListener(this);
+
+ mBtnPlayPause = mControlsFrame.findViewById(R.id.btnPlayPause);
+ mBtnPlayPause.setOnClickListener(this);
+ mBtnPlayPause.setImageDrawable(mPlayDrawable);
+
+ if (mControlsDisabled) {
+ disableControls();
+ } else {
+ enableControls();
+ }
+ setBottomProgressBarVisibility(mBottomProgressBarVisibility);
+ setControlsEnabled(false);
+ prepare();
+ }
+
+ Runnable hideControlsRunnable = new Runnable() {
@Override
- public void setCaptions(@RawRes int resId, CaptionsView.CMime cMime) {
- mSubView.setCaptionsSource(resId, cMime);
- }
-
- @Override
- public void removeCaptions(){
- setCaptions(null, null);
- }
-
- @Override
- public Toolbar getToolbar() {
- return mToolbar;
- }
-
- @Override
- public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
- LOG("Surface texture available: %dx%d", width, height);
- mInitialTextureWidth = width;
- mInitialTextureHeight = height;
- mSurfaceAvailable = true;
- mSurface = new Surface(surfaceTexture);
- if (mIsPrepared) {
- LOG("Surface texture available and media player is prepared");
- mPlayer.setSurface(mSurface);
- } else {
- prepare();
+ public void run() {
+ hideControls();
+ }
+ };
+
+ @Override
+ public void onClick(View view) {
+ if (view.getId() == R.id.btnPlayPause) {
+ if (mPlayer.isPlaying()) {
+ pause();
+ } else {
+ if (mHideControlsOnPlay && !mControlsDisabled) {
+ mHandler.postDelayed(hideControlsRunnable, 500);
}
- }
-
- @Override
- public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {
- LOG("Surface texture changed: %dx%d", width, height);
- adjustAspectRatio(width, height, mPlayer.getVideoWidth(), mPlayer.getVideoHeight());
- }
-
- @Override
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
- LOG("Surface texture destroyed");
- mSurfaceAvailable = false;
- mSurface = null;
- return false;
- }
+ start();
+ }
+ } else if (view.getId() == R.id.duration) {
+ mShowTotalDuration = !mShowTotalDuration;
+ }
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (fromUser) {
+ seekTo(progress);
+ mPositionTextView.setText(Util.getDurationString(progress, false));
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ mWasPlaying = isPlaying();
+ if (mWasPlaying) mPlayer.pause(); // keeps the time updater running, unlike pause()
+ mPositionTextView.setVisibility(VISIBLE);
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ if (mWasPlaying) mPlayer.start();
+ mPositionTextView.setVisibility(GONE);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ LOG("Attached to window");
+ if (mPlayer != null) {
+ LOG("mPlayer not null on attach");
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ LOG("Detached from window");
+ release();
+
+ mSeeker = null;
+ mLabelPosition = null;
+ mLabelDuration = null;
+ mBtnPlayPause = null;
+
+ mControlsFrame = null;
+ mClickFrame = null;
+ mProgressFrame = null;
+
+ if (mHandler != null) {
+ mHandler.removeCallbacks(mUpdateCounters);
+ mHandler = null;
+ }
+ }
+
+ // Utilities
+
+ private static void LOG(String message, Object... args) {
+ if (args != null && args.length > 0) {
+ message = String.format(message, args);
+ }
+ Log.d("BetterVideoPlayer", message);
+ }
+
+ private void adjustAspectRatio(int viewWidth, int viewHeight, int videoWidth, int videoHeight) {
+ final double aspectRatio = (double) videoHeight / videoWidth;
+ int newWidth, newHeight;
+
+ if (viewHeight > (int) (viewWidth * aspectRatio)) {
+ // limited by narrow width; restrict height
+ newWidth = viewWidth;
+ newHeight = (int) (viewWidth * aspectRatio);
+ } else {
+ // limited by short height; restrict width
+ newWidth = (int) (viewHeight / aspectRatio);
+ newHeight = viewHeight;
+ }
+
+ final int xoff = (viewWidth - newWidth) / 2;
+ final int yoff = (viewHeight - newHeight) / 2;
+
+ final Matrix txform = new Matrix();
+ mTextureView.getTransform(txform);
+ txform.setScale((float) newWidth / viewWidth, (float) newHeight / viewHeight);
+ txform.postTranslate(xoff, yoff);
+ mTextureView.setTransform(txform);
+ }
+
+ private void throwError(Exception e) {
+ if (mCallback != null)
+ mCallback.onError(this, e);
+ else throw new RuntimeException(e);
+ }
+
+ public void setLoop(boolean loop) {
+ this.mLoop = loop;
+ }
+
+ @Override
+ public void setLoadingStyle(@LoadingStyle int style) {
+ Drawable drawable;
+ switch (style) {
+ case DOUBLE_BOUNCE:
+ drawable = new DoubleBounce();
+ break;
+ case ROTATING_PLANE:
+ drawable = new RotatingPlane();
+ break;
+ case WAVE:
+ drawable = new Wave();
+ break;
+ case WANDERING_CUBES:
+ drawable = new WanderingCubes();
+ break;
+ case PULSE:
+ drawable = new Pulse();
+ break;
+ case CHASING_DOTS:
+ drawable = new ChasingDots();
+ break;
+ case THREE_BOUNCE:
+ drawable = new ThreeBounce();
+ break;
+ case CIRCLE:
+ drawable = new Circle();
+ break;
+ case CUBE_GRID:
+ drawable = new CubeGrid();
+ break;
+ case FADING_CIRCLE:
+ drawable = new FadingCircle();
+ break;
+ case ROTATING_CIRCLE:
+ drawable = new RotatingCircle();
+ break;
+ default:
+ drawable = new ThreeBounce();
+ break;
+ }
+ mProgressBar.setIndeterminateDrawable(drawable);
+ }
+
+ OnSwipeTouchListener clickFrameSwipeListener =
+ new OnSwipeTouchListener(true) {
+
+ float diffTime = -1, finalTime = -1;
+ int startVolume;
+ int maxVolume;
+ int startBrightness;
+ int maxBrightness;
@Override
- public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
- }
-
- // Media player listeners
-
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- @Override
- public void onPrepared(MediaPlayer mediaPlayer) {
- LOG("onPrepared()");
- mProgressBar.setVisibility(View.INVISIBLE);
- showControls();
- mIsPrepared = true;
-
- if (mCallback != null) {
- mCallback.onPrepared(this);
- }
-
- mLabelPosition.setText(Util.getDurationString(0, false));
- mLabelDuration.setText(Util.getDurationString(mediaPlayer.getDuration(), false));
- mSeeker.setProgress(0);
- mSeeker.setMax(mediaPlayer.getDuration());
- setControlsEnabled(true);
-
- if (mAutoPlay) {
- if (!mControlsDisabled && mHideControlsOnPlay) {
- mHandler.postDelayed(hideControlsRunnable, 500);
- }
- start();
- if (mInitialPosition > 0) {
- seekTo(mInitialPosition);
- mInitialPosition = -1;
- }
+ public void onMove(Direction dir, float diff) {
+ // If swipe is not enabled, move should not be evaluated.
+ if (mGestureType != SWIPE_GESTURE)
+ return;
+
+ if (dir == Direction.LEFT || dir == Direction.RIGHT) {
+ if (mPlayer.getDuration() <= 60) {
+ diffTime = (float) mPlayer.getDuration() * diff / ((float) mInitialTextureWidth);
} else {
- // Hack to show first frame, is there another way?
- mPlayer.start();
- mPlayer.pause();
- }
- }
-
- @Override
- public void onBufferingUpdate(MediaPlayer mediaPlayer, int percent) {
- LOG("Buffering: %d%%", percent);
- if (mCallback != null) {
- mCallback.onBuffering(percent);
+ diffTime = (float) 60000 * diff / ((float) mInitialTextureWidth);
}
- if (mSeeker != null) {
- if (percent == 100) {
- mSeeker.setSecondaryProgress(0);
- mBottomProgressBar.setSecondaryProgress(0);
- } else {
- float percentage = percent / 100f;
- int secondaryProgress = (int) (mSeeker.getMax() * percentage);
- mSeeker.setSecondaryProgress(secondaryProgress);
- mBottomProgressBar.setSecondaryProgress(secondaryProgress);
- }
+ if (dir == Direction.LEFT) {
+ diffTime *= -1;
}
- }
-
- @Override
- public void onCompletion(MediaPlayer mediaPlayer) {
- LOG("onCompletion()");
- mBtnPlayPause.setImageDrawable(mRestartDrawable);
- if (mHandler != null)
- mHandler.removeCallbacks(mUpdateCounters);
- int currentProgress = mSeeker.getMax();
- mSeeker.setProgress(currentProgress);
- mBottomProgressBar.setProgress(currentProgress);
- if(!mLoop) {
- showControls();
+ finalTime = mPlayer.getCurrentPosition() + diffTime;
+ if (finalTime < 0) {
+ finalTime = 0;
+ } else if (finalTime > mPlayer.getDuration()) {
+ finalTime = mPlayer.getDuration();
}
- else{
- start();
+ diffTime = finalTime - mPlayer.getCurrentPosition();
+
+ String progressText =
+ Util.getDurationString((long) finalTime, false) +
+ " [" + (dir == Direction.LEFT ? "-" : "+") +
+ Util.getDurationString((long) Math.abs(diffTime), false) +
+ "]";
+ mPositionTextView.setText(progressText);
+ } else {
+ finalTime = -1;
+ if (initialX >= mInitialTextureWidth / 2 || mWindow == null) {
+ float diffVolume;
+ int finalVolume;
+
+ diffVolume = (float) maxVolume * diff / ((float) mInitialTextureHeight / 2);
+ if (dir == Direction.DOWN) {
+ diffVolume = -diffVolume;
+ }
+ finalVolume = startVolume + (int) diffVolume;
+ if (finalVolume < 0)
+ finalVolume = 0;
+ else if (finalVolume > maxVolume)
+ finalVolume = maxVolume;
+
+ String progressText = String.format(
+ getResources().getString(R.string.volume), finalVolume
+ );
+ mPositionTextView.setText(progressText);
+ am.setStreamVolume(AudioManager.STREAM_MUSIC, finalVolume, 0);
+ } else if (initialX < mInitialTextureWidth / 2) {
+ float diffBrightness;
+ int finalBrightness;
+
+ diffBrightness = (float) maxBrightness * diff / ((float) mInitialTextureHeight / 2);
+ if (dir == Direction.DOWN) {
+ diffBrightness = -diffBrightness;
+ }
+ finalBrightness = startBrightness + (int) diffBrightness;
+ if (finalBrightness < 0)
+ finalBrightness = 0;
+ else if (finalBrightness > maxBrightness)
+ finalBrightness = maxBrightness;
+
+ String progressText = String.format(
+ getResources().getString(R.string.brightness), finalBrightness
+ );
+ mPositionTextView.setText(progressText);
+
+ WindowManager.LayoutParams layout = mWindow.getAttributes();
+ layout.screenBrightness = (float) finalBrightness / 100;
+ mWindow.setAttributes(layout);
+
+ PreferenceManager.getDefaultSharedPreferences(getContext())
+ .edit()
+ .putInt(BETTER_VIDEO_PLAYER_BRIGHTNESS, finalBrightness)
+ .apply();
}
- if (mCallback != null)
- mCallback.onCompletion(this);
+ }
}
@Override
- public void onVideoSizeChanged(MediaPlayer mediaPlayer, int width, int height) {
- LOG("Video size changed: %dx%d", width, height);
- adjustAspectRatio(mInitialTextureWidth, mInitialTextureHeight, width, height);
-
+ public void onClick() {
+ toggleControls();
}
@Override
- public boolean onError(MediaPlayer mediaPlayer, int what, int extra) {
- if (what == -38) {
- // Error code -38 happens on some Samsung devices
- // Just ignore it
- return false;
- }
- String errorMsg = "Preparation/playback error (" + what + "): ";
- switch (what) {
- default:
- errorMsg += "Unknown error";
- break;
- case MediaPlayer.MEDIA_ERROR_IO:
- errorMsg += "I/O error";
- break;
- case MediaPlayer.MEDIA_ERROR_MALFORMED:
- errorMsg += "Malformed";
- break;
- case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
- errorMsg += "Not valid for progressive playback";
- break;
- case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
- errorMsg += "Server died";
- break;
- case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
- errorMsg += "Timed out";
- break;
- case MediaPlayer.MEDIA_ERROR_UNSUPPORTED:
- errorMsg += "Unsupported";
- break;
- }
- throwError(new Exception(errorMsg));
- return false;
- }
-
- // View events
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- setKeepScreenOn(true);
-
- mHandler = new Handler();
- mPlayer = new MediaPlayer();
- mPlayer.setOnPreparedListener(this);
- mPlayer.setOnBufferingUpdateListener(this);
- mPlayer.setOnCompletionListener(this);
- mPlayer.setOnVideoSizeChangedListener(this);
- mPlayer.setOnErrorListener(this);
- mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
-
- am = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
-
- // Instantiate and add TextureView for rendering
- final LayoutInflater li = LayoutInflater.from(getContext());
- View mTextureFrame = li.inflate(R.layout.bvp_include_surface, this, false);
- addView(mTextureFrame);
-
- mTextureView = (TextureView) mTextureFrame.findViewById(R.id.textureview);
- mTextureView.setSurfaceTextureListener(this);
-
- viewForward = (TextView) mTextureFrame.findViewById(R.id.view_forward);
- viewBackward = (TextView) mTextureFrame.findViewById(R.id.view_backward);
-
- // Inflate and add progress
- mProgressFrame = li.inflate(R.layout.bvp_include_progress, this, false);
- mProgressBar = (SpinKitView) mProgressFrame.findViewById(R.id.spin_kit);
- mBottomProgressBar = (ProgressBar) mProgressFrame.findViewById(R.id.progressBarBottom);
-
- TypedValue typedValue = new TypedValue();
- Resources.Theme theme = getContext().getTheme();
- theme.resolveAttribute(R.attr.colorAccent, typedValue, true);
- int color = typedValue.data;
- mProgressBar.setColor(color);
- setLoadingStyle(mLoadingStyle);
-
- mPositionTextView = (TextView)mProgressFrame.findViewById(R.id.position_textview);
- mPositionTextView.setShadowLayer(3,3,3,Color.BLACK);
- addView(mProgressFrame);
-
- // Instantiate and add click frame (used to toggle controls)
- mClickFrame = new FrameLayout(getContext());
- //noinspection RedundantCast
- ((FrameLayout) mClickFrame).setForeground(
- Util.resolveDrawable(getContext(), R.attr.selectableItemBackground));
- addView(mClickFrame, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT));
-
- // Inflate controls
- mControlsFrame = li.inflate(R.layout.bvp_include_controls, this, false);
- LayoutParams mControlsLp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- mControlsLp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
- addView(mControlsFrame, mControlsLp);
-
- // Add topbar
- mToolbarFrame = li.inflate(R.layout.bvp_include_topbar, this, false);
- mToolbar = (Toolbar) mToolbarFrame.findViewById(R.id.toolbar);
- mToolbar.setTitle(mTitle);
- mToolbarFrame.setVisibility(mShowToolbar ? VISIBLE:GONE);
- addView(mToolbarFrame);
-
- // Inflate subtitles
- View mSubtitlesFrame = li.inflate(R.layout.bvp_include_subtitle, this, false);
- LayoutParams mSubtitlesLp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- mSubtitlesLp.addRule(RelativeLayout.ABOVE, R.id.bvp_include_relativelayout);
- mSubtitlesLp.alignWithParent = true;
-
- mSubView = (CaptionsView) mSubtitlesFrame.findViewById(R.id.subs_box);
- mSubView.setPlayer(mPlayer);
-
- mSubView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mSubViewTextSize);
- mSubView.setTextColor(mSubViewTextColor);
-
- addView(mSubtitlesFrame, mSubtitlesLp);
-
- // Retrieve controls
- mSeeker = (SeekBar) mControlsFrame.findViewById(R.id.seeker);
- mSeeker.setOnSeekBarChangeListener(this);
-
- mLabelPosition = (TextView) mControlsFrame.findViewById(R.id.position);
- mLabelPosition.setText(Util.getDurationString(0, false));
-
- mLabelDuration = (TextView) mControlsFrame.findViewById(R.id.duration);
- mLabelDuration.setText(Util.getDurationString(0, true));
- mLabelDuration.setOnClickListener(this);
-
- mBtnPlayPause = (ImageButton) mControlsFrame.findViewById(R.id.btnPlayPause);
- mBtnPlayPause.setOnClickListener(this);
- mBtnPlayPause.setImageDrawable(mPlayDrawable);
-
- if (mControlsDisabled) {
- disableControls();
+ public void onDoubleTap(MotionEvent e) {
+ if (mGestureType == DOUBLETAP_GESTURE) {
+ int seekSec = mDoubleTapSeekDuration / 1000;
+ viewForward.setText(seekSec + " seconds");
+ viewBackward.setText(seekSec + " seconds");
+ if (e.getX() > mInitialTextureWidth / 2) {
+ animateViewFade(viewForward, 1);
+ seekTo(getCurrentPosition() + mDoubleTapSeekDuration);
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ animateViewFade(viewForward, 0);
+ }
+ }, 500);
} else {
- enableControls();
- }
- setBottomProgressBarVisibility(mBottomProgressBarVisibility);
- setControlsEnabled(false);
- prepare();
- }
-
- Runnable hideControlsRunnable = new Runnable() {
- @Override
- public void run() {
- hideControls();
- }
- };
-
- @Override
- public void onClick(View view) {
- if (view.getId() == R.id.btnPlayPause) {
- if (mPlayer.isPlaying()) {
- pause();
- } else {
- if (mHideControlsOnPlay && !mControlsDisabled) {
- mHandler.postDelayed(hideControlsRunnable, 500);
- }
- start();
+ animateViewFade(viewBackward, 1);
+ seekTo(getCurrentPosition() - mDoubleTapSeekDuration);
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ animateViewFade(viewBackward, 0);
}
- } else if(view.getId() == R.id.duration){
- mShowTotalDuration = !mShowTotalDuration;
+ }, 500);
}
+ }
}
@Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- if (fromUser) {
- seekTo(progress);
- mPositionTextView.setText(Util.getDurationString(progress, false));
- }
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- mWasPlaying = isPlaying();
- if (mWasPlaying) mPlayer.pause(); // keeps the time updater running, unlike pause()
- mPositionTextView.setVisibility(VISIBLE);
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
+ public void onAfterMove() {
+ if (finalTime >= 0 && mGestureType == SWIPE_GESTURE) {
+ seekTo((int) finalTime);
if (mWasPlaying) mPlayer.start();
- mPositionTextView.setVisibility(GONE);
+ }
+ mPositionTextView.setVisibility(View.GONE);
}
@Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- LOG("Attached to window");
- if(mPlayer != null){
- LOG("mPlayer not null on attach");
- }
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- LOG("Detached from window");
- release();
-
- mSeeker = null;
- mLabelPosition = null;
- mLabelDuration = null;
- mBtnPlayPause = null;
-
- mControlsFrame = null;
- mClickFrame = null;
- mProgressFrame = null;
-
- if (mHandler != null) {
- mHandler.removeCallbacks(mUpdateCounters);
- mHandler = null;
- }
- }
-
- // Utilities
-
- private static void LOG(String message, Object... args) {
- if (args != null && args.length > 0) {
- message = String.format(message, args);
- }
- Log.d("BetterVideoPlayer", message);
- }
-
- private void adjustAspectRatio(int viewWidth, int viewHeight, int videoWidth, int videoHeight) {
- final double aspectRatio = (double) videoHeight / videoWidth;
- int newWidth, newHeight;
-
- if (viewHeight > (int) (viewWidth * aspectRatio)) {
- // limited by narrow width; restrict height
- newWidth = viewWidth;
- newHeight = (int) (viewWidth * aspectRatio);
- } else {
- // limited by short height; restrict width
- newWidth = (int) (viewHeight / aspectRatio);
- newHeight = viewHeight;
+ public void onBeforeMove(Direction dir) {
+ if (mGestureType != SWIPE_GESTURE)
+ return;
+ if (dir == Direction.LEFT || dir == Direction.RIGHT) {
+ mWasPlaying = isPlaying();
+ mPlayer.pause();
+ mPositionTextView.setVisibility(View.VISIBLE);
+ } else {
+ maxBrightness = 100;
+ if (mWindow != null) {
+ startBrightness = (int) (mWindow.getAttributes().screenBrightness * 100);
}
-
- final int xoff = (viewWidth - newWidth) / 2;
- final int yoff = (viewHeight - newHeight) / 2;
-
- final Matrix txform = new Matrix();
- mTextureView.getTransform(txform);
- txform.setScale((float) newWidth / viewWidth, (float) newHeight / viewHeight);
- txform.postTranslate(xoff, yoff);
- mTextureView.setTransform(txform);
- }
-
- private void throwError(Exception e) {
- if (mCallback != null)
- mCallback.onError(this, e);
- else throw new RuntimeException(e);
- }
-
- public void setLoop(boolean loop){
- this.mLoop = loop;
+ maxVolume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+ startVolume = am.getStreamVolume(AudioManager.STREAM_MUSIC);
+ mPositionTextView.setVisibility(View.VISIBLE);
+ }
}
+ };
+ // Runnable used to run code on an interval to update counters and seeker
+ private final Runnable mUpdateCounters = new Runnable() {
@Override
- public void setLoadingStyle(@LoadingStyle int style) {
- Drawable drawable;
- switch (style){
- case DOUBLE_BOUNCE:
- drawable = new DoubleBounce();
- break;
- case ROTATING_PLANE:
- drawable = new RotatingPlane();
- break;
- case WAVE:
- drawable = new Wave();
- break;
- case WANDERING_CUBES:
- drawable = new WanderingCubes();
- break;
- case PULSE:
- drawable = new Pulse();
- break;
- case CHASING_DOTS:
- drawable = new ChasingDots();
- break;
- case THREE_BOUNCE:
- drawable = new ThreeBounce();
- break;
- case CIRCLE:
- drawable = new Circle();
- break;
- case CUBE_GRID:
- drawable = new CubeGrid();
- break;
- case FADING_CIRCLE:
- drawable = new FadingCircle();
- break;
- case ROTATING_CIRCLE :
- drawable = new RotatingCircle();
- break;
- default:
- drawable = new ThreeBounce();
- break;
- }
- mProgressBar.setIndeterminateDrawable(drawable);
- }
-
- OnSwipeTouchListener clickFrameSwipeListener = new OnSwipeTouchListener(){
-
- float diffTime = -1, finalTime = -1;
- int startVolume;
- int maxVolume;
- int startBrightness;
- int maxBrightness;
- @Override
- public void onMove(Direction dir, float diff) {
- // If swipe is not enabled, move should not be evaluated.
- if(!mSwipeEnabled)
- return;
-
- if(dir == Direction.LEFT || dir == Direction.RIGHT) {
- if(mPlayer.getDuration() <= 60){
- diffTime = (float) mPlayer.getDuration() * diff / ((float) mInitialTextureWidth);
- }
- else{
- diffTime = (float) 60000 * diff / ((float) mInitialTextureWidth);
- }
- if (dir == Direction.LEFT) {
- diffTime *= -1;
- }
- finalTime = mPlayer.getCurrentPosition() + diffTime;
- if (finalTime < 0) {
- finalTime = 0;
- }
- else if (finalTime > mPlayer.getDuration()) {
- finalTime = mPlayer.getDuration();
- }
- diffTime = finalTime - mPlayer.getCurrentPosition();
-
- String progressText =
- Util.getDurationString((long) finalTime, false) +
- " [" + (dir == Direction.LEFT ? "-":"+") +
- Util.getDurationString((long) Math.abs(diffTime), false) +
- "]";
- mPositionTextView.setText(progressText);
- }
- else{
- finalTime = -1;
- if(initialX >= mInitialTextureWidth/2 || mWindow==null) {
- float diffVolume;
- int finalVolume;
-
- diffVolume = (float) maxVolume * diff / ((float) mInitialTextureHeight / 2);
- if (dir == Direction.DOWN) {
- diffVolume = -diffVolume;
- }
- finalVolume = startVolume + (int) diffVolume;
- if (finalVolume < 0)
- finalVolume = 0;
- else if (finalVolume > maxVolume)
- finalVolume = maxVolume;
-
- String progressText = String.format(
- getResources().getString(R.string.volume), finalVolume
- );
- mPositionTextView.setText(progressText);
- am.setStreamVolume(AudioManager.STREAM_MUSIC, finalVolume, 0);
- }
- else if(initialX < mInitialTextureWidth/2){
- float diffBrightness;
- int finalBrightness;
-
- diffBrightness = (float) maxBrightness * diff / ((float) mInitialTextureHeight / 2);
- if (dir == Direction.DOWN) {
- diffBrightness = -diffBrightness;
- }
- finalBrightness = startBrightness + (int) diffBrightness;
- if (finalBrightness < 0)
- finalBrightness = 0;
- else if (finalBrightness > maxBrightness)
- finalBrightness = maxBrightness;
-
- String progressText = String.format(
- getResources().getString(R.string.brightness), finalBrightness
- );
- mPositionTextView.setText(progressText);
-
- WindowManager.LayoutParams layout = mWindow.getAttributes();
- layout.screenBrightness = (float)finalBrightness / 100;
- mWindow.setAttributes(layout);
-
- PreferenceManager.getDefaultSharedPreferences(getContext())
- .edit()
- .putInt(BETTER_VIDEO_PLAYER_BRIGHTNESS, finalBrightness)
- .apply();
- }
- }
- }
-
- @Override
- public void onClick() {
- toggleControls();
- }
-
- @Override
- public void onAfterMove() {
- if(finalTime >= 0 && mSwipeEnabled) {
- seekTo((int) finalTime);
- if (mWasPlaying) mPlayer.start();
- }
- mPositionTextView.setVisibility(View.GONE);
- }
-
- @Override
- public void onBeforeMove(Direction dir) {
- if(!mSwipeEnabled)
- return;
- if(dir == Direction.LEFT || dir == Direction.RIGHT) {
- mWasPlaying = isPlaying();
- mPlayer.pause();
- mPositionTextView.setVisibility(View.VISIBLE);
- }
- else{
- maxBrightness = 100;
- if(mWindow!=null) {
- startBrightness = (int) (mWindow.getAttributes().screenBrightness * 100);
- }
- maxVolume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
- startVolume = am.getStreamVolume(AudioManager.STREAM_MUSIC);
- mPositionTextView.setVisibility(View.VISIBLE);
- }
- }
- };
-
- // Runnable used to run code on an interval to update counters and seeker
- private final Runnable mUpdateCounters = new Runnable() {
- @Override
- public void run() {
- if (mHandler == null || !mIsPrepared || mSeeker == null || mPlayer == null)
- return;
- long pos = mPlayer.getCurrentPosition();
- final long dur = mPlayer.getDuration();
- if (pos > dur) pos = dur;
- mLabelPosition.setText(Util.getDurationString(pos, false));
- if(mShowTotalDuration) {
- mLabelDuration.setText(Util.getDurationString(dur, false));
- } else {
- mLabelDuration.setText(Util.getDurationString(dur - pos, true));
- }
- int position = (int) pos;
- int duration = (int) dur;
-
- mSeeker.setProgress(position);
- mSeeker.setMax(duration);
-
- mBottomProgressBar.setProgress(position);
- mBottomProgressBar.setMax(duration);
-
- if (mProgressCallback != null)
- mProgressCallback.onVideoProgressUpdate(position, duration);
- if (mHandler != null)
- mHandler.postDelayed(this, UPDATE_INTERVAL);
- }
- };
+ public void run() {
+ if (mHandler == null || !mIsPrepared || mSeeker == null || mPlayer == null)
+ return;
+ long pos = mPlayer.getCurrentPosition();
+ final long dur = mPlayer.getDuration();
+ if (pos > dur) pos = dur;
+ mLabelPosition.setText(Util.getDurationString(pos, false));
+ if (mShowTotalDuration) {
+ mLabelDuration.setText(Util.getDurationString(dur, false));
+ } else {
+ mLabelDuration.setText(Util.getDurationString(dur - pos, true));
+ }
+ int position = (int) pos;
+ int duration = (int) dur;
+
+ mSeeker.setProgress(position);
+ mSeeker.setMax(duration);
+
+ mBottomProgressBar.setProgress(position);
+ mBottomProgressBar.setMax(duration);
+
+ if (mProgressCallback != null)
+ mProgressCallback.onVideoProgressUpdate(position, duration);
+ if (mHandler != null)
+ mHandler.postDelayed(this, UPDATE_INTERVAL);
+ }
+ };
}
diff --git a/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/IUserMethods.java b/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/IUserMethods.java
index d74d6e6..3a14ecb 100644
--- a/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/IUserMethods.java
+++ b/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/IUserMethods.java
@@ -44,7 +44,7 @@ interface IUserMethods {
* @param type Which button is being targeted.
* @param drawable Drawable object to use for styling.
*/
- void setButtonDrawable(@BetterVideoPlayer.LoadingStyle int type, @NonNull Drawable drawable);
+ void setButtonDrawable(@BetterVideoPlayer.ButtonType int type, @NonNull Drawable drawable);
void setHideControlsOnPlay(boolean hide);
@@ -68,6 +68,10 @@ void setVolume(@FloatRange(from = 0f, to = 1f) float leftVolume,
void setBottomProgressBarVisibility(boolean isShowing);
+ /**
+ * Enable swipe gestures which are volume control for up and down at right side of the player.
+ * Horizontal swipes changes progress of the player.
+ */
void enableSwipeGestures();
/**
@@ -77,7 +81,14 @@ void setVolume(@FloatRange(from = 0f, to = 1f) float leftVolume,
*/
void enableSwipeGestures(@NonNull Window window);
- void disableSwipeGestures();
+ /**
+ * Double tap gestures are Youtube like. Seek forward or backward
+ * after double tapping at one side.
+ * @param seek
+ */
+ void enableDoubleTapGestures(int seek);
+
+ void disableGestures();
void showToolbar();
diff --git a/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/OnSwipeTouchListener.java b/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/OnSwipeTouchListener.java
index aa30c25..c916f6a 100644
--- a/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/OnSwipeTouchListener.java
+++ b/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/OnSwipeTouchListener.java
@@ -1,5 +1,6 @@
package com.halilibo.bettervideoplayer;
+import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
@@ -9,12 +10,26 @@
*/
abstract class OnSwipeTouchListener implements OnTouchListener {
+ private final boolean doubleTapEnabled;
+ private final Handler mHandler;
+ private Runnable futureClickRunnable = new Runnable() {
+ @Override
+ public void run() {
+ onClick();
+ }
+ };
+
enum Direction{
LEFT, RIGHT, UP, DOWN;
}
+ public OnSwipeTouchListener(boolean doubleTapEnabled){
+ this.doubleTapEnabled = doubleTapEnabled;
+ this.mHandler = new Handler();
+ }
private final static String TAG = "ClickFrame";
private final static int SWIPE_THRESHOLD = 100;
+ private static final long DOUBLE_TAP_THRESHOLD = 150;
// 0: uninitialized
// 1: horizontal
@@ -25,6 +40,7 @@ enum Direction{
protected float initialY;
private float decidedX;
private float decidedY;
+ private long lastClick = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getActionMasked();
@@ -91,13 +107,24 @@ else if(initialGesture == 2){
break;
case MotionEvent.ACTION_UP:
- deltaX = event.getX() - initialX;
- deltaY = event.getY() - initialY;
-
- if(initialGesture == 0){
- onClick();
- return true;
+ if(initialGesture == 0){ // Finger did not move enough to trigger a swipe
+ if(doubleTapEnabled &&
+ System.currentTimeMillis() - lastClick <= DOUBLE_TAP_THRESHOLD &&
+ lastClick != 0) {
+ mHandler.removeCallbacks(futureClickRunnable);
+ onDoubleTap(event);
+ return true;
+ }
+ else {
+ lastClick = System.currentTimeMillis();
+ if(doubleTapEnabled)
+ mHandler.postDelayed(futureClickRunnable, DOUBLE_TAP_THRESHOLD);
+ else
+ mHandler.post(futureClickRunnable);
+ return true;
+ }
}
+
onAfterMove();
initialGesture = 0;
return true;
@@ -116,6 +143,8 @@ else if(initialGesture == 2){
public abstract void onClick();
+ public abstract void onDoubleTap(MotionEvent event);
+
public abstract void onAfterMove();
public abstract void onBeforeMove(Direction dir);
diff --git a/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/utility/Util.java b/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/utility/Util.java
index 0565748..5b19e9d 100644
--- a/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/utility/Util.java
+++ b/bettervideoplayer/src/main/java/com/halilibo/bettervideoplayer/utility/Util.java
@@ -14,10 +14,6 @@
*/
public class Util {
- public static int getScreenWidth(Context context) {
- return context.getResources().getDisplayMetrics().widthPixels;
- }
-
public static String getDurationString(long durationMs, boolean negativePrefix) {
long hours = TimeUnit.MILLISECONDS.toHours(durationMs);
long minutes = TimeUnit.MILLISECONDS.toMinutes(durationMs);
@@ -77,4 +73,8 @@ private static Drawable resolveDrawable(Context context, @AttrRes int attr, @Sup
a.recycle();
}
}
+
+ public static int getScreenWidth(Context context) {
+ return context.getResources().getDisplayMetrics().widthPixels;
+ }
}
\ No newline at end of file
diff --git a/bettervideoplayer/src/main/res/values/attrs.xml b/bettervideoplayer/src/main/res/values/attrs.xml
index d511679..bb9cbfa 100644
--- a/bettervideoplayer/src/main/res/values/attrs.xml
+++ b/bettervideoplayer/src/main/res/values/attrs.xml
@@ -34,7 +34,11 @@
Kind of like the Youtube player.
-->
-
+
+
+
+
+
diff --git a/build.gradle b/build.gradle
index a96ae6e..c1b6f00 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,9 +3,13 @@
buildscript {
repositories {
jcenter()
+ maven {
+ url 'https://maven.google.com/'
+ name 'Google'
+ }
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.2'
+ classpath 'com.android.tools.build:gradle:3.1.2'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
// NOTE: Do not place your application dependencies here; they belong
@@ -17,6 +21,10 @@ allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
+ maven {
+ url 'https://maven.google.com/'
+ name 'Google'
+ }
}
}
@@ -24,11 +32,11 @@ task clean(type: Delete) {
delete rootProject.buildDir
}
-project.ext.compileSdkVersion = 25
-project.ext.buildToolsVersion = "25.0.2"
+project.ext.compileSdkVersion = 27
+project.ext.buildToolsVersion = "27.0.3"
project.ext.minSdkVersion = 15
-project.ext.targetSdkVersion = 25
-project.ext.googleAPIsVersion = "25.3.1"
+project.ext.targetSdkVersion = 27
+project.ext.googleAPIsVersion = "27.1.1"
project.ext.publishVersionCode = 1
project.ext.publishVersionName = "0.1.0"
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 38f79bf..47fda96 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon May 01 16:23:10 BST 2017
+#Wed May 02 02:09:11 EET 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip