Marked many (too many) variables as final

This commit is contained in:
Avently 2020-07-12 03:59:47 +03:00
parent a7fbe05a73
commit b2164ce5fc
13 changed files with 295 additions and 273 deletions

View file

@ -23,13 +23,13 @@ public final class FlingBehavior extends AppBarLayout.Behavior {
} }
private boolean allowScroll = true; private boolean allowScroll = true;
private Rect globalRect = new Rect(); private final Rect globalRect = new Rect();
@Override @Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) { public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {
ViewGroup playQueue = child.findViewById(R.id.playQueuePanel); final ViewGroup playQueue = child.findViewById(R.id.playQueuePanel);
if (playQueue != null) { if (playQueue != null) {
boolean visible = playQueue.getGlobalVisibleRect(globalRect); final boolean visible = playQueue.getGlobalVisibleRect(globalRect);
if (visible && globalRect.contains((int) ev.getRawX(), (int) ev.getRawY())) { if (visible && globalRect.contains((int) ev.getRawX(), (int) ev.getRawY())) {
allowScroll = false; allowScroll = false;
return false; return false;

View file

@ -45,7 +45,6 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.navigation.NavigationView; import com.google.android.material.navigation.NavigationView;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance; import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance;
@ -453,21 +452,21 @@ public class MainActivity extends AppCompatActivity {
public void onBackPressed() { public void onBackPressed() {
if (DEBUG) Log.d(TAG, "onBackPressed() called"); if (DEBUG) Log.d(TAG, "onBackPressed() called");
FrameLayout bottomSheetLayout = findViewById(R.id.fragment_player_holder); final FrameLayout bottomSheetLayout = findViewById(R.id.fragment_player_holder);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetLayout); final BottomSheetBehavior<FrameLayout> bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetLayout);
final int sheetState = bottomSheetBehavior.getState(); final int sheetState = bottomSheetBehavior.getState();
// In case bottomSheet is not visible on the screen or collapsed we can assume that the user interacts with a fragment // In case bottomSheet is not visible on the screen or collapsed we can assume that the user interacts with a fragment
// inside fragment_holder so all back presses should be handled by it // inside fragment_holder so all back presses should be handled by it
if (sheetState == BottomSheetBehavior.STATE_HIDDEN || sheetState == BottomSheetBehavior.STATE_COLLAPSED) { if (sheetState == BottomSheetBehavior.STATE_HIDDEN || sheetState == BottomSheetBehavior.STATE_COLLAPSED) {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder); final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder);
// If current fragment implements BackPressable (i.e. can/wanna handle back press) delegate the back press to it // If current fragment implements BackPressable (i.e. can/wanna handle back press) delegate the back press to it
if (fragment instanceof BackPressable) { if (fragment instanceof BackPressable) {
if (((BackPressable) fragment).onBackPressed()) return; if (((BackPressable) fragment).onBackPressed()) return;
} }
} else { } else {
Fragment fragmentPlayer = getSupportFragmentManager().findFragmentById(R.id.fragment_player_holder); final Fragment fragmentPlayer = getSupportFragmentManager().findFragmentById(R.id.fragment_player_holder);
// If current fragment implements BackPressable (i.e. can/wanna handle back press) delegate the back press to it // If current fragment implements BackPressable (i.e. can/wanna handle back press) delegate the back press to it
if (fragmentPlayer instanceof BackPressable) { if (fragmentPlayer instanceof BackPressable) {
if (!((BackPressable) fragmentPlayer).onBackPressed()) if (!((BackPressable) fragmentPlayer).onBackPressed())

View file

@ -10,7 +10,7 @@ class StackItem implements Serializable {
private String url; private String url;
private PlayQueue playQueue; private PlayQueue playQueue;
StackItem(int serviceId, String url, String title, PlayQueue playQueue) { StackItem(final int serviceId, final String url, final String title, final PlayQueue playQueue) {
this.serviceId = serviceId; this.serviceId = serviceId;
this.url = url; this.url = url;
this.title = title; this.title = title;

View file

@ -73,10 +73,7 @@ import org.schabi.newpipe.util.*;
import org.schabi.newpipe.views.AnimatedProgressBar; import org.schabi.newpipe.views.AnimatedProgressBar;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collection; import java.util.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import icepick.State; import icepick.State;
@ -143,7 +140,7 @@ public class VideoDetailFragment
private List<VideoStream> sortedVideoStreams; private List<VideoStream> sortedVideoStreams;
private int selectedVideoStreamIndex = -1; private int selectedVideoStreamIndex = -1;
private BottomSheetBehavior bottomSheetBehavior; private BottomSheetBehavior<FrameLayout> bottomSheetBehavior;
private BroadcastReceiver broadcastReceiver; private BroadcastReceiver broadcastReceiver;
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
@ -194,7 +191,7 @@ public class VideoDetailFragment
private ImageButton overlayCloseButton; private ImageButton overlayCloseButton;
private AppBarLayout appBarLayout; private AppBarLayout appBarLayout;
private ViewPager viewPager; private ViewPager viewPager;
private TabAdaptor pageAdapter; private TabAdaptor pageAdapter;
private TabLayout tabLayout; private TabLayout tabLayout;
private FrameLayout relatedStreamsLayout; private FrameLayout relatedStreamsLayout;
@ -210,19 +207,19 @@ public class VideoDetailFragment
// Service management // Service management
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
private ServiceConnection getServiceConnection(boolean playAfterConnect) { private ServiceConnection getServiceConnection(final boolean playAfterConnect) {
return new ServiceConnection() { return new ServiceConnection() {
@Override @Override
public void onServiceDisconnected(ComponentName name) { public void onServiceDisconnected(final ComponentName name) {
if (DEBUG) Log.d(TAG, "Player service is disconnected"); if (DEBUG) Log.d(TAG, "Player service is disconnected");
unbind(); unbind();
} }
@Override @Override
public void onServiceConnected(ComponentName compName, IBinder service) { public void onServiceConnected(final ComponentName compName, final IBinder service) {
if (DEBUG) Log.d(TAG, "Player service is connected"); if (DEBUG) Log.d(TAG, "Player service is connected");
MainPlayer.LocalBinder localBinder = (MainPlayer.LocalBinder) service; final MainPlayer.LocalBinder localBinder = (MainPlayer.LocalBinder) service;
playerService = localBinder.getService(); playerService = localBinder.getService();
player = localBinder.getPlayer(); player = localBinder.getPlayer();
@ -255,18 +252,16 @@ public class VideoDetailFragment
private void bind() { private void bind() {
if (DEBUG) Log.d(TAG, "bind() called"); if (DEBUG) Log.d(TAG, "bind() called");
Intent serviceIntent = new Intent(getContext(), MainPlayer.class); final Intent serviceIntent = new Intent(getContext(), MainPlayer.class);
final boolean success = getContext().bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE); bound = requireContext().bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
if (!bound) requireContext().unbindService(serviceConnection);
if (!success) getContext().unbindService(serviceConnection);
bound = success;
} }
private void unbind() { private void unbind() {
if (DEBUG) Log.d(TAG, "unbind() called"); if (DEBUG) Log.d(TAG, "unbind() called");
if (bound) { if (bound) {
getContext().unbindService(serviceConnection); requireContext().unbindService(serviceConnection);
bound = false; bound = false;
stopPlayerListener(); stopPlayerListener();
playerService = null; playerService = null;
@ -286,20 +281,20 @@ public class VideoDetailFragment
// startService() can be called concurrently and it will give a random crashes and NullPointerExceptions // startService() can be called concurrently and it will give a random crashes and NullPointerExceptions
// inside the service because the service will be bound twice. Prevent it with unbinding first // inside the service because the service will be bound twice. Prevent it with unbinding first
unbind(); unbind();
getContext().startService(new Intent(getContext(), MainPlayer.class)); requireContext().startService(new Intent(getContext(), MainPlayer.class));
serviceConnection = getServiceConnection(playAfterConnect); serviceConnection = getServiceConnection(playAfterConnect);
bind(); bind();
} }
private void stopService() { private void stopService() {
unbind(); unbind();
getContext().stopService(new Intent(getContext(), MainPlayer.class)); requireContext().stopService(new Intent(getContext(), MainPlayer.class));
} }
/*////////////////////////////////////////////////////////////////////////*/ /*////////////////////////////////////////////////////////////////////////*/
public static VideoDetailFragment getInstance(int serviceId, String videoUrl, String name, PlayQueue playQueue) { public static VideoDetailFragment getInstance(final int serviceId, final String videoUrl, final String name, final PlayQueue playQueue) {
VideoDetailFragment instance = new VideoDetailFragment(); VideoDetailFragment instance = new VideoDetailFragment();
instance.setInitialData(serviceId, videoUrl, name, playQueue); instance.setInitialData(serviceId, videoUrl, name, playQueue);
return instance; return instance;
@ -330,8 +325,8 @@ public class VideoDetailFragment
settingsContentObserver = new ContentObserver(new Handler()) { settingsContentObserver = new ContentObserver(new Handler()) {
@Override @Override
public void onChange(boolean selfChange) { public void onChange(final boolean selfChange) {
if(activity != null && !PlayerHelper.globalScreenOrientationLocked(activity)) if (activity != null && !PlayerHelper.globalScreenOrientationLocked(activity))
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
} }
}; };
@ -402,10 +397,9 @@ public class VideoDetailFragment
if (positionSubscriber != null) positionSubscriber.dispose(); if (positionSubscriber != null) positionSubscriber.dispose();
if (currentWorker != null) currentWorker.dispose(); if (currentWorker != null) currentWorker.dispose();
if (disposables != null) disposables.clear(); disposables.clear();
positionSubscriber = null; positionSubscriber = null;
currentWorker = null; currentWorker = null;
disposables = null;
bottomSheetBehavior.setBottomSheetCallback(null); bottomSheetBehavior.setBottomSheetCallback(null);
} }
@ -521,10 +515,9 @@ public class VideoDetailFragment
case R.id.overlay_play_pause_button: case R.id.overlay_play_pause_button:
if (playerIsNotStopped()) { if (playerIsNotStopped()) {
player.onPlayPause(); player.onPlayPause();
player.hideControls(0,0); player.hideControls(0, 0);
showSystemUi(); showSystemUi();
} } else openVideoPlayer();
else openVideoPlayer();
setOverlayPlayPauseImage(); setOverlayPlayPauseImage();
break; break;
@ -754,12 +747,13 @@ public class VideoDetailFragment
// Remove top // Remove top
stack.pop(); stack.pop();
// Get stack item from the new top // Get stack item from the new top
assert stack.peek() != null;
setupFromHistoryItem(stack.peek()); setupFromHistoryItem(stack.peek());
return true; return true;
} }
private void setupFromHistoryItem(StackItem item) { private void setupFromHistoryItem(final StackItem item) {
setAutoplay(false); setAutoplay(false);
hideMainPlayer(); hideMainPlayer();
@ -773,9 +767,9 @@ public class VideoDetailFragment
// Maybe an item was deleted in background activity // Maybe an item was deleted in background activity
if (item.getPlayQueue().getItem() == null) return; if (item.getPlayQueue().getItem() == null) return;
PlayQueueItem playQueueItem = item.getPlayQueue().getItem(); final PlayQueueItem playQueueItem = item.getPlayQueue().getItem();
// Update title, url, uploader from the last item in the stack (it's current now) // Update title, url, uploader from the last item in the stack (it's current now)
boolean isPlayerStopped = player == null || player.isPlayerStopped(); final boolean isPlayerStopped = player == null || player.isPlayerStopped();
if (playQueueItem != null && isPlayerStopped) if (playQueueItem != null && isPlayerStopped)
updateOverlayData(playQueueItem.getTitle(), playQueueItem.getUploader(), playQueueItem.getThumbnailUrl()); updateOverlayData(playQueueItem.getTitle(), playQueueItem.getUploader(), playQueueItem.getThumbnailUrl());
} }
@ -792,7 +786,7 @@ public class VideoDetailFragment
else prepareAndHandleInfo(currentInfo, false); else prepareAndHandleInfo(currentInfo, false);
} }
public void selectAndLoadVideo(int serviceId, String videoUrl, String name, PlayQueue playQueue) { public void selectAndLoadVideo(final int serviceId, final String videoUrl, final String name, final PlayQueue playQueue) {
// Situation when user switches from players to main player. All needed data is here, we can start watching // Situation when user switches from players to main player. All needed data is here, we can start watching
if (this.playQueue != null && this.playQueue.equals(playQueue)) { if (this.playQueue != null && this.playQueue.equals(playQueue)) {
openVideoPlayer(); openVideoPlayer();
@ -802,7 +796,7 @@ public class VideoDetailFragment
startLoading(false, true); startLoading(false, true);
} }
public void prepareAndHandleInfo(final StreamInfo info, boolean scrollToTop) { public void prepareAndHandleInfo(final StreamInfo info, final boolean scrollToTop) {
if (DEBUG) Log.d(TAG, "prepareAndHandleInfo() called with: info = [" if (DEBUG) Log.d(TAG, "prepareAndHandleInfo() called with: info = ["
+ info + "], scrollToTop = [" + scrollToTop + "]"); + info + "], scrollToTop = [" + scrollToTop + "]");
@ -821,7 +815,7 @@ public class VideoDetailFragment
} }
@Override @Override
public void startLoading(boolean forceLoad) { public void startLoading(final boolean forceLoad) {
super.startLoading(forceLoad); super.startLoading(forceLoad);
initTabs(); initTabs();
@ -831,7 +825,7 @@ public class VideoDetailFragment
runWorker(forceLoad, stack.isEmpty()); runWorker(forceLoad, stack.isEmpty());
} }
private void startLoading(boolean forceLoad, boolean addToBackStack) { private void startLoading(final boolean forceLoad, final boolean addToBackStack) {
super.startLoading(false); super.startLoading(false);
initTabs(); initTabs();
@ -841,7 +835,7 @@ public class VideoDetailFragment
runWorker(forceLoad, addToBackStack); runWorker(forceLoad, addToBackStack);
} }
private void runWorker(boolean forceLoad, boolean addToBackStack) { private void runWorker(final boolean forceLoad, final boolean addToBackStack) {
currentWorker = ExtractorHelper.getStreamInfo(serviceId, url, forceLoad) currentWorker = ExtractorHelper.getStreamInfo(serviceId, url, forceLoad)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -867,26 +861,26 @@ public class VideoDetailFragment
} }
pageAdapter.clearAllItems(); pageAdapter.clearAllItems();
if(shouldShowComments()){ if (shouldShowComments()) {
pageAdapter.addFragment(CommentsFragment.getInstance(serviceId, url, name), COMMENTS_TAB_TAG); pageAdapter.addFragment(CommentsFragment.getInstance(serviceId, url, name), COMMENTS_TAB_TAG);
} }
if(showRelatedStreams && null == relatedStreamsLayout){ if (showRelatedStreams && null == relatedStreamsLayout) {
//temp empty fragment. will be updated in handleResult //temp empty fragment. will be updated in handleResult
pageAdapter.addFragment(new Fragment(), RELATED_TAB_TAG); pageAdapter.addFragment(new Fragment(), RELATED_TAB_TAG);
} }
if(pageAdapter.getCount() == 0){ if (pageAdapter.getCount() == 0) {
pageAdapter.addFragment(new EmptyFragment(), EMPTY_TAB_TAG); pageAdapter.addFragment(new EmptyFragment(), EMPTY_TAB_TAG);
} }
pageAdapter.notifyDataSetUpdate(); pageAdapter.notifyDataSetUpdate();
if(pageAdapter.getCount() < 2){ if (pageAdapter.getCount() < 2) {
tabLayout.setVisibility(View.GONE); tabLayout.setVisibility(View.GONE);
}else{ } else {
int position = pageAdapter.getItemPositionByTitle(selectedTabTag); final int position = pageAdapter.getItemPositionByTitle(selectedTabTag);
if(position != -1) viewPager.setCurrentItem(position); if (position != -1) viewPager.setCurrentItem(position);
tabLayout.setVisibility(View.VISIBLE); tabLayout.setVisibility(View.VISIBLE);
} }
} }
@ -911,10 +905,10 @@ public class VideoDetailFragment
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
private void openBackgroundPlayer(final boolean append) { private void openBackgroundPlayer(final boolean append) {
AudioStream audioStream = currentInfo.getAudioStreams() final AudioStream audioStream = currentInfo.getAudioStreams()
.get(ListHelper.getDefaultAudioFormat(activity, currentInfo.getAudioStreams())); .get(ListHelper.getDefaultAudioFormat(activity, currentInfo.getAudioStreams()));
boolean useExternalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity) final boolean useExternalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity)
.getBoolean(activity.getString(R.string.use_external_audio_player_key), false); .getBoolean(activity.getString(R.string.use_external_audio_player_key), false);
// If a user watched video inside fullscreen mode and than chose another player return to non-fullscreen mode // If a user watched video inside fullscreen mode and than chose another player return to non-fullscreen mode
@ -939,7 +933,7 @@ public class VideoDetailFragment
// If a user watched video inside fullscreen mode and than chose another player return to non-fullscreen mode // If a user watched video inside fullscreen mode and than chose another player return to non-fullscreen mode
if (player != null && player.isFullscreen()) player.toggleFullscreen(); if (player != null && player.isFullscreen()) player.toggleFullscreen();
PlayQueue queue = setupPlayQueueForIntent(append); final PlayQueue queue = setupPlayQueueForIntent(append);
if (append) { if (append) {
NavigationHelper.enqueueOnPopupPlayer(activity, queue, false); NavigationHelper.enqueueOnPopupPlayer(activity, queue, false);
} else { } else {
@ -950,7 +944,8 @@ public class VideoDetailFragment
private void openVideoPlayer() { private void openVideoPlayer() {
if (PreferenceManager.getDefaultSharedPreferences(activity) if (PreferenceManager.getDefaultSharedPreferences(activity)
.getBoolean(this.getString(R.string.use_external_video_player_key), false)) { .getBoolean(this.getString(R.string.use_external_video_player_key), false)) {
VideoStream selectedVideoStream = getSelectedVideoStream(); final VideoStream selectedVideoStream = getSelectedVideoStream();
if (selectedVideoStream == null) return;
startOnExternalPlayer(activity, currentInfo, selectedVideoStream); startOnExternalPlayer(activity, currentInfo, selectedVideoStream);
} else { } else {
replaceQueueIfUserConfirms(this::openMainPlayer); replaceQueueIfUserConfirms(this::openMainPlayer);
@ -961,7 +956,7 @@ public class VideoDetailFragment
// See UI changes while remote playQueue changes // See UI changes while remote playQueue changes
if (!bound) startService(false); if (!bound) startService(false);
PlayQueue queue = setupPlayQueueForIntent(append); final PlayQueue queue = setupPlayQueueForIntent(append);
if (append) { if (append) {
NavigationHelper.enqueueOnBackgroundPlayer(activity, queue, false); NavigationHelper.enqueueOnBackgroundPlayer(activity, queue, false);
} else { } else {
@ -971,18 +966,18 @@ public class VideoDetailFragment
private void openMainPlayer() { private void openMainPlayer() {
if (playerService == null) { if (playerService == null) {
startService(true); startService(true);
return; return;
} }
if (currentInfo == null) return; if (currentInfo == null) return;
PlayQueue queue = setupPlayQueueForIntent(false); final PlayQueue queue = setupPlayQueueForIntent(false);
// Video view can have elements visible from popup, We hide it here but once it ready the view will be shown in handleIntent() // Video view can have elements visible from popup, We hide it here but once it ready the view will be shown in handleIntent()
playerService.getView().setVisibility(View.GONE); Objects.requireNonNull(playerService.getView()).setVisibility(View.GONE);
addVideoPlayerView(); addVideoPlayerView();
Intent playerIntent = NavigationHelper.getPlayerIntent(getContext(), MainPlayer.class, queue, null, true); final Intent playerIntent = NavigationHelper.getPlayerIntent(requireContext(), MainPlayer.class, queue, null, true);
activity.startService(playerIntent); activity.startService(playerIntent);
} }
@ -995,7 +990,7 @@ public class VideoDetailFragment
playerService.getView().setVisibility(View.GONE); playerService.getView().setVisibility(View.GONE);
} }
private PlayQueue setupPlayQueueForIntent(boolean append) { private PlayQueue setupPlayQueueForIntent(final boolean append) {
if (append) return new SinglePlayQueue(currentInfo); if (append) return new SinglePlayQueue(currentInfo);
PlayQueue queue = playQueue; PlayQueue queue = playQueue;
@ -1026,7 +1021,7 @@ public class VideoDetailFragment
// Utils // Utils
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
public void setAutoplay(boolean autoplay) { public void setAutoplay(final boolean autoplay) {
this.autoPlayEnabled = autoplay; this.autoPlayEnabled = autoplay;
} }
@ -1059,7 +1054,7 @@ public class VideoDetailFragment
&& isAutoplayAllowedByUser(); && isAutoplayAllowedByUser();
} }
private boolean isAutoplayAllowedByUser () { private boolean isAutoplayAllowedByUser() {
if (activity == null) return false; if (activity == null) return false;
switch (PlayerHelper.getAutoplayType(activity)) { switch (PlayerHelper.getAutoplayType(activity)) {
@ -1076,7 +1071,7 @@ public class VideoDetailFragment
private void addVideoPlayerView() { private void addVideoPlayerView() {
if (player == null || getView() == null) return; if (player == null || getView() == null) return;
FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder); final FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder);
// Check if viewHolder already contains a child // Check if viewHolder already contains a child
if (player.getRootView().getParent() != viewHolder) removeVideoPlayerView(); if (player.getRootView().getParent() != viewHolder) removeVideoPlayerView();
@ -1095,7 +1090,7 @@ public class VideoDetailFragment
private void makeDefaultHeightForVideoPlaceholder() { private void makeDefaultHeightForVideoPlaceholder() {
if (getView() == null) return; if (getView() == null) return;
FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder); final FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder);
viewHolder.getLayoutParams().height = FrameLayout.LayoutParams.MATCH_PARENT; viewHolder.getLayoutParams().height = FrameLayout.LayoutParams.MATCH_PARENT;
viewHolder.requestLayout(); viewHolder.requestLayout();
} }
@ -1113,7 +1108,7 @@ public class VideoDetailFragment
disposables.add(Single.just(descriptionHtml) disposables.add(Single.just(descriptionHtml)
.map((@io.reactivex.annotations.NonNull String description) -> { .map((@io.reactivex.annotations.NonNull String description) -> {
Spanned parsedDescription; final Spanned parsedDescription;
if (Build.VERSION.SDK_INT >= 24) { if (Build.VERSION.SDK_INT >= 24) {
parsedDescription = Html.fromHtml(description, 0); parsedDescription = Html.fromHtml(description, 0);
} else { } else {
@ -1137,11 +1132,11 @@ public class VideoDetailFragment
*/ */
private void setHeightThumbnail() { private void setHeightThumbnail() {
final DisplayMetrics metrics = getResources().getDisplayMetrics(); final DisplayMetrics metrics = getResources().getDisplayMetrics();
boolean isPortrait = metrics.heightPixels > metrics.widthPixels; final boolean isPortrait = metrics.heightPixels > metrics.widthPixels;
int height; final int height;
if (player != null && player.isFullscreen()) if (player != null && player.isFullscreen())
height = isInMultiWindow() ? getView().getHeight() : activity.getWindow().getDecorView().getHeight(); height = isInMultiWindow() ? Objects.requireNonNull(getView()).getHeight() : activity.getWindow().getDecorView().getHeight();
else else
height = isPortrait height = isPortrait
? (int) (metrics.widthPixels / (16.0f / 9.0f)) ? (int) (metrics.widthPixels / (16.0f / 9.0f))
@ -1150,7 +1145,7 @@ public class VideoDetailFragment
thumbnailImageView.setLayoutParams(new FrameLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height)); thumbnailImageView.setLayoutParams(new FrameLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height));
thumbnailImageView.setMinimumHeight(height); thumbnailImageView.setMinimumHeight(height);
if (player != null) { if (player != null) {
int maxHeight = (int) (metrics.heightPixels * MAX_PLAYER_HEIGHT); final int maxHeight = (int) (metrics.heightPixels * MAX_PLAYER_HEIGHT);
player.getSurfaceView().setHeights(height, player.isFullscreen() ? height : maxHeight); player.getSurfaceView().setHeights(height, player.isFullscreen() ? height : maxHeight);
} }
} }
@ -1159,7 +1154,7 @@ public class VideoDetailFragment
contentRootLayoutHiding.setVisibility(View.VISIBLE); contentRootLayoutHiding.setVisibility(View.VISIBLE);
} }
protected void setInitialData(int serviceId, String url, String name, PlayQueue playQueue) { protected void setInitialData(final int serviceId, final String url, final String name, final PlayQueue playQueue) {
this.serviceId = serviceId; this.serviceId = serviceId;
this.url = url; this.url = url;
this.name = !TextUtils.isEmpty(name) ? name : ""; this.name = !TextUtils.isEmpty(name) ? name : "";
@ -1188,9 +1183,9 @@ public class VideoDetailFragment
broadcastReceiver = new BroadcastReceiver() { broadcastReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(ACTION_SHOW_MAIN_PLAYER)) { if (intent.getAction().equals(ACTION_SHOW_MAIN_PLAYER)) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
} else if(intent.getAction().equals(ACTION_HIDE_MAIN_PLAYER)) { } else if (intent.getAction().equals(ACTION_HIDE_MAIN_PLAYER)) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
} }
} }
@ -1227,7 +1222,7 @@ public class VideoDetailFragment
super.showLoading(); super.showLoading();
//if data is already cached, transition from VISIBLE -> INVISIBLE -> VISIBLE is not required //if data is already cached, transition from VISIBLE -> INVISIBLE -> VISIBLE is not required
if(!ExtractorHelper.isCached(serviceId, url, InfoItem.InfoType.STREAM)){ if (!ExtractorHelper.isCached(serviceId, url, InfoItem.InfoType.STREAM)) {
contentRootLayoutHiding.setVisibility(View.INVISIBLE); contentRootLayoutHiding.setVisibility(View.INVISIBLE);
} }
@ -1245,10 +1240,10 @@ public class VideoDetailFragment
videoTitleToggleArrow.setVisibility(View.GONE); videoTitleToggleArrow.setVisibility(View.GONE);
videoTitleRoot.setClickable(false); videoTitleRoot.setClickable(false);
if(relatedStreamsLayout != null){ if (relatedStreamsLayout != null) {
if(showRelatedStreams){ if (showRelatedStreams) {
relatedStreamsLayout.setVisibility(player != null && player.isFullscreen() ? View.GONE : View.INVISIBLE); relatedStreamsLayout.setVisibility(player != null && player.isFullscreen() ? View.GONE : View.INVISIBLE);
}else{ } else {
relatedStreamsLayout.setVisibility(View.GONE); relatedStreamsLayout.setVisibility(View.GONE);
} }
} }
@ -1266,11 +1261,11 @@ public class VideoDetailFragment
currentInfo = info; currentInfo = info;
setInitialData(info.getServiceId(), info.getOriginalUrl(), info.getName(), playQueue); setInitialData(info.getServiceId(), info.getOriginalUrl(), info.getName(), playQueue);
if(showRelatedStreams){ if (showRelatedStreams) {
if(null == relatedStreamsLayout){ //phone if (null == relatedStreamsLayout) { //phone
pageAdapter.updateItem(RELATED_TAB_TAG, RelatedVideosFragment.getInstance(info)); pageAdapter.updateItem(RELATED_TAB_TAG, RelatedVideosFragment.getInstance(info));
pageAdapter.notifyDataSetUpdate(); pageAdapter.notifyDataSetUpdate();
}else{ //tablet } else { //tablet
getChildFragmentManager().beginTransaction() getChildFragmentManager().beginTransaction()
.replace(R.id.relatedStreamsLayout, RelatedVideosFragment.getInstance(info)) .replace(R.id.relatedStreamsLayout, RelatedVideosFragment.getInstance(info))
.commitNow(); .commitNow();
@ -1359,6 +1354,12 @@ public class VideoDetailFragment
videoUploadDateView.setVisibility(View.GONE); videoUploadDateView.setVisibility(View.GONE);
} }
sortedVideoStreams = ListHelper.getSortedStreamVideosList(
activity,
info.getVideoStreams(),
info.getVideoOnlyStreams(),
false);
selectedVideoStreamIndex = ListHelper.getDefaultResolutionIndex(activity, sortedVideoStreams);
prepareDescription(info.getDescription()); prepareDescription(info.getDescription());
updateProgressInfo(info); updateProgressInfo(info);
initThumbnailViews(info); initThumbnailViews(info);
@ -1381,7 +1382,7 @@ public class VideoDetailFragment
detailControlsDownload.setVisibility(View.GONE); detailControlsDownload.setVisibility(View.GONE);
break; break;
default: default:
if(info.getAudioStreams().isEmpty()) detailControlsBackground.setVisibility(View.GONE); if (info.getAudioStreams().isEmpty()) detailControlsBackground.setVisibility(View.GONE);
if (!info.getVideoStreams().isEmpty() if (!info.getVideoStreams().isEmpty()
|| !info.getVideoOnlyStreams().isEmpty()) break; || !info.getVideoOnlyStreams().isEmpty()) break;
@ -1393,28 +1394,28 @@ public class VideoDetailFragment
public void openDownloadDialog() { public void openDownloadDialog() {
try { try {
DownloadDialog downloadDialog = DownloadDialog.newInstance(currentInfo); final DownloadDialog downloadDialog = DownloadDialog.newInstance(currentInfo);
downloadDialog.setVideoStreams(sortedVideoStreams); downloadDialog.setVideoStreams(sortedVideoStreams);
downloadDialog.setAudioStreams(currentInfo.getAudioStreams()); downloadDialog.setAudioStreams(currentInfo.getAudioStreams());
downloadDialog.setSelectedVideoStream(selectedVideoStreamIndex); downloadDialog.setSelectedVideoStream(selectedVideoStreamIndex);
downloadDialog.setSubtitleStreams(currentInfo.getSubtitles()); downloadDialog.setSubtitleStreams(currentInfo.getSubtitles());
downloadDialog.show(activity.getSupportFragmentManager(), "downloadDialog"); downloadDialog.show(activity.getSupportFragmentManager(), "downloadDialog");
} catch (Exception e) { } catch (Exception e) {
ErrorActivity.ErrorInfo info = ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR, final ErrorActivity.ErrorInfo info = ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
ServiceList.all() ServiceList.all()
.get(currentInfo .get(currentInfo
.getServiceId()) .getServiceId())
.getServiceInfo() .getServiceInfo()
.getName(), "", .getName(), "",
R.string.could_not_setup_download_menu); R.string.could_not_setup_download_menu);
ErrorActivity.reportError(activity, ErrorActivity.reportError(activity,
e, e,
activity.getClass(), activity.getClass(),
activity.findViewById(android.R.id.content), info); activity.findViewById(android.R.id.content), info);
} }
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
@ -1428,7 +1429,7 @@ public class VideoDetailFragment
else if (exception instanceof ContentNotAvailableException) { else if (exception instanceof ContentNotAvailableException) {
showError(getString(R.string.content_not_available), false); showError(getString(R.string.content_not_available), false);
} else { } else {
int errorId = exception instanceof YoutubeStreamExtractor.DecryptException final int errorId = exception instanceof YoutubeStreamExtractor.DecryptException
? R.string.youtube_signature_decryption_error ? R.string.youtube_signature_decryption_error
: exception instanceof ParsingException : exception instanceof ParsingException
? R.string.parsing_error ? R.string.parsing_error
@ -1484,7 +1485,7 @@ public class VideoDetailFragment
}); });
} }
private void showPlaybackProgress(long progress, long duration) { private void showPlaybackProgress(final long progress, final long duration) {
final int progressSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(progress); final int progressSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(progress);
final int durationSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(duration); final int durationSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(duration);
positionView.setMax(durationSeconds); positionView.setMax(durationSeconds);
@ -1501,9 +1502,9 @@ public class VideoDetailFragment
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@Override @Override
public void onQueueUpdate(PlayQueue queue) { public void onQueueUpdate(final PlayQueue queue) {
playQueue = queue; playQueue = queue;
StackItem stackWithQueue; final StackItem stackWithQueue;
// This should be the only place where we push data to stack. It will allow to have live instance of PlayQueue with actual // This should be the only place where we push data to stack. It will allow to have live instance of PlayQueue with actual
// information about deleted/added items inside Channel/Playlist queue and makes possible to have a history of played items // information about deleted/added items inside Channel/Playlist queue and makes possible to have a history of played items
if (stack.isEmpty() || !stack.peek().getPlayQueue().equals(queue)) { if (stack.isEmpty() || !stack.peek().getPlayQueue().equals(queue)) {
@ -1522,7 +1523,7 @@ public class VideoDetailFragment
} }
@Override @Override
public void onPlaybackUpdate(int state, int repeatMode, boolean shuffled, PlaybackParameters parameters) { public void onPlaybackUpdate(final int state, final int repeatMode, final boolean shuffled, final PlaybackParameters parameters) {
setOverlayPlayPauseImage(); setOverlayPlayPauseImage();
switch (state) { switch (state) {
@ -1542,7 +1543,7 @@ public class VideoDetailFragment
} }
@Override @Override
public void onProgressUpdate(int currentProgress, int duration, int bufferPercent) { public void onProgressUpdate(final int currentProgress, final int duration, final int bufferPercent) {
// Progress updates every second even if media is paused. It's useless until playing // Progress updates every second even if media is paused. It's useless until playing
if (!player.getPlayer().isPlaying() || playQueue == null) return; if (!player.getPlayer().isPlaying() || playQueue == null) return;
@ -1551,8 +1552,8 @@ public class VideoDetailFragment
} }
@Override @Override
public void onMetadataUpdate(StreamInfo info, PlayQueue queue) { public void onMetadataUpdate(final StreamInfo info, final PlayQueue queue) {
StackItem item = findQueueInStack(queue); final StackItem item = findQueueInStack(queue);
if (item != null) { if (item != null) {
// When PlayQueue can have multiple streams (PlaylistPlayQueue or ChannelPlayQueue) every new played stream gives // When PlayQueue can have multiple streams (PlaylistPlayQueue or ChannelPlayQueue) every new played stream gives
// new title and url. StackItem contains information about first played stream. Let's update it here // new title and url. StackItem contains information about first played stream. Let's update it here
@ -1567,13 +1568,13 @@ public class VideoDetailFragment
if (currentInfo != null && info.getUrl().equals(currentInfo.getUrl())) return; if (currentInfo != null && info.getUrl().equals(currentInfo.getUrl())) return;
currentInfo = info; currentInfo = info;
setInitialData(info.getServiceId(), info.getUrl(),info.getName(), queue); setInitialData(info.getServiceId(), info.getUrl(), info.getName(), queue);
setAutoplay(false); setAutoplay(false);
prepareAndHandleInfo(info, true); prepareAndHandleInfo(info, true);
} }
@Override @Override
public void onPlayerError(ExoPlaybackException error) { public void onPlayerError(final ExoPlaybackException error) {
if (error.type == ExoPlaybackException.TYPE_SOURCE || error.type == ExoPlaybackException.TYPE_UNEXPECTED) { if (error.type == ExoPlaybackException.TYPE_SOURCE || error.type == ExoPlaybackException.TYPE_UNEXPECTED) {
hideMainPlayer(); hideMainPlayer();
if (playerService != null && player.isFullscreen()) if (playerService != null && player.isFullscreen())
@ -1590,12 +1591,12 @@ public class VideoDetailFragment
} }
@Override @Override
public void onFullscreenStateChanged(boolean fullscreen) { public void onFullscreenStateChanged(final boolean fullscreen) {
if (playerService.getView() == null || player.getParentActivity() == null) if (playerService.getView() == null || player.getParentActivity() == null)
return; return;
View view = playerService.getView(); final View view = playerService.getView();
ViewGroup parent = (ViewGroup) view.getParent(); final ViewGroup parent = (ViewGroup) view.getParent();
if (parent == null) return; if (parent == null) return;
if (fullscreen) { if (fullscreen) {
@ -1619,7 +1620,7 @@ public class VideoDetailFragment
return; return;
} }
int newOrientation = isLandscape() ? final int newOrientation = isLandscape() ?
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
: ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; : ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
@ -1627,13 +1628,13 @@ public class VideoDetailFragment
} }
/* /*
* Will scroll down to description view after long click on moreOptionsButton * Will scroll down to description view after long click on moreOptionsButton
* */ * */
@Override @Override
public void onMoreOptionsLongClicked() { public void onMoreOptionsLongClicked() {
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams(); final CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior(); final AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, -getView().findViewById(R.id.player_placeholder).getHeight()); final ValueAnimator valueAnimator = ValueAnimator.ofInt(0, -getView().findViewById(R.id.player_placeholder).getHeight());
valueAnimator.setInterpolator(new DecelerateInterpolator()); valueAnimator.setInterpolator(new DecelerateInterpolator());
valueAnimator.addUpdateListener(animation -> { valueAnimator.addUpdateListener(animation -> {
behavior.setTopAndBottomOffset((int) animation.getAnimatedValue()); behavior.setTopAndBottomOffset((int) animation.getAnimatedValue());
@ -1662,7 +1663,7 @@ public class VideoDetailFragment
if (activity == null) return; if (activity == null) return;
int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE final int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_FULLSCREEN
@ -1683,12 +1684,10 @@ public class VideoDetailFragment
return player != null && player.getPlayer() != null && player.getPlayer().getPlaybackState() != Player.STATE_IDLE; return player != null && player.getPlayer() != null && player.getPlayer().getPlaybackState() != Player.STATE_IDLE;
} }
private void setupBrightness(boolean save) { private void setupBrightness(final boolean save) {
if (activity == null) return; if (activity == null) return;
WindowManager.LayoutParams lp = activity.getWindow().getAttributes(); final WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
float brightnessLevel;
if (save) { if (save) {
// Save current brightness level // Save current brightness level
PlayerHelper.setScreenBrightness(activity, lp.screenBrightness); PlayerHelper.setScreenBrightness(activity, lp.screenBrightness);
@ -1698,7 +1697,7 @@ public class VideoDetailFragment
lp.screenBrightness = -1; lp.screenBrightness = -1;
} else { } else {
// Restore already saved brightness level // Restore already saved brightness level
brightnessLevel = PlayerHelper.getScreenBrightness(activity); final float brightnessLevel = PlayerHelper.getScreenBrightness(activity);
if (brightnessLevel <= 0.0f && brightnessLevel > 1.0f) if (brightnessLevel <= 0.0f && brightnessLevel > 1.0f)
return; return;
@ -1712,7 +1711,7 @@ public class VideoDetailFragment
setAutoplay(true); setAutoplay(true);
player.checkLandscape(); player.checkLandscape();
boolean orientationLocked = PlayerHelper.globalScreenOrientationLocked(activity); final boolean orientationLocked = PlayerHelper.globalScreenOrientationLocked(activity);
// Let's give a user time to look at video information page if video is not playing // Let's give a user time to look at video information page if video is not playing
if (orientationLocked && !player.isPlaying()) { if (orientationLocked && !player.isPlaying()) {
player.onPlay(); player.onPlay();
@ -1729,17 +1728,17 @@ public class VideoDetailFragment
} }
/* /*
* Means that the player fragment was swiped away via BottomSheetLayout and is empty but ready for any new actions. See cleanUp() * Means that the player fragment was swiped away via BottomSheetLayout and is empty but ready for any new actions. See cleanUp()
* */ * */
private boolean wasCleared() { private boolean wasCleared() {
return url == null; return url == null;
} }
private StackItem findQueueInStack(PlayQueue queue) { private StackItem findQueueInStack(final PlayQueue queue) {
StackItem item = null; StackItem item = null;
Iterator<StackItem> iterator = stack.descendingIterator(); final Iterator<StackItem> iterator = stack.descendingIterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
StackItem next = iterator.next(); final StackItem next = iterator.next();
if (next.getPlayQueue().equals(queue)) { if (next.getPlayQueue().equals(queue)) {
item = next; item = next;
break; break;
@ -1763,7 +1762,7 @@ public class VideoDetailFragment
} }
} }
private void showClearingQueueConfirmation(Runnable onAllow) { private void showClearingQueueConfirmation(final Runnable onAllow) {
new AlertDialog.Builder(activity) new AlertDialog.Builder(activity)
.setTitle(R.string.confirm_prompt) .setTitle(R.string.confirm_prompt)
.setMessage(R.string.clear_queue_confirmation_description) .setMessage(R.string.clear_queue_confirmation_description)
@ -1775,14 +1774,14 @@ public class VideoDetailFragment
} }
/* /*
* Remove unneeded information while waiting for a next task * Remove unneeded information while waiting for a next task
* */ * */
private void cleanUp() { private void cleanUp() {
// New beginning // New beginning
stack.clear(); stack.clear();
if (currentWorker != null) currentWorker.dispose(); if (currentWorker != null) currentWorker.dispose();
stopService(); stopService();
setInitialData(0,null,"", null); setInitialData(0, null, "", null);
currentInfo = null; currentInfo = null;
updateOverlayData(null, null, null); updateOverlayData(null, null, null);
} }
@ -1792,10 +1791,10 @@ public class VideoDetailFragment
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
private void setupBottomPlayer() { private void setupBottomPlayer() {
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams(); final CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior(); final AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
FrameLayout bottomSheetLayout = activity.findViewById(R.id.fragment_player_holder); final FrameLayout bottomSheetLayout = activity.findViewById(R.id.fragment_player_holder);
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetLayout); bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetLayout);
bottomSheetBehavior.setState(bottomSheetState); bottomSheetBehavior.setState(bottomSheetState);
final int peekHeight = getResources().getDimensionPixelSize(R.dimen.mini_player_height); final int peekHeight = getResources().getDimensionPixelSize(R.dimen.mini_player_height);
@ -1810,7 +1809,8 @@ public class VideoDetailFragment
} }
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override public void onStateChanged(@NonNull View bottomSheet, int newState) { @Override
public void onStateChanged(@NonNull final View bottomSheet, final int newState) {
bottomSheetState = newState; bottomSheetState = newState;
switch (newState) { switch (newState) {
@ -1843,7 +1843,9 @@ public class VideoDetailFragment
break; break;
} }
} }
@Override public void onSlide(@NonNull View bottomSheet, float slideOffset) {
@Override
public void onSlide(@NonNull final View bottomSheet, final float slideOffset) {
setOverlayLook(appBarLayout, behavior, slideOffset); setOverlayLook(appBarLayout, behavior, slideOffset);
} }
}); });
@ -1855,31 +1857,31 @@ public class VideoDetailFragment
}); });
} }
private void updateOverlayData(@Nullable String title, @Nullable String uploader, @Nullable String thumbnailUrl) { private void updateOverlayData(@Nullable final String title, @Nullable final String uploader, @Nullable final String thumbnailUrl) {
overlayTitleTextView.setText(TextUtils.isEmpty(title) ? "" : title); overlayTitleTextView.setText(TextUtils.isEmpty(title) ? "" : title);
overlayChannelTextView.setText(TextUtils.isEmpty(uploader) ? "" : uploader); overlayChannelTextView.setText(TextUtils.isEmpty(uploader) ? "" : uploader);
overlayThumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark); overlayThumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark);
if (!TextUtils.isEmpty(thumbnailUrl)) if (!TextUtils.isEmpty(thumbnailUrl))
imageLoader.displayImage(thumbnailUrl, overlayThumbnailImageView, imageLoader.displayImage(thumbnailUrl, overlayThumbnailImageView,
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS, null); ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS, null);
} }
private void setOverlayPlayPauseImage() { private void setOverlayPlayPauseImage() {
int attr = player != null && player.getPlayer().getPlayWhenReady() ? R.attr.pause : R.attr.play; final int attr = player != null && player.getPlayer().getPlayWhenReady() ? R.attr.pause : R.attr.play;
overlayPlayPauseButton.setImageResource(ThemeHelper.resolveResourceIdFromAttr(activity, attr)); overlayPlayPauseButton.setImageResource(ThemeHelper.resolveResourceIdFromAttr(activity, attr));
} }
private void setOverlayLook(AppBarLayout appBarLayout, AppBarLayout.Behavior behavior, float slideOffset) { private void setOverlayLook(final AppBarLayout appBarLayout, final AppBarLayout.Behavior behavior, final float slideOffset) {
if (behavior != null) { if (behavior != null) {
overlay.setAlpha(Math.min(MAX_OVERLAY_ALPHA, 1 - slideOffset)); overlay.setAlpha(Math.min(MAX_OVERLAY_ALPHA, 1 - slideOffset));
// These numbers are not special. They just do a cool transition // These numbers are not special. They just do a cool transition
behavior.setTopAndBottomOffset((int)(-thumbnailImageView.getHeight() * 2 * (1 - slideOffset) / 3)); behavior.setTopAndBottomOffset((int) (-thumbnailImageView.getHeight() * 2 * (1 - slideOffset) / 3));
appBarLayout.requestLayout(); appBarLayout.requestLayout();
} }
} }
private void setOverlayElementsClickable(boolean enable) { private void setOverlayElementsClickable(final boolean enable) {
overlayThumbnailImageView.setClickable(enable); overlayThumbnailImageView.setClickable(enable);
overlayThumbnailImageView.setLongClickable(enable); overlayThumbnailImageView.setLongClickable(enable);
overlayMetadata.setClickable(enable); overlayMetadata.setClickable(enable);

View file

@ -274,7 +274,7 @@ public abstract class BasePlayer implements
return; return;
} }
boolean samePlayQueue = playQueue != null && playQueue.equals(queue); final boolean samePlayQueue = playQueue != null && playQueue.equals(queue);
final int repeatMode = intent.getIntExtra(REPEAT_MODE, getRepeatMode()); final int repeatMode = intent.getIntExtra(REPEAT_MODE, getRepeatMode());
final float playbackSpeed = intent.getFloatExtra(PLAYBACK_SPEED, getPlaybackSpeed()); final float playbackSpeed = intent.getFloatExtra(PLAYBACK_SPEED, getPlaybackSpeed());

View file

@ -102,7 +102,7 @@ public final class MainPlayer extends Service {
} }
private void createView() { private void createView() {
View layout = View.inflate(this, R.layout.activity_main_player, null); final View layout = View.inflate(this, R.layout.activity_main_player, null);
playerImpl = new VideoPlayerImpl(this); playerImpl = new VideoPlayerImpl(this);
playerImpl.setup(layout); playerImpl.setup(layout);
@ -124,7 +124,7 @@ public final class MainPlayer extends Service {
return START_NOT_STICKY; return START_NOT_STICKY;
} }
public void stop(boolean autoplayEnabled) { public void stop(final boolean autoplayEnabled) {
if (DEBUG) Log.d(TAG, "stop() called"); if (DEBUG) Log.d(TAG, "stop() called");
if (playerImpl.getPlayer() != null) { if (playerImpl.getPlayer() != null) {
@ -212,7 +212,7 @@ public final class MainPlayer extends Service {
if (getView().getParent() != null) { if (getView().getParent() != null) {
if (playerImpl.getParentActivity() != null) { if (playerImpl.getParentActivity() != null) {
// This means view was added to fragment // This means view was added to fragment
ViewGroup parent = (ViewGroup) getView().getParent(); final ViewGroup parent = (ViewGroup) getView().getParent();
parent.removeView(getView()); parent.removeView(getView());
} else } else
// This means view was added by windowManager for popup player // This means view was added by windowManager for popup player
@ -244,7 +244,7 @@ public final class MainPlayer extends Service {
setupNotification(notRemoteView); setupNotification(notRemoteView);
setupNotification(bigNotRemoteView); setupNotification(bigNotRemoteView);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, getString(R.string.notification_channel_id)) final NotificationCompat.Builder builder = new NotificationCompat.Builder(this, getString(R.string.notification_channel_id))
.setOngoing(true) .setOngoing(true)
.setSmallIcon(R.drawable.ic_newpipe_triangle_white) .setSmallIcon(R.drawable.ic_newpipe_triangle_white)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
@ -254,7 +254,7 @@ public final class MainPlayer extends Service {
return builder; return builder;
} }
private void setupNotification(RemoteViews remoteViews) { private void setupNotification(final RemoteViews remoteViews) {
// Don't show anything until player is playing // Don't show anything until player is playing
if (playerImpl == null) return; if (playerImpl == null) return;
@ -298,7 +298,7 @@ public final class MainPlayer extends Service {
* *
* @param drawableId if != -1, sets the drawable with that id on the play/pause button * @param drawableId if != -1, sets the drawable with that id on the play/pause button
*/ */
synchronized void updateNotification(int drawableId) { synchronized void updateNotification(final int drawableId) {
//if (DEBUG) Log.d(TAG, "updateNotification() called with: drawableId = [" + drawableId + "]"); //if (DEBUG) Log.d(TAG, "updateNotification() called with: drawableId = [" + drawableId + "]");
if (notBuilder == null) return; if (notBuilder == null) return;
if (drawableId != -1) { if (drawableId != -1) {
@ -329,7 +329,7 @@ public final class MainPlayer extends Service {
} }
private Intent getIntentForNotification() { private Intent getIntentForNotification() {
Intent intent; final Intent intent;
if (playerImpl.audioPlayerSelected() || playerImpl.popupPlayerSelected()) { if (playerImpl.audioPlayerSelected() || playerImpl.popupPlayerSelected()) {
// Means we play in popup or audio only. Let's show BackgroundPlayerActivity // Means we play in popup or audio only. Let's show BackgroundPlayerActivity
intent = NavigationHelper.getBackgroundPlayerActivityIntent(getApplicationContext()); intent = NavigationHelper.getBackgroundPlayerActivityIntent(getApplicationContext());

View file

@ -186,7 +186,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
} }
Intent getSwitchIntent(final Class clazz, final MainPlayer.PlayerType playerType) { Intent getSwitchIntent(final Class clazz, final MainPlayer.PlayerType playerType) {
Intent intent = NavigationHelper.getPlayerIntent( final Intent intent = NavigationHelper.getPlayerIntent(
getApplicationContext(), getApplicationContext(),
clazz, clazz,
this.player.getPlayQueue(), this.player.getPlayQueue(),

View file

@ -97,7 +97,7 @@ public class VideoPlayerImpl extends VideoPlayer
View.OnLongClickListener { View.OnLongClickListener {
private static final String TAG = ".VideoPlayerImpl"; private static final String TAG = ".VideoPlayerImpl";
private final float MAX_GESTURE_LENGTH = 0.75f; private static final float MAX_GESTURE_LENGTH = 0.75f;
private TextView titleTextView; private TextView titleTextView;
private TextView channelTextView; private TextView channelTextView;
@ -142,11 +142,11 @@ public class VideoPlayerImpl extends VideoPlayer
private boolean isVerticalVideo = false; private boolean isVerticalVideo = false;
boolean shouldUpdateOnProgress; boolean shouldUpdateOnProgress;
private MainPlayer service; private final MainPlayer service;
private PlayerServiceEventListener fragmentListener; private PlayerServiceEventListener fragmentListener;
private PlayerEventListener activityListener; private PlayerEventListener activityListener;
private GestureDetector gestureDetector; private GestureDetector gestureDetector;
private SharedPreferences defaultPreferences; private final SharedPreferences defaultPreferences;
private ContentObserver settingsContentObserver; private ContentObserver settingsContentObserver;
@NonNull @NonNull
final private AudioPlaybackResolver resolver; final private AudioPlaybackResolver resolver;
@ -184,7 +184,7 @@ public class VideoPlayerImpl extends VideoPlayer
public void handleIntent(Intent intent) { public void handleIntent(Intent intent) {
if (intent.getStringExtra(VideoPlayer.PLAY_QUEUE_KEY) == null) return; if (intent.getStringExtra(VideoPlayer.PLAY_QUEUE_KEY) == null) return;
MainPlayer.PlayerType oldPlayerType = playerType; final MainPlayer.PlayerType oldPlayerType = playerType;
choosePlayerTypeFromIntent(intent); choosePlayerTypeFromIntent(intent);
audioOnly = audioPlayerSelected(); audioOnly = audioPlayerSelected();
@ -350,8 +350,8 @@ public class VideoPlayerImpl extends VideoPlayer
*/ */
private void setupElementsSize() { private void setupElementsSize() {
if (popupPlayerSelected()) { if (popupPlayerSelected()) {
int controlsPadding = service.getResources().getDimensionPixelSize(R.dimen.player_popup_controls_padding); final int controlsPadding = service.getResources().getDimensionPixelSize(R.dimen.player_popup_controls_padding);
int buttonsPadding = service.getResources().getDimensionPixelSize(R.dimen.player_popup_buttons_padding); final int buttonsPadding = service.getResources().getDimensionPixelSize(R.dimen.player_popup_buttons_padding);
getTopControlsRoot().setPaddingRelative(controlsPadding, 0, controlsPadding, 0); getTopControlsRoot().setPaddingRelative(controlsPadding, 0, controlsPadding, 0);
getBottomControlsRoot().setPaddingRelative(controlsPadding, 0, controlsPadding, 0); getBottomControlsRoot().setPaddingRelative(controlsPadding, 0, controlsPadding, 0);
getQualityTextView().setPadding(buttonsPadding, buttonsPadding, buttonsPadding, buttonsPadding); getQualityTextView().setPadding(buttonsPadding, buttonsPadding, buttonsPadding, buttonsPadding);
@ -361,10 +361,10 @@ public class VideoPlayerImpl extends VideoPlayer
getQualityTextView().setMinimumWidth(0); getQualityTextView().setMinimumWidth(0);
getPlaybackSpeedTextView().setMinimumWidth(0); getPlaybackSpeedTextView().setMinimumWidth(0);
} else if (videoPlayerSelected()) { } else if (videoPlayerSelected()) {
int buttonsMinWidth = service.getResources().getDimensionPixelSize(R.dimen.player_main_buttons_min_width); final int buttonsMinWidth = service.getResources().getDimensionPixelSize(R.dimen.player_main_buttons_min_width);
int playerTopPadding = service.getResources().getDimensionPixelSize(R.dimen.player_main_top_padding); final int playerTopPadding = service.getResources().getDimensionPixelSize(R.dimen.player_main_top_padding);
int controlsPadding = service.getResources().getDimensionPixelSize(R.dimen.player_main_controls_padding); final int controlsPadding = service.getResources().getDimensionPixelSize(R.dimen.player_main_controls_padding);
int buttonsPadding = service.getResources().getDimensionPixelSize(R.dimen.player_main_buttons_padding); final int buttonsPadding = service.getResources().getDimensionPixelSize(R.dimen.player_main_buttons_padding);
getTopControlsRoot().setPaddingRelative(controlsPadding, playerTopPadding, controlsPadding, 0); getTopControlsRoot().setPaddingRelative(controlsPadding, playerTopPadding, controlsPadding, 0);
getBottomControlsRoot().setPaddingRelative(controlsPadding, 0, controlsPadding, 0); getBottomControlsRoot().setPaddingRelative(controlsPadding, 0, controlsPadding, 0);
getQualityTextView().setPadding(buttonsPadding, buttonsPadding, buttonsPadding, buttonsPadding); getQualityTextView().setPadding(buttonsPadding, buttonsPadding, buttonsPadding, buttonsPadding);
@ -379,7 +379,7 @@ public class VideoPlayerImpl extends VideoPlayer
public void initListeners() { public void initListeners() {
super.initListeners(); super.initListeners();
PlayerGestureListener listener = new PlayerGestureListener(this, service); final PlayerGestureListener listener = new PlayerGestureListener(this, service);
gestureDetector = new GestureDetector(context, listener); gestureDetector = new GestureDetector(context, listener);
getRootView().setOnTouchListener(listener); getRootView().setOnTouchListener(listener);
@ -415,7 +415,7 @@ public class VideoPlayerImpl extends VideoPlayer
if (getRootView() == null || getRootView().getParent() == null || !(getRootView().getParent() instanceof ViewGroup)) if (getRootView() == null || getRootView().getParent() == null || !(getRootView().getParent() instanceof ViewGroup))
return null; return null;
ViewGroup parent = (ViewGroup) getRootView().getParent(); final ViewGroup parent = (ViewGroup) getRootView().getParent();
return (AppCompatActivity) parent.getContext(); return (AppCompatActivity) parent.getContext();
} }
@ -509,7 +509,7 @@ public class VideoPlayerImpl extends VideoPlayer
} }
@Override @Override
public void onUpdateProgress(int currentProgress, int duration, int bufferPercent) { public void onUpdateProgress(final int currentProgress, final int duration, final int bufferPercent) {
super.onUpdateProgress(currentProgress, duration, bufferPercent); super.onUpdateProgress(currentProgress, duration, bufferPercent);
updateProgress(currentProgress, duration, bufferPercent); updateProgress(currentProgress, duration, bufferPercent);
@ -560,7 +560,8 @@ public class VideoPlayerImpl extends VideoPlayer
} }
@Override @Override
protected void initPlayback(@NonNull PlayQueue queue, int repeatMode, float playbackSpeed, float playbackPitch, boolean playbackSkipSilence, boolean playOnReady) { protected void initPlayback(@NonNull PlayQueue queue, int repeatMode, float playbackSpeed,
float playbackPitch, boolean playbackSkipSilence, boolean playOnReady) {
super.initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, playbackSkipSilence, playOnReady); super.initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, playbackSkipSilence, playOnReady);
updateQueue(); updateQueue();
} }
@ -760,16 +761,16 @@ public class VideoPlayerImpl extends VideoPlayer
} }
private void setupScreenRotationButton() { private void setupScreenRotationButton() {
boolean orientationLocked = PlayerHelper.globalScreenOrientationLocked(service); final boolean orientationLocked = PlayerHelper.globalScreenOrientationLocked(service);
boolean tabletInLandscape = isTablet(service) && service.isLandscape(); final boolean tabletInLandscape = isTablet(service) && service.isLandscape();
boolean showButton = videoPlayerSelected() && (orientationLocked || isVerticalVideo || tabletInLandscape); final boolean showButton = videoPlayerSelected() && (orientationLocked || isVerticalVideo || tabletInLandscape);
screenRotationButton.setVisibility(showButton ? View.VISIBLE : View.GONE); screenRotationButton.setVisibility(showButton ? View.VISIBLE : View.GONE);
screenRotationButton.setImageDrawable(service.getResources().getDrawable( screenRotationButton.setImageDrawable(service.getResources().getDrawable(
isFullscreen() ? R.drawable.ic_fullscreen_exit_white : R.drawable.ic_fullscreen_white)); isFullscreen() ? R.drawable.ic_fullscreen_exit_white : R.drawable.ic_fullscreen_white));
} }
private void prepareOrientation() { private void prepareOrientation() {
boolean orientationLocked = PlayerHelper.globalScreenOrientationLocked(service); final boolean orientationLocked = PlayerHelper.globalScreenOrientationLocked(service);
if (orientationLocked && isFullscreen() && service.isLandscape() == isVerticalVideo && fragmentListener != null) if (orientationLocked && isFullscreen() && service.isLandscape() == isVerticalVideo && fragmentListener != null)
fragmentListener.onScreenRotationButtonClicked(); fragmentListener.onScreenRotationButtonClicked();
} }
@ -1068,8 +1069,8 @@ public class VideoPlayerImpl extends VideoPlayer
// because in that case the controls should be aligned to another side of a screen. The problem is when user leaves // because in that case the controls should be aligned to another side of a screen. The problem is when user leaves
// the app and returns back (while the app in landscape) Android reports via DisplayMetrics that orientation is // the app and returns back (while the app in landscape) Android reports via DisplayMetrics that orientation is
// portrait and it gives wrong sizes calculations. Let's skip re-calculation in every case but landscape // portrait and it gives wrong sizes calculations. Let's skip re-calculation in every case but landscape
boolean reportedOrientationIsLandscape = service.isLandscape(); final boolean reportedOrientationIsLandscape = service.isLandscape();
boolean actualOrientationIsLandscape = context.getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE; final boolean actualOrientationIsLandscape = context.getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE;
if (reportedOrientationIsLandscape && actualOrientationIsLandscape) setControlsSize(); if (reportedOrientationIsLandscape && actualOrientationIsLandscape) setControlsSize();
// Close it because when changing orientation from portrait (in fullscreen mode) the size of queue layout can be // Close it because when changing orientation from portrait (in fullscreen mode) the size of queue layout can be
// larger than the screen size // larger than the screen size
@ -1130,7 +1131,7 @@ public class VideoPlayerImpl extends VideoPlayer
} }
} }
private void choosePlayerTypeFromIntent(Intent intent) { private void choosePlayerTypeFromIntent(final Intent intent) {
// If you want to open popup from the app just include Constants.POPUP_ONLY into an extra // If you want to open popup from the app just include Constants.POPUP_ONLY into an extra
if (intent.getIntExtra(PLAYER_TYPE, PLAYER_TYPE_VIDEO) == PLAYER_TYPE_AUDIO) { if (intent.getIntExtra(PLAYER_TYPE, PLAYER_TYPE_VIDEO) == PLAYER_TYPE_AUDIO) {
playerType = MainPlayer.PlayerType.AUDIO; playerType = MainPlayer.PlayerType.AUDIO;
@ -1165,12 +1166,12 @@ public class VideoPlayerImpl extends VideoPlayer
return getPlayer() == null || getPlayer().getPlaybackState() == SimpleExoPlayer.STATE_IDLE; return getPlayer() == null || getPlayer().getPlaybackState() == SimpleExoPlayer.STATE_IDLE;
} }
private int distanceFromCloseButton(MotionEvent popupMotionEvent) { private int distanceFromCloseButton(final MotionEvent popupMotionEvent) {
final int closeOverlayButtonX = closeOverlayButton.getLeft() + closeOverlayButton.getWidth() / 2; final int closeOverlayButtonX = closeOverlayButton.getLeft() + closeOverlayButton.getWidth() / 2;
final int closeOverlayButtonY = closeOverlayButton.getTop() + closeOverlayButton.getHeight() / 2; final int closeOverlayButtonY = closeOverlayButton.getTop() + closeOverlayButton.getHeight() / 2;
float fingerX = popupLayoutParams.x + popupMotionEvent.getX(); final float fingerX = popupLayoutParams.x + popupMotionEvent.getX();
float fingerY = popupLayoutParams.y + popupMotionEvent.getY(); final float fingerY = popupLayoutParams.y + popupMotionEvent.getY();
return (int) Math.sqrt(Math.pow(closeOverlayButtonX - fingerX, 2) + Math.pow(closeOverlayButtonY - fingerY, 2)); return (int) Math.sqrt(Math.pow(closeOverlayButtonX - fingerX, 2) + Math.pow(closeOverlayButtonY - fingerY, 2));
} }
@ -1181,7 +1182,7 @@ public class VideoPlayerImpl extends VideoPlayer
return buttonRadius * 1.2f; return buttonRadius * 1.2f;
} }
public boolean isInsideClosingRadius(MotionEvent popupMotionEvent) { public boolean isInsideClosingRadius(final MotionEvent popupMotionEvent) {
return distanceFromCloseButton(popupMotionEvent) <= getClosingRadius(); return distanceFromCloseButton(popupMotionEvent) <= getClosingRadius();
} }
@ -1199,7 +1200,7 @@ public class VideoPlayerImpl extends VideoPlayer
} }
@Override @Override
public void showControls(long duration) { public void showControls(final long duration) {
if (queueVisible) return; if (queueVisible) return;
showOrHideButtons(); showOrHideButtons();
@ -1208,7 +1209,7 @@ public class VideoPlayerImpl extends VideoPlayer
} }
@Override @Override
public void hideControls(final long duration, long delay) { public void hideControls(final long duration, final long delay) {
if (DEBUG) Log.d(TAG, "hideControls() called with: delay = [" + delay + "]"); if (DEBUG) Log.d(TAG, "hideControls() called with: delay = [" + delay + "]");
showOrHideButtons(); showOrHideButtons();
@ -1231,7 +1232,7 @@ public class VideoPlayerImpl extends VideoPlayer
private void showSystemUIPartially() { private void showSystemUIPartially() {
if (isFullscreen() && getParentActivity() != null) { if (isFullscreen() && getParentActivity() != null) {
int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE; final int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
getParentActivity().getWindow().getDecorView().setSystemUiVisibility(visibility); getParentActivity().getWindow().getDecorView().setSystemUiVisibility(visibility);
} }
} }
@ -1247,40 +1248,40 @@ public class VideoPlayerImpl extends VideoPlayer
* NavigationBar and notches but not under them. Tablets have only bottom NavigationBar * NavigationBar and notches but not under them. Tablets have only bottom NavigationBar
*/ */
public void setControlsSize() { public void setControlsSize() {
Point size = new Point(); final Point size = new Point();
Display display = getRootView().getDisplay(); final Display display = getRootView().getDisplay();
if (display == null || !videoPlayerSelected()) return; if (display == null || !videoPlayerSelected()) return;
// This method will give a correct size of a usable area of a window. // This method will give a correct size of a usable area of a window.
// It doesn't include NavigationBar, notches, etc. // It doesn't include NavigationBar, notches, etc.
display.getSize(size); display.getSize(size);
int width = isFullscreen ? (service.isLandscape() ? size.x : size.y) : ViewGroup.LayoutParams.MATCH_PARENT; final int width = isFullscreen ? (service.isLandscape() ? size.x : size.y) : ViewGroup.LayoutParams.MATCH_PARENT;
int gravity = isFullscreen ? (display.getRotation() == Surface.ROTATION_90 ? Gravity.START : Gravity.END) : Gravity.TOP; final int gravity = isFullscreen ? (display.getRotation() == Surface.ROTATION_90 ? Gravity.START : Gravity.END) : Gravity.TOP;
getTopControlsRoot().getLayoutParams().width = width; getTopControlsRoot().getLayoutParams().width = width;
RelativeLayout.LayoutParams topParams = ((RelativeLayout.LayoutParams) getTopControlsRoot().getLayoutParams()); final RelativeLayout.LayoutParams topParams = ((RelativeLayout.LayoutParams) getTopControlsRoot().getLayoutParams());
topParams.removeRule(RelativeLayout.ALIGN_PARENT_START); topParams.removeRule(RelativeLayout.ALIGN_PARENT_START);
topParams.removeRule(RelativeLayout.ALIGN_PARENT_END); topParams.removeRule(RelativeLayout.ALIGN_PARENT_END);
topParams.addRule(gravity == Gravity.END ? RelativeLayout.ALIGN_PARENT_END : RelativeLayout.ALIGN_PARENT_START); topParams.addRule(gravity == Gravity.END ? RelativeLayout.ALIGN_PARENT_END : RelativeLayout.ALIGN_PARENT_START);
getTopControlsRoot().requestLayout(); getTopControlsRoot().requestLayout();
getBottomControlsRoot().getLayoutParams().width = width; getBottomControlsRoot().getLayoutParams().width = width;
RelativeLayout.LayoutParams bottomParams = ((RelativeLayout.LayoutParams) getBottomControlsRoot().getLayoutParams()); final RelativeLayout.LayoutParams bottomParams = ((RelativeLayout.LayoutParams) getBottomControlsRoot().getLayoutParams());
bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_START); bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_START);
bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_END); bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_END);
bottomParams.addRule(gravity == Gravity.END ? RelativeLayout.ALIGN_PARENT_END : RelativeLayout.ALIGN_PARENT_START); bottomParams.addRule(gravity == Gravity.END ? RelativeLayout.ALIGN_PARENT_END : RelativeLayout.ALIGN_PARENT_START);
getBottomControlsRoot().requestLayout(); getBottomControlsRoot().requestLayout();
ViewGroup controlsRoot = getRootView().findViewById(R.id.playbackWindowRoot); final ViewGroup controlsRoot = getRootView().findViewById(R.id.playbackWindowRoot);
// In tablet navigationBar located at the bottom of the screen. And the situations when we need to set custom height is // In tablet navigationBar located at the bottom of the screen. And the situations when we need to set custom height is
// in fullscreen mode in tablet in non-multiWindow mode or with vertical video. Other than that MATCH_PARENT is good // in fullscreen mode in tablet in non-multiWindow mode or with vertical video. Other than that MATCH_PARENT is good
boolean navBarAtTheBottom = PlayerHelper.isTablet(service) || !service.isLandscape(); final boolean navBarAtTheBottom = PlayerHelper.isTablet(service) || !service.isLandscape();
controlsRoot.getLayoutParams().height = isFullscreen && !isInMultiWindow() && navBarAtTheBottom controlsRoot.getLayoutParams().height = isFullscreen && !isInMultiWindow() && navBarAtTheBottom
? size.y ? size.y
: ViewGroup.LayoutParams.MATCH_PARENT; : ViewGroup.LayoutParams.MATCH_PARENT;
controlsRoot.requestLayout(); controlsRoot.requestLayout();
int topPadding = isFullscreen && !isInMultiWindow() ? getStatusBarHeight() : 0; final int topPadding = isFullscreen && !isInMultiWindow() ? getStatusBarHeight() : 0;
getRootView().findViewById(R.id.playbackWindowRoot).setPadding(0, topPadding, 0, 0); getRootView().findViewById(R.id.playbackWindowRoot).setPadding(0, topPadding, 0, 0);
getRootView().findViewById(R.id.playbackWindowRoot).requestLayout(); getRootView().findViewById(R.id.playbackWindowRoot).requestLayout();
} }
@ -1290,11 +1291,11 @@ public class VideoPlayerImpl extends VideoPlayer
*/ */
private int getStatusBarHeight() { private int getStatusBarHeight() {
int statusBarHeight = 0; int statusBarHeight = 0;
int resourceId = service.getResources().getIdentifier("status_bar_height_landscape", "dimen", "android"); final int resourceId = service.getResources().getIdentifier("status_bar_height_landscape", "dimen", "android");
if (resourceId > 0) statusBarHeight = service.getResources().getDimensionPixelSize(resourceId); if (resourceId > 0) statusBarHeight = service.getResources().getDimensionPixelSize(resourceId);
if (statusBarHeight == 0) { if (statusBarHeight == 0) {
// Some devices provide wrong value for status bar height in landscape mode, this is workaround // Some devices provide wrong value for status bar height in landscape mode, this is workaround
DisplayMetrics metrics = getRootView().getResources().getDisplayMetrics(); final DisplayMetrics metrics = getRootView().getResources().getDisplayMetrics();
statusBarHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, metrics); statusBarHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, metrics);
} }
return statusBarHeight; return statusBarHeight;
@ -1304,7 +1305,7 @@ public class VideoPlayerImpl extends VideoPlayer
* @return true if main player is attached to activity and activity inside multiWindow mode * @return true if main player is attached to activity and activity inside multiWindow mode
*/ */
private boolean isInMultiWindow() { private boolean isInMultiWindow() {
AppCompatActivity parent = getParentActivity(); final AppCompatActivity parent = getParentActivity();
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && parent != null && parent.isInMultiWindowMode(); return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && parent != null && parent.isInMultiWindowMode();
} }
@ -1317,9 +1318,9 @@ public class VideoPlayerImpl extends VideoPlayer
} }
public void checkLandscape() { public void checkLandscape() {
AppCompatActivity parent = getParentActivity(); final AppCompatActivity parent = getParentActivity();
boolean videoInLandscapeButNotInFullscreen = service.isLandscape() && !isFullscreen() && videoPlayerSelected() && !audioOnly; final boolean videoInLandscapeButNotInFullscreen = service.isLandscape() && !isFullscreen() && videoPlayerSelected() && !audioOnly;
boolean playingState = getCurrentState() != STATE_COMPLETED && getCurrentState() != STATE_PAUSED; final boolean playingState = getCurrentState() != STATE_COMPLETED && getCurrentState() != STATE_PAUSED;
if (parent != null && videoInLandscapeButNotInFullscreen && playingState && !PlayerHelper.isTablet(service)) if (parent != null && videoInLandscapeButNotInFullscreen && playingState && !PlayerHelper.isTablet(service))
toggleFullscreen(); toggleFullscreen();
@ -1342,7 +1343,7 @@ public class VideoPlayerImpl extends VideoPlayer
itemsListCloseButton.setOnClickListener(view -> onQueueClosed()); itemsListCloseButton.setOnClickListener(view -> onQueueClosed());
} }
public void useVideoSource(boolean video) { public void useVideoSource(final boolean video) {
if (playQueue == null || audioOnly == !video || audioPlayerSelected()) if (playQueue == null || audioOnly == !video || audioPlayerSelected())
return; return;
@ -1415,7 +1416,7 @@ public class VideoPlayerImpl extends VideoPlayer
final boolean popupRememberSizeAndPos = PlayerHelper.isRememberingPopupDimensions(service); final boolean popupRememberSizeAndPos = PlayerHelper.isRememberingPopupDimensions(service);
final float defaultSize = service.getResources().getDimension(R.dimen.popup_default_width); final float defaultSize = service.getResources().getDimension(R.dimen.popup_default_width);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(service); final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(service);
popupWidth = popupRememberSizeAndPos ? sharedPreferences.getFloat(POPUP_SAVED_WIDTH, defaultSize) : defaultSize; popupWidth = popupRememberSizeAndPos ? sharedPreferences.getFloat(POPUP_SAVED_WIDTH, defaultSize) : defaultSize;
popupHeight = getMinimumVideoHeight(popupWidth); popupHeight = getMinimumVideoHeight(popupWidth);
@ -1428,8 +1429,8 @@ public class VideoPlayerImpl extends VideoPlayer
popupLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; popupLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
getSurfaceView().setHeights((int) popupHeight, (int) popupHeight); getSurfaceView().setHeights((int) popupHeight, (int) popupHeight);
int centerX = (int) (screenWidth / 2f - popupWidth / 2f); final int centerX = (int) (screenWidth / 2f - popupWidth / 2f);
int centerY = (int) (screenHeight / 2f - popupHeight / 2f); final int centerY = (int) (screenHeight / 2f - popupHeight / 2f);
popupLayoutParams.x = popupRememberSizeAndPos ? sharedPreferences.getInt(POPUP_SAVED_X, centerX) : centerX; popupLayoutParams.x = popupRememberSizeAndPos ? sharedPreferences.getInt(POPUP_SAVED_X, centerX) : centerX;
popupLayoutParams.y = popupRememberSizeAndPos ? sharedPreferences.getInt(POPUP_SAVED_Y, centerY) : centerY; popupLayoutParams.y = popupRememberSizeAndPos ? sharedPreferences.getInt(POPUP_SAVED_Y, centerY) : centerY;
@ -1458,7 +1459,7 @@ public class VideoPlayerImpl extends VideoPlayer
final int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE final int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
WindowManager.LayoutParams closeOverlayLayoutParams = new WindowManager.LayoutParams( final WindowManager.LayoutParams closeOverlayLayoutParams = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
popupLayoutParamType(), popupLayoutParamType(),
flags, flags,
@ -1523,19 +1524,19 @@ public class VideoPlayerImpl extends VideoPlayer
} }
public void savePositionAndSize() { public void savePositionAndSize() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(service); final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(service);
sharedPreferences.edit().putInt(POPUP_SAVED_X, popupLayoutParams.x).apply(); sharedPreferences.edit().putInt(POPUP_SAVED_X, popupLayoutParams.x).apply();
sharedPreferences.edit().putInt(POPUP_SAVED_Y, popupLayoutParams.y).apply(); sharedPreferences.edit().putInt(POPUP_SAVED_Y, popupLayoutParams.y).apply();
sharedPreferences.edit().putFloat(POPUP_SAVED_WIDTH, popupLayoutParams.width).apply(); sharedPreferences.edit().putFloat(POPUP_SAVED_WIDTH, popupLayoutParams.width).apply();
} }
private float getMinimumVideoHeight(float width) { private float getMinimumVideoHeight(final float width) {
//if (DEBUG) Log.d(TAG, "getMinimumVideoHeight() called with: width = [" + width + "], returned: " + height); //if (DEBUG) Log.d(TAG, "getMinimumVideoHeight() called with: width = [" + width + "], returned: " + height);
return width / (16.0f / 9.0f); // Respect the 16:9 ratio that most videos have return width / (16.0f / 9.0f); // Respect the 16:9 ratio that most videos have
} }
public void updateScreenSize() { public void updateScreenSize() {
DisplayMetrics metrics = new DisplayMetrics(); final DisplayMetrics metrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(metrics); windowManager.getDefaultDisplay().getMetrics(metrics);
screenWidth = metrics.widthPixels; screenWidth = metrics.widthPixels;
@ -1604,7 +1605,7 @@ public class VideoPlayerImpl extends VideoPlayer
} }
public void removePopupFromView() { public void removePopupFromView() {
boolean isCloseOverlayHasParent = closeOverlayView != null && closeOverlayView.getParent() != null; final boolean isCloseOverlayHasParent = closeOverlayView != null && closeOverlayView.getParent() != null;
if (popupHasParent()) if (popupHasParent())
windowManager.removeView(getRootView()); windowManager.removeView(getRootView());
if (isCloseOverlayHasParent) if (isCloseOverlayHasParent)
@ -1640,7 +1641,7 @@ public class VideoPlayerImpl extends VideoPlayer
} }
private boolean popupHasParent() { private boolean popupHasParent() {
View root = getRootView(); final View root = getRootView();
return root != null && root.getLayoutParams() instanceof WindowManager.LayoutParams && root.getParent() != null; return root != null && root.getLayoutParams() instanceof WindowManager.LayoutParams && root.getParent() != null;
} }
@ -1648,27 +1649,27 @@ public class VideoPlayerImpl extends VideoPlayer
// Manipulations with listener // Manipulations with listener
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
public void setFragmentListener(PlayerServiceEventListener listener) { public void setFragmentListener(final PlayerServiceEventListener listener) {
fragmentListener = listener; fragmentListener = listener;
updateMetadata(); updateMetadata();
updatePlayback(); updatePlayback();
triggerProgressUpdate(); triggerProgressUpdate();
} }
public void removeFragmentListener(PlayerServiceEventListener listener) { public void removeFragmentListener(final PlayerServiceEventListener listener) {
if (fragmentListener == listener) { if (fragmentListener == listener) {
fragmentListener = null; fragmentListener = null;
} }
} }
/*package-private*/ void setActivityListener(PlayerEventListener listener) { void setActivityListener(final PlayerEventListener listener) {
activityListener = listener; activityListener = listener;
updateMetadata(); updateMetadata();
updatePlayback(); updatePlayback();
triggerProgressUpdate(); triggerProgressUpdate();
} }
/*package-private*/ void removeActivityListener(PlayerEventListener listener) { void removeActivityListener(final PlayerEventListener listener) {
if (activityListener == listener) { if (activityListener == listener) {
activityListener = null; activityListener = null;
} }
@ -1703,7 +1704,7 @@ public class VideoPlayerImpl extends VideoPlayer
} }
} }
private void updateProgress(int currentProgress, int duration, int bufferPercent) { private void updateProgress(final int currentProgress, final int duration, final int bufferPercent) {
if (fragmentListener != null) { if (fragmentListener != null) {
fragmentListener.onProgressUpdate(currentProgress, duration, bufferPercent); fragmentListener.onProgressUpdate(currentProgress, duration, bufferPercent);
} }
@ -1787,11 +1788,11 @@ public class VideoPlayerImpl extends VideoPlayer
return popupHeight; return popupHeight;
} }
public void setPopupWidth(float width) { public void setPopupWidth(final float width) {
popupWidth = width; popupWidth = width;
} }
public void setPopupHeight(float height) { public void setPopupHeight(final float height) {
popupHeight = height; popupHeight = height;
} }

View file

@ -16,14 +16,14 @@ import java.util.List;
public class CustomBottomSheetBehavior extends BottomSheetBehavior<FrameLayout> { public class CustomBottomSheetBehavior extends BottomSheetBehavior<FrameLayout> {
public CustomBottomSheetBehavior(Context context, AttributeSet attrs) { public CustomBottomSheetBehavior(final Context context, final AttributeSet attrs) {
super(context, attrs); super(context, attrs);
} }
boolean visible; boolean visible;
Rect globalRect = new Rect(); Rect globalRect = new Rect();
private boolean skippingInterception = false; private boolean skippingInterception = false;
private List<Integer> skipInterceptionOfElements = Arrays.asList( private final List<Integer> skipInterceptionOfElements = Arrays.asList(
R.id.detail_content_root_layout, R.id.relatedStreamsLayout, R.id.playQueuePanel, R.id.viewpager); R.id.detail_content_root_layout, R.id.relatedStreamsLayout, R.id.playQueuePanel, R.id.viewpager);
@Override @Override
@ -38,8 +38,8 @@ public class CustomBottomSheetBehavior extends BottomSheetBehavior<FrameLayout>
// Don't need to do anything if bottomSheet isn't expanded // Don't need to do anything if bottomSheet isn't expanded
if (getState() == BottomSheetBehavior.STATE_EXPANDED) { if (getState() == BottomSheetBehavior.STATE_EXPANDED) {
// Without overriding scrolling will not work when user touches these elements // Without overriding scrolling will not work when user touches these elements
for (Integer element : skipInterceptionOfElements) { for (final Integer element : skipInterceptionOfElements) {
ViewGroup viewGroup = child.findViewById(element); final ViewGroup viewGroup = child.findViewById(element);
if (viewGroup != null) { if (viewGroup != null) {
visible = viewGroup.getGlobalVisibleRect(globalRect); visible = viewGroup.getGlobalVisibleRect(globalRect);
if (visible && globalRect.contains((int) event.getRawX(), (int) event.getRawY())) { if (visible && globalRect.contains((int) event.getRawX(), (int) event.getRawY())) {

View file

@ -20,8 +20,8 @@ public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListen
private static final String TAG = ".PlayerGestureListener"; private static final String TAG = ".PlayerGestureListener";
private static final boolean DEBUG = BasePlayer.DEBUG; private static final boolean DEBUG = BasePlayer.DEBUG;
private VideoPlayerImpl playerImpl; private final VideoPlayerImpl playerImpl;
private MainPlayer service; private final MainPlayer service;
private int initialPopupX, initialPopupY; private int initialPopupX, initialPopupY;
@ -29,7 +29,7 @@ public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListen
private boolean isResizing; private boolean isResizing;
private int tossFlingVelocity; private final int tossFlingVelocity;
private final boolean isVolumeGestureEnabled; private final boolean isVolumeGestureEnabled;
private final boolean isBrightnessGestureEnabled; private final boolean isBrightnessGestureEnabled;
@ -114,9 +114,9 @@ public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListen
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
private boolean onDoubleTapInMain(MotionEvent e) { private boolean onDoubleTapInMain(MotionEvent e) {
if (e.getX() > playerImpl.getRootView().getWidth() * 2 / 3) { if (e.getX() > playerImpl.getRootView().getWidth() * 2.0 / 3.0) {
playerImpl.onFastForward(); playerImpl.onFastForward();
} else if (e.getX() < playerImpl.getRootView().getWidth() / 3) { } else if (e.getX() < playerImpl.getRootView().getWidth() / 3.0) {
playerImpl.onFastRewind(); playerImpl.onFastRewind();
} else { } else {
playerImpl.getPlayPauseButton().performClick(); playerImpl.getPlayPauseButton().performClick();
@ -143,7 +143,8 @@ public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListen
return true; return true;
} }
private boolean onScrollInMain(MotionEvent initialEvent, MotionEvent movingEvent, float distanceX, float distanceY) { private boolean onScrollInMain(final MotionEvent initialEvent, final MotionEvent movingEvent,
final float distanceX, final float distanceY) {
if (!isVolumeGestureEnabled && !isBrightnessGestureEnabled) return false; if (!isVolumeGestureEnabled && !isBrightnessGestureEnabled) return false;
//noinspection PointlessBooleanExpression //noinspection PointlessBooleanExpression
@ -162,9 +163,9 @@ public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListen
if (isVolumeGestureEnabled && initialEvent.getX() > playerImpl.getRootView().getWidth() / 2.0) { if (isVolumeGestureEnabled && initialEvent.getX() > playerImpl.getRootView().getWidth() / 2.0) {
playerImpl.getVolumeProgressBar().incrementProgressBy((int) distanceY); playerImpl.getVolumeProgressBar().incrementProgressBy((int) distanceY);
float currentProgressPercent = final float currentProgressPercent =
(float) playerImpl.getVolumeProgressBar().getProgress() / playerImpl.getMaxGestureLength(); (float) playerImpl.getVolumeProgressBar().getProgress() / playerImpl.getMaxGestureLength();
int currentVolume = (int) (maxVolume * currentProgressPercent); final int currentVolume = (int) (maxVolume * currentProgressPercent);
playerImpl.getAudioReactor().setVolume(currentVolume); playerImpl.getAudioReactor().setVolume(currentVolume);
if (DEBUG) Log.d(TAG, "onScroll().volumeControl, currentVolume = " + currentVolume); if (DEBUG) Log.d(TAG, "onScroll().volumeControl, currentVolume = " + currentVolume);
@ -183,15 +184,15 @@ public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListen
playerImpl.getBrightnessRelativeLayout().setVisibility(View.GONE); playerImpl.getBrightnessRelativeLayout().setVisibility(View.GONE);
} }
} else if (isBrightnessGestureEnabled && initialEvent.getX() <= playerImpl.getRootView().getWidth() / 2.0) { } else if (isBrightnessGestureEnabled && initialEvent.getX() <= playerImpl.getRootView().getWidth() / 2.0) {
Activity parent = playerImpl.getParentActivity(); final Activity parent = playerImpl.getParentActivity();
if (parent == null) return true; if (parent == null) return true;
Window window = parent.getWindow(); final Window window = parent.getWindow();
playerImpl.getBrightnessProgressBar().incrementProgressBy((int) distanceY); playerImpl.getBrightnessProgressBar().incrementProgressBy((int) distanceY);
float currentProgressPercent = final float currentProgressPercent =
(float) playerImpl.getBrightnessProgressBar().getProgress() / playerImpl.getMaxGestureLength(); (float) playerImpl.getBrightnessProgressBar().getProgress() / playerImpl.getMaxGestureLength();
WindowManager.LayoutParams layoutParams = window.getAttributes(); final WindowManager.LayoutParams layoutParams = window.getAttributes();
layoutParams.screenBrightness = currentProgressPercent; layoutParams.screenBrightness = currentProgressPercent;
window.setAttributes(layoutParams); window.setAttributes(layoutParams);
@ -306,8 +307,10 @@ public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListen
isMovingInPopup = true; isMovingInPopup = true;
float diffX = (int) (movingEvent.getRawX() - initialEvent.getRawX()), posX = (int) (initialPopupX + diffX); final float diffX = (int) (movingEvent.getRawX() - initialEvent.getRawX());
float diffY = (int) (movingEvent.getRawY() - initialEvent.getRawY()), posY = (int) (initialPopupY + diffY); float posX = (int) (initialPopupX + diffX);
final float diffY = (int) (movingEvent.getRawY() - initialEvent.getRawY());
float posY = (int) (initialPopupY + diffY);
if (posX > (playerImpl.getScreenWidth() - playerImpl.getPopupWidth())) posX = (int) (playerImpl.getScreenWidth() - playerImpl.getPopupWidth()); if (posX > (playerImpl.getScreenWidth() - playerImpl.getPopupWidth())) posX = (int) (playerImpl.getScreenWidth() - playerImpl.getPopupWidth());
else if (posX < 0) posX = 0; else if (posX < 0) posX = 0;

View file

@ -46,7 +46,7 @@ public abstract class PlayQueue implements Serializable {
private ArrayList<PlayQueueItem> backup; private ArrayList<PlayQueueItem> backup;
private ArrayList<PlayQueueItem> streams; private ArrayList<PlayQueueItem> streams;
private ArrayList<PlayQueueItem> history; private final ArrayList<PlayQueueItem> history;
@NonNull private final AtomicInteger queueIndex; @NonNull private final AtomicInteger queueIndex;
private transient BehaviorSubject<PlayQueueEvent> eventBroadcast; private transient BehaviorSubject<PlayQueueEvent> eventBroadcast;
@ -132,7 +132,7 @@ public abstract class PlayQueue implements Serializable {
* Returns the item at the given index. * Returns the item at the given index.
* May throw {@link IndexOutOfBoundsException}. * May throw {@link IndexOutOfBoundsException}.
* */ * */
public PlayQueueItem getItem(int index) { public PlayQueueItem getItem(final int index) {
if (index < 0 || index >= streams.size() || streams.get(index) == null) return null; if (index < 0 || index >= streams.size() || streams.get(index) == null) return null;
return streams.get(index); return streams.get(index);
} }
@ -235,7 +235,7 @@ public abstract class PlayQueue implements Serializable {
* Will emit a {@link AppendEvent} on any given context. * Will emit a {@link AppendEvent} on any given context.
* */ * */
public synchronized void append(@NonNull final List<PlayQueueItem> items) { public synchronized void append(@NonNull final List<PlayQueueItem> items) {
List<PlayQueueItem> itemList = new ArrayList<>(items); final List<PlayQueueItem> itemList = new ArrayList<>(items);
if (isShuffled()) { if (isShuffled()) {
backup.addAll(itemList); backup.addAll(itemList);
@ -300,8 +300,7 @@ public abstract class PlayQueue implements Serializable {
} }
if (backup != null) { if (backup != null) {
final int backupIndex = backup.indexOf(getItem(removeIndex)); backup.remove(getItem(removeIndex));
backup.remove(backupIndex);
} }
history.remove(streams.remove(removeIndex)); history.remove(streams.remove(removeIndex));
@ -332,7 +331,7 @@ public abstract class PlayQueue implements Serializable {
queueIndex.incrementAndGet(); queueIndex.incrementAndGet();
} }
PlayQueueItem playQueueItem = streams.remove(source); final PlayQueueItem playQueueItem = streams.remove(source);
playQueueItem.setAutoQueued(false); playQueueItem.setAutoQueued(false);
streams.add(target, playQueueItem); streams.add(target, playQueueItem);
broadcast(new MoveEvent(source, target)); broadcast(new MoveEvent(source, target));
@ -431,7 +430,7 @@ public abstract class PlayQueue implements Serializable {
history.remove(history.size() - 1); history.remove(history.size() - 1);
PlayQueueItem last = history.remove(history.size() - 1); final PlayQueueItem last = history.remove(history.size() - 1);
setIndex(indexOf(last)); setIndex(indexOf(last));
return true; return true;
@ -443,11 +442,11 @@ public abstract class PlayQueue implements Serializable {
* VideoDetailFragment without duplicating items from two identical queues * VideoDetailFragment without duplicating items from two identical queues
* */ * */
@Override @Override
public boolean equals(@Nullable Object obj) { public boolean equals(@Nullable final Object obj) {
if (!(obj instanceof PlayQueue) || getStreams().size() != ((PlayQueue) obj).getStreams().size()) if (!(obj instanceof PlayQueue) || getStreams().size() != ((PlayQueue) obj).getStreams().size())
return false; return false;
PlayQueue other = (PlayQueue) obj; final PlayQueue other = (PlayQueue) obj;
for (int i = 0; i < getStreams().size(); i++) { for (int i = 0; i < getStreams().size(); i++) {
if (!getItem(i).getUrl().equals(other.getItem(i).getUrl())) if (!getItem(i).getUrl().equals(other.getItem(i).getUrl()))
return false; return false;

View file

@ -114,13 +114,25 @@ public class NavigationHelper {
.putExtra(BasePlayer.PLAYBACK_SKIP_SILENCE, playbackSkipSilence); .putExtra(BasePlayer.PLAYBACK_SKIP_SILENCE, playbackSkipSilence);
} }
public static void playOnMainPlayer(final AppCompatActivity activity, final PlayQueue queue, final boolean autoPlay) { public static void playOnMainPlayer(
final AppCompatActivity activity,
final PlayQueue queue,
final boolean autoPlay) {
playOnMainPlayer(activity.getSupportFragmentManager(), queue, autoPlay); playOnMainPlayer(activity.getSupportFragmentManager(), queue, autoPlay);
} }
public static void playOnMainPlayer(final FragmentManager fragmentManager, final PlayQueue queue, boolean autoPlay) { public static void playOnMainPlayer(
PlayQueueItem currentStream = queue.getItem(); final FragmentManager fragmentManager,
openVideoDetailFragment(fragmentManager, currentStream.getServiceId(), currentStream.getUrl(), currentStream.getTitle(), autoPlay, queue); final PlayQueue queue,
final boolean autoPlay) {
final PlayQueueItem currentStream = queue.getItem();
openVideoDetailFragment(
fragmentManager,
currentStream.getServiceId(),
currentStream.getUrl(),
currentStream.getTitle(),
autoPlay,
queue);
} }
public static void playOnMainPlayer(@NonNull final Context context, public static void playOnMainPlayer(@NonNull final Context context,
@ -131,7 +143,7 @@ public class NavigationHelper {
final boolean autoPlay, final boolean autoPlay,
final boolean resumePlayback) { final boolean resumePlayback) {
Intent intent = getPlayerIntent(context, MainActivity.class, queue, resumePlayback); final Intent intent = getPlayerIntent(context, MainActivity.class, queue, resumePlayback);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Constants.KEY_LINK_TYPE, linkType); intent.putExtra(Constants.KEY_LINK_TYPE, linkType);
intent.putExtra(Constants.KEY_URL, url); intent.putExtra(Constants.KEY_URL, url);
@ -147,14 +159,14 @@ public class NavigationHelper {
} }
Toast.makeText(context, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
Intent intent = getPlayerIntent(context, MainPlayer.class, queue, resumePlayback); final Intent intent = getPlayerIntent(context, MainPlayer.class, queue, resumePlayback);
intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_POPUP); intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_POPUP);
startService(context, intent); startService(context, intent);
} }
public static void playOnBackgroundPlayer(final Context context, final PlayQueue queue, final boolean resumePlayback) { public static void playOnBackgroundPlayer(final Context context, final PlayQueue queue, final boolean resumePlayback) {
Toast.makeText(context, R.string.background_player_playing_toast, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.background_player_playing_toast, Toast.LENGTH_SHORT).show();
Intent intent = getPlayerIntent(context, MainPlayer.class, queue, resumePlayback); final Intent intent = getPlayerIntent(context, MainPlayer.class, queue, resumePlayback);
intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_AUDIO); intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_AUDIO);
startService(context, intent); startService(context, intent);
} }
@ -170,7 +182,7 @@ public class NavigationHelper {
} }
Toast.makeText(context, R.string.popup_playing_append, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.popup_playing_append, Toast.LENGTH_SHORT).show();
Intent intent = getPlayerEnqueueIntent(context, MainPlayer.class, queue, selectOnAppend, resumePlayback); final Intent intent = getPlayerEnqueueIntent(context, MainPlayer.class, queue, selectOnAppend, resumePlayback);
intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_POPUP); intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_POPUP);
startService(context, intent); startService(context, intent);
} }
@ -179,9 +191,9 @@ public class NavigationHelper {
enqueueOnBackgroundPlayer(context, queue, false, resumePlayback); enqueueOnBackgroundPlayer(context, queue, false, resumePlayback);
} }
public static void enqueueOnBackgroundPlayer(final Context context, final PlayQueue queue, boolean selectOnAppend, final boolean resumePlayback) { public static void enqueueOnBackgroundPlayer(final Context context, final PlayQueue queue, final boolean selectOnAppend, final boolean resumePlayback) {
Toast.makeText(context, R.string.background_player_append, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.background_player_append, Toast.LENGTH_SHORT).show();
Intent intent = getPlayerEnqueueIntent(context, MainPlayer.class, queue, selectOnAppend, resumePlayback); final Intent intent = getPlayerEnqueueIntent(context, MainPlayer.class, queue, selectOnAppend, resumePlayback);
intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_AUDIO); intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_AUDIO);
startService(context, intent); startService(context, intent);
} }
@ -307,25 +319,31 @@ public class NavigationHelper {
openVideoDetailFragment(fragmentManager, serviceId, url, title, true, null); openVideoDetailFragment(fragmentManager, serviceId, url, title, true, null);
} }
public static void openVideoDetailFragment(FragmentManager fragmentManager, int serviceId, String url, String title, boolean autoPlay, PlayQueue playQueue) { public static void openVideoDetailFragment(
Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_player_holder); FragmentManager fragmentManager,
int serviceId,
String url,
String title,
boolean autoPlay,
PlayQueue playQueue) {
final Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_player_holder);
if (title == null) title = ""; if (title == null) title = "";
if (fragment instanceof VideoDetailFragment && fragment.isVisible()) { if (fragment instanceof VideoDetailFragment && fragment.isVisible()) {
expandMainPlayer(fragment.getActivity()); expandMainPlayer(fragment.requireActivity());
VideoDetailFragment detailFragment = (VideoDetailFragment) fragment; final VideoDetailFragment detailFragment = (VideoDetailFragment) fragment;
detailFragment.setAutoplay(autoPlay); detailFragment.setAutoplay(autoPlay);
detailFragment.selectAndLoadVideo(serviceId, url, title, playQueue); detailFragment.selectAndLoadVideo(serviceId, url, title, playQueue);
detailFragment.scrollToTop(); detailFragment.scrollToTop();
return; return;
} }
VideoDetailFragment instance = VideoDetailFragment.getInstance(serviceId, url, title, playQueue); final VideoDetailFragment instance = VideoDetailFragment.getInstance(serviceId, url, title, playQueue);
instance.setAutoplay(autoPlay); instance.setAutoplay(autoPlay);
defaultTransaction(fragmentManager) defaultTransaction(fragmentManager)
.replace(R.id.fragment_player_holder, instance) .replace(R.id.fragment_player_holder, instance)
.runOnCommit(() -> expandMainPlayer(instance.getActivity())) .runOnCommit(() -> expandMainPlayer(instance.requireActivity()))
.commit(); .commit();
} }
@ -335,9 +353,9 @@ public class NavigationHelper {
} }
public static void openChannelFragment( public static void openChannelFragment(
FragmentManager fragmentManager, final FragmentManager fragmentManager,
int serviceId, final int serviceId,
String url, final String url,
String name) { String name) {
if (name == null) name = ""; if (name == null) name = "";
defaultTransaction(fragmentManager) defaultTransaction(fragmentManager)
@ -525,7 +543,7 @@ public class NavigationHelper {
case STREAM: case STREAM:
rIntent.putExtra(VideoDetailFragment.AUTO_PLAY, rIntent.putExtra(VideoDetailFragment.AUTO_PLAY,
PreferenceManager.getDefaultSharedPreferences(context) PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(context.getString(R.string.autoplay_through_intent_key), false)); .getBoolean(context.getString(R.string.autoplay_through_intent_key), false));
break; break;
} }
@ -558,6 +576,7 @@ public class NavigationHelper {
/** /**
* Start an activity to install Kore * Start an activity to install Kore
*
* @param context the context * @param context the context
*/ */
public static void installKore(Context context) { public static void installKore(Context context) {
@ -566,13 +585,13 @@ public class NavigationHelper {
/** /**
* Start Kore app to show a video on Kodi * Start Kore app to show a video on Kodi
* * <p>
* For a list of supported urls see the * For a list of supported urls see the
* <a href="https://github.com/xbmc/Kore/blob/master/app/src/main/AndroidManifest.xml"> * <a href="https://github.com/xbmc/Kore/blob/master/app/src/main/AndroidManifest.xml">
* Kore source code * Kore source code
* </a>. * </a>.
* *
* @param context the context to use * @param context the context to use
* @param videoURL the url to the video * @param videoURL the url to the video
*/ */
public static void playWithKore(Context context, Uri videoURL) { public static void playWithKore(Context context, Uri videoURL) {

View file

@ -25,14 +25,14 @@ public class ExpandableSurfaceView extends SurfaceView {
if (videoAspectRatio == 0.0f) return; if (videoAspectRatio == 0.0f) return;
int width = MeasureSpec.getSize(widthMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec);
boolean verticalVideo = videoAspectRatio < 1; final boolean verticalVideo = videoAspectRatio < 1;
// Use maxHeight only on non-fit resize mode and in vertical videos // Use maxHeight only on non-fit resize mode and in vertical videos
int height = maxHeight != 0 && resizeMode != AspectRatioFrameLayout.RESIZE_MODE_FIT && verticalVideo ? maxHeight : baseHeight; int height = maxHeight != 0 && resizeMode != AspectRatioFrameLayout.RESIZE_MODE_FIT && verticalVideo ? maxHeight : baseHeight;
if (height == 0) return; if (height == 0) return;
float viewAspectRatio = width / ((float) height); final float viewAspectRatio = width / ((float) height);
float aspectDeformation = videoAspectRatio / viewAspectRatio - 1; final float aspectDeformation = videoAspectRatio / viewAspectRatio - 1;
scaleX = 1.0f; scaleX = 1.0f;
scaleY = 1.0f; scaleY = 1.0f;
@ -73,15 +73,14 @@ public class ExpandableSurfaceView extends SurfaceView {
* @param base The height that will be used in every resize mode as a minimum height * @param base The height that will be used in every resize mode as a minimum height
* @param max The max height for vertical videos in non-FIT resize modes * @param max The max height for vertical videos in non-FIT resize modes
*/ */
public void setHeights(int base, int max) { public void setHeights(final int base, final int max) {
if (baseHeight == base && maxHeight == max) return; if (baseHeight == base && maxHeight == max) return;
baseHeight = base; baseHeight = base;
maxHeight = max; maxHeight = max;
requestLayout(); requestLayout();
} }
@AspectRatioFrameLayout.ResizeMode public void setResizeMode(@AspectRatioFrameLayout.ResizeMode final int newResizeMode) {
public void setResizeMode(int newResizeMode) {
if (resizeMode == newResizeMode) return; if (resizeMode == newResizeMode) return;
resizeMode = newResizeMode; resizeMode = newResizeMode;
@ -93,7 +92,7 @@ public class ExpandableSurfaceView extends SurfaceView {
return resizeMode; return resizeMode;
} }
public void setAspectRatio(float aspectRatio) { public void setAspectRatio(final float aspectRatio) {
if (videoAspectRatio == aspectRatio) return; if (videoAspectRatio == aspectRatio) return;
videoAspectRatio = aspectRatio; videoAspectRatio = aspectRatio;