diff --git a/app/build.gradle b/app/build.gradle index f1480066d..12f1ac5fe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -44,10 +44,10 @@ android { ext { androidxLibVersion = '1.0.0' - exoPlayerLibVersion = '2.9.6' //2.10.5 + exoPlayerLibVersion = '2.10.5' roomDbLibVersion = '2.1.0' leakCanaryLibVersion = '1.5.4' //1.6.1 - okHttpLibVersion = '3.12.1' + okHttpLibVersion = '3.12.5' //3.12.6 icepickLibVersion = '3.2.0' stethoLibVersion = '1.5.0' } diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 98aadbaef..c24d77d03 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -28,17 +28,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.preference.PreferenceManager; -import androidx.annotation.NonNull; -import com.google.android.material.navigation.NavigationView; -import androidx.fragment.app.Fragment; -import androidx.core.view.GravityCompat; -import androidx.drawerlayout.widget.DrawerLayout; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.ActionBarDrawerToggle; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; import android.util.Log; -import android.view.Gravity; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -49,6 +39,17 @@ import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.ActionBarDrawerToggle; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.core.view.GravityCompat; +import androidx.drawerlayout.widget.DrawerLayout; +import androidx.fragment.app.Fragment; + +import com.google.android.material.navigation.NavigationView; + import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; @@ -361,7 +362,7 @@ public class MainActivity extends AppCompatActivity { // close drawer on return, and don't show animation, so its looks like the drawer isn't open // when the user returns to MainActivity - drawer.closeDrawer(Gravity.START, false); + drawer.closeDrawer(GravityCompat.START, false); try { String selectedServiceName = NewPipe.getService( ServiceHelper.getSelectedServiceId(this)).getServiceInfo().getName(); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java index 7a7710943..e0661a49f 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java @@ -1,15 +1,6 @@ package org.schabi.newpipe.fragments; import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import com.google.android.material.tabs.TabLayout; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentPagerAdapter; -import androidx.viewpager.widget.ViewPager; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -18,6 +9,17 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.tabs.TabLayout; + import org.schabi.newpipe.BaseFragment; import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.exceptions.ExtractionException; @@ -111,8 +113,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte public void onDestroy() { super.onDestroy(); tabsManager.unsetSavedTabsListener(); - pagerAdapter = null; - viewPager.setAdapter(pagerAdapter); + if (viewPager != null) viewPager.setAdapter(null); } /*////////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java index c9acf3c0b..764af271a 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java @@ -1,11 +1,12 @@ package org.schabi.newpipe.fragments.list; import android.os.Bundle; -import androidx.annotation.NonNull; import android.text.TextUtils; import android.util.Log; import android.view.View; +import androidx.annotation.NonNull; + import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.ListInfo; import org.schabi.newpipe.util.Constants; @@ -61,8 +62,10 @@ public abstract class BaseListInfoFragment @Override public void onDestroy() { super.onDestroy(); - if (currentWorker != null) currentWorker.dispose(); - currentWorker = null; + if (currentWorker != null) { + currentWorker.dispose(); + currentWorker = null; + } } /*////////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java index 71a8ae7b1..b3c5716bc 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -28,12 +28,13 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.AudioManager; import android.preference.PreferenceManager; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import android.util.Log; import android.view.View; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.google.android.exoplayer2.DefaultRenderersFactory; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayerFactory; @@ -209,7 +210,7 @@ public abstract class BasePlayer implements this.databaseUpdateReactor = new CompositeDisposable(); final String userAgent = Downloader.USER_AGENT; - final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); + final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter.Builder(context).build(); this.dataSource = new PlayerDataSource(context, userAgent, bandwidthMeter); final TrackSelection.Factory trackSelectionFactory = PlayerHelper.getQualitySelector(context); @@ -1193,10 +1194,7 @@ public abstract class BasePlayer implements } public boolean isPlaying() { - if (simpleExoPlayer == null) return false; - final int state = simpleExoPlayer.getPlaybackState(); - return (state == Player.STATE_READY || state == Player.STATE_BUFFERING) - && simpleExoPlayer.getPlayWhenReady(); + return simpleExoPlayer != null && simpleExoPlayer.isPlaying(); } @Player.RepeatMode diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java b/app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java index 605228099..8160640cb 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java @@ -1,9 +1,11 @@ package org.schabi.newpipe.player.helper; import android.content.Context; -import androidx.annotation.NonNull; import android.util.Log; +import androidx.annotation.NonNull; + +import com.google.android.exoplayer2.database.ExoDatabaseProvider; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DefaultDataSource; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; @@ -54,7 +56,7 @@ import java.io.File; if (cache == null) { final LeastRecentlyUsedCacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(maxCacheSize); - cache = new SimpleCache(cacheDir, evictor); + cache = new SimpleCache(cacheDir, evictor, new ExoDatabaseProvider(context)); } } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java b/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java index 37d4c1df9..a5c703837 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java @@ -2,11 +2,12 @@ package org.schabi.newpipe.player.helper; import android.content.Context; import android.content.Intent; +import android.support.v4.media.session.MediaSessionCompat; +import android.view.KeyEvent; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.media.session.MediaButtonReceiver; -import android.support.v4.media.session.MediaSessionCompat; -import android.view.KeyEvent; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector; @@ -27,10 +28,10 @@ public class MediaSessionManager { this.mediaSession = new MediaSessionCompat(context, TAG); this.mediaSession.setActive(true); - this.sessionConnector = new MediaSessionConnector(mediaSession, - new PlayQueuePlaybackController(callback)); + this.sessionConnector = new MediaSessionConnector(mediaSession); + this.sessionConnector.setControlDispatcher(new PlayQueuePlaybackController(callback)); this.sessionConnector.setQueueNavigator(new PlayQueueNavigator(mediaSession, callback)); - this.sessionConnector.setPlayer(player, null); + this.sessionConnector.setPlayer(player); } @Nullable @@ -43,7 +44,7 @@ public class MediaSessionManager { * Should be called on player destruction to prevent leakage. * */ public void dispose() { - this.sessionConnector.setPlayer(null, null); + this.sessionConnector.setPlayer(null); this.sessionConnector.setQueueNavigator(null); this.mediaSession.setActive(false); this.mediaSession.release(); diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java index 4602e83b8..5aa331dc5 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java @@ -1,9 +1,10 @@ package org.schabi.newpipe.player.helper; import android.content.Context; + import androidx.annotation.NonNull; -import com.google.android.exoplayer2.source.ExtractorMediaSource; +import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.source.SingleSampleMediaSource; import com.google.android.exoplayer2.source.dash.DashMediaSource; import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource; @@ -64,12 +65,12 @@ public class PlayerDataSource { cacheDataSourceFactory), cacheDataSourceFactory); } - public ExtractorMediaSource.Factory getExtractorMediaSourceFactory() { - return new ExtractorMediaSource.Factory(cacheDataSourceFactory) + public ProgressiveMediaSource.Factory getExtractorMediaSourceFactory() { + return new ProgressiveMediaSource.Factory(cacheDataSourceFactory) .setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(EXTRACTOR_MINIMUM_RETRY)); } - public ExtractorMediaSource.Factory getExtractorMediaSourceFactory(@NonNull final String key) { + public ProgressiveMediaSource.Factory getExtractorMediaSourceFactory(@NonNull final String key) { return getExtractorMediaSourceFactory().setCustomCacheKey(key); } diff --git a/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java b/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java index 72af2497f..ab0de08be 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java +++ b/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java @@ -2,10 +2,12 @@ package org.schabi.newpipe.player.mediasession; import android.os.Bundle; import android.os.ResultReceiver; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import android.support.v4.media.session.MediaSessionCompat; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.exoplayer2.ControlDispatcher; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector; import com.google.android.exoplayer2.util.Util; @@ -63,17 +65,17 @@ public class PlayQueueNavigator implements MediaSessionConnector.QueueNavigator } @Override - public void onSkipToPrevious(Player player) { + public void onSkipToPrevious(Player player, ControlDispatcher controlDispatcher) { callback.onSkipToPrevious(); } @Override - public void onSkipToQueueItem(Player player, long id) { + public void onSkipToQueueItem(Player player, ControlDispatcher controlDispatcher, long id) { callback.onSkipToIndex((int) id); } @Override - public void onSkipToNext(Player player) { + public void onSkipToNext(Player player, ControlDispatcher controlDispatcher) { callback.onSkipToNext(); } @@ -100,12 +102,7 @@ public class PlayQueueNavigator implements MediaSessionConnector.QueueNavigator } @Override - public String[] getCommands() { - return new String[0]; - } - - @Override - public void onCommand(Player player, String command, Bundle extras, ResultReceiver cb) { - + public boolean onCommand(Player player, ControlDispatcher controlDispatcher, String command, Bundle extras, ResultReceiver cb) { + return false; } } diff --git a/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueuePlaybackController.java b/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueuePlaybackController.java index a460a1653..b7f0638e3 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueuePlaybackController.java +++ b/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueuePlaybackController.java @@ -1,9 +1,9 @@ package org.schabi.newpipe.player.mediasession; +import com.google.android.exoplayer2.DefaultControlDispatcher; import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.ext.mediasession.DefaultPlaybackController; -public class PlayQueuePlaybackController extends DefaultPlaybackController { +public class PlayQueuePlaybackController extends DefaultControlDispatcher { private final MediaSessionCallback callback; public PlayQueuePlaybackController(final MediaSessionCallback callback) { @@ -12,12 +12,12 @@ public class PlayQueuePlaybackController extends DefaultPlaybackController { } @Override - public void onPlay(Player player) { - callback.onPlay(); - } - - @Override - public void onPause(Player player) { - callback.onPause(); + public boolean dispatchSetPlayWhenReady(Player player, boolean playWhenReady) { + if (playWhenReady) { + callback.onPlay(); + } else { + callback.onPause(); + } + return true; } } diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java b/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java index fde826a96..d51cf630d 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java @@ -1,15 +1,17 @@ package org.schabi.newpipe.player.playback; -import androidx.annotation.NonNull; import android.text.TextUtils; import android.util.Pair; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; -import com.google.android.exoplayer2.trackselection.FixedTrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.util.Assertions; @@ -21,7 +23,6 @@ import com.google.android.exoplayer2.util.Assertions; * a broader set of languages. * */ public class CustomTrackSelector extends DefaultTrackSelector { - private static final int WITHIN_RENDERER_CAPABILITIES_BONUS = 1000; private String preferredTextLanguage; @@ -41,23 +42,22 @@ public class CustomTrackSelector extends DefaultTrackSelector { } } - /** @see DefaultTrackSelector#formatHasLanguage(Format, String)*/ - protected static boolean formatHasLanguage(Format format, String language) { + private static boolean formatHasLanguage(Format format, String language) { return language != null && TextUtils.equals(language, format.language); } - /** @see DefaultTrackSelector#formatHasNoLanguage(Format)*/ - protected static boolean formatHasNoLanguage(Format format) { - return TextUtils.isEmpty(format.language) || formatHasLanguage(format, C.LANGUAGE_UNDETERMINED); - } - - /** @see DefaultTrackSelector#selectTextTrack(TrackGroupArray, int[][], Parameters) */ @Override - protected Pair selectTextTrack(TrackGroupArray groups, int[][] formatSupport, - Parameters params) { + @Nullable + protected Pair selectTextTrack( + TrackGroupArray groups, + int[][] formatSupport, + Parameters params, + @Nullable String selectedAudioLanguage) + throws ExoPlaybackException { TrackGroup selectedGroup = null; - int selectedTrackIndex = 0; - int selectedTrackScore = 0; + int selectedTrackIndex = C.INDEX_UNSET; + int newPipeTrackScore = 0; + TextTrackScore selectedTrackScore = null; for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) { TrackGroup trackGroup = groups.get(groupIndex); int[] trackFormatSupport = formatSupport[groupIndex]; @@ -65,41 +65,17 @@ public class CustomTrackSelector extends DefaultTrackSelector { if (isSupported(trackFormatSupport[trackIndex], params.exceedRendererCapabilitiesIfNecessary)) { Format format = trackGroup.getFormat(trackIndex); - int maskedSelectionFlags = - format.selectionFlags & ~params.disabledTextTrackSelectionFlags; - boolean isDefault = (maskedSelectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; - boolean isForced = (maskedSelectionFlags & C.SELECTION_FLAG_FORCED) != 0; - int trackScore; - boolean preferredLanguageFound = formatHasLanguage(format, preferredTextLanguage); - if (preferredLanguageFound - || (params.selectUndeterminedTextLanguage && formatHasNoLanguage(format))) { - if (isDefault) { - trackScore = 8; - } else if (!isForced) { - // Prefer non-forced to forced if a preferred text language has been specified. Where - // both are provided the non-forced track will usually contain the forced subtitles as - // a subset. - trackScore = 6; - } else { - trackScore = 4; - } - trackScore += preferredLanguageFound ? 1 : 0; - } else if (isDefault) { - trackScore = 3; - } else if (isForced) { - if (formatHasLanguage(format, params.preferredAudioLanguage)) { - trackScore = 2; - } else { - trackScore = 1; - } - } else { - // Track should not be selected. - continue; - } - if (isSupported(trackFormatSupport[trackIndex], false)) { - trackScore += WITHIN_RENDERER_CAPABILITIES_BONUS; - } - if (trackScore > selectedTrackScore) { + TextTrackScore trackScore = + new TextTrackScore( + format, params, trackFormatSupport[trackIndex], selectedAudioLanguage); + if (formatHasLanguage(format, preferredTextLanguage)) { + selectedGroup = trackGroup; + selectedTrackIndex = trackIndex; + selectedTrackScore = trackScore; + // found user selected match (perfect!) + break; + } else if (trackScore.isWithinConstraints + && (selectedTrackScore == null || trackScore.compareTo(selectedTrackScore) > 0)) { selectedGroup = trackGroup; selectedTrackIndex = trackIndex; selectedTrackScore = trackScore; @@ -110,6 +86,7 @@ public class CustomTrackSelector extends DefaultTrackSelector { return selectedGroup == null ? null : Pair.create( - new FixedTrackSelection(selectedGroup, selectedTrackIndex), selectedTrackScore); + new TrackSelection.Definition(selectedGroup, selectedTrackIndex), + Assertions.checkNotNull(selectedTrackScore)); } -} \ No newline at end of file +} diff --git a/build.gradle b/build.gradle index a95f6dcc0..60a85021a 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.0' + classpath 'com.android.tools.build:gradle:3.4.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e2a99f5b5..e98d29bd8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Sep 22 10:40:45 CEST 2019 +#Mon Oct 07 06:29:33 CEST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip