Merge remote-tracking branch 'upstream/dev' into sepiasearch
This commit is contained in:
commit
5c4d72ec42
47 changed files with 522 additions and 171 deletions
|
|
@ -67,8 +67,10 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins;
|
|||
public class App extends MultiDexApplication {
|
||||
protected static final String TAG = App.class.toString();
|
||||
private static App app;
|
||||
public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID;
|
||||
|
||||
@Nullable private Disposable disposable = null;
|
||||
@Nullable
|
||||
private Disposable disposable = null;
|
||||
|
||||
@NonNull
|
||||
public static App getApp() {
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
+ "savedInstanceState = [" + savedInstanceState + "]");
|
||||
}
|
||||
|
||||
// enable TLS1.1/1.2 for kitkat devices, to fix download and play for mediaCCC sources
|
||||
// enable TLS1.1/1.2 for kitkat devices, to fix download and play for media.ccc.de sources
|
||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
|
||||
TLSSocketFactoryCompat.setAsDefault();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,37 +29,46 @@ public class AboutActivity extends AppCompatActivity {
|
|||
* List of all software components.
|
||||
*/
|
||||
private static final SoftwareComponent[] SOFTWARE_COMPONENTS = {
|
||||
new SoftwareComponent("Giga Get", "2014 - 2015", "Peter Cai",
|
||||
new SoftwareComponent("ACRA", "2013", "Kevin Gaudin",
|
||||
"https://github.com/ACRA/acra", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("AndroidX", "2005 - 2011", "The Android Open Source Project",
|
||||
"https://developer.android.com/jetpack", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("CircleImageView", "2014 - 2020", "Henning Dodenhof",
|
||||
"https://github.com/hdodenhof/CircleImageView",
|
||||
StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("ExoPlayer", "2014 - 2020", "Google, Inc.",
|
||||
"https://github.com/google/ExoPlayer", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("GigaGet", "2014 - 2015", "Peter Cai",
|
||||
"https://github.com/PaperAirplane-Dev-Team/GigaGet", StandardLicenses.GPL3),
|
||||
new SoftwareComponent("Groupie", "2016", "Lisa Wray",
|
||||
"https://github.com/lisawray/groupie", StandardLicenses.MIT),
|
||||
new SoftwareComponent("Icepick", "2015", "Frankie Sardo",
|
||||
"https://github.com/frankiesardo/icepick", StandardLicenses.EPL1),
|
||||
new SoftwareComponent("Jsoup", "2009 - 2020", "Jonathan Hedley",
|
||||
"https://github.com/jhy/jsoup", StandardLicenses.MIT),
|
||||
new SoftwareComponent("Markwon", "2019", "Dimitry Ivanov",
|
||||
"https://github.com/noties/Markwon", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("Material Components for Android", "2016 - 2020", "Google, Inc.",
|
||||
"https://github.com/material-components/material-components-android",
|
||||
StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("NewPipe Extractor", "2017 - 2020", "Christian Schabesberger",
|
||||
"https://github.com/TeamNewPipe/NewPipeExtractor", StandardLicenses.GPL3),
|
||||
new SoftwareComponent("Jsoup", "2017", "Jonathan Hedley",
|
||||
"https://github.com/jhy/jsoup", StandardLicenses.MIT),
|
||||
new SoftwareComponent("Rhino", "2015", "Mozilla",
|
||||
"https://www.mozilla.org/rhino/", StandardLicenses.MPL2),
|
||||
new SoftwareComponent("ACRA", "2013", "Kevin Gaudin",
|
||||
"http://www.acra.ch", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("NoNonsense-FilePicker", "2016", "Jonas Kalderstam",
|
||||
"https://github.com/spacecowboy/NoNonsense-FilePicker",
|
||||
StandardLicenses.MPL2),
|
||||
new SoftwareComponent("OkHttp", "2019", "Square, Inc.",
|
||||
"https://square.github.io/okhttp/", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("PrettyTime", "2012 - 2020", "Lincoln Baxter, III",
|
||||
"https://github.com/ocpsoft/prettytime", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("RxAndroid", "2015", "The RxAndroid authors",
|
||||
"https://github.com/ReactiveX/RxAndroid", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("RxBinding", "2015", "Jake Wharton",
|
||||
"https://github.com/JakeWharton/RxBinding", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("RxJava", "2016 - 2020", "RxJava Contributors",
|
||||
"https://github.com/ReactiveX/RxJava", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("Universal Image Loader", "2011 - 2015", "Sergey Tarasevich",
|
||||
"https://github.com/nostra13/Android-Universal-Image-Loader",
|
||||
StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("CircleImageView", "2014 - 2020", "Henning Dodenhof",
|
||||
"https://github.com/hdodenhof/CircleImageView", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("NoNonsense-FilePicker", "2016", "Jonas Kalderstam",
|
||||
"https://github.com/spacecowboy/NoNonsense-FilePicker", StandardLicenses.MPL2),
|
||||
new SoftwareComponent("ExoPlayer", "2014 - 2020", "Google Inc",
|
||||
"https://github.com/google/ExoPlayer", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("RxAndroid", "2015 - 2018", "The RxAndroid authors",
|
||||
"https://github.com/ReactiveX/RxAndroid", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("RxJava", "2016 - 2020", "RxJava Contributors",
|
||||
"https://github.com/ReactiveX/RxJava", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("RxBinding", "2015 - 2018", "Jake Wharton",
|
||||
"https://github.com/JakeWharton/RxBinding", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("PrettyTime", "2012 - 2020", "Lincoln Baxter, III",
|
||||
"https://github.com/ocpsoft/prettytime", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("Markwon", "2017 - 2020", "Noties",
|
||||
"https://github.com/noties/Markwon", StandardLicenses.APACHE2),
|
||||
new SoftwareComponent("Groupie", "2016", "Lisa Wray",
|
||||
"https://github.com/lisawray/groupie", StandardLicenses.MIT)
|
||||
};
|
||||
|
||||
private static final int POS_ABOUT = 0;
|
||||
|
|
@ -115,7 +124,8 @@ public class AboutActivity extends AppCompatActivity {
|
|||
* A placeholder fragment containing a simple view.
|
||||
*/
|
||||
public static class AboutFragment extends Fragment {
|
||||
public AboutFragment() { }
|
||||
public AboutFragment() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Created a new instance of this fragment for the given section number.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import org.schabi.newpipe.util.ShareUtils;
|
|||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
|
||||
|
|
@ -35,12 +36,9 @@ public class LicenseFragment extends Fragment {
|
|||
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
|
||||
public static LicenseFragment newInstance(final SoftwareComponent[] softwareComponents) {
|
||||
if (softwareComponents == null) {
|
||||
throw new NullPointerException("softwareComponents is null");
|
||||
}
|
||||
final LicenseFragment fragment = new LicenseFragment();
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putParcelableArray(ARG_COMPONENTS, softwareComponents);
|
||||
bundle.putParcelableArray(ARG_COMPONENTS, Objects.requireNonNull(softwareComponents));
|
||||
final LicenseFragment fragment = new LicenseFragment();
|
||||
fragment.setArguments(bundle);
|
||||
return fragment;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ public final class StandardLicenses {
|
|||
= new License("Mozilla Public License, Version 2.0", "MPL 2.0", "mpl2.html");
|
||||
public static final License MIT
|
||||
= new License("MIT License", "MIT", "mit.html");
|
||||
public static final License EPL1
|
||||
= new License("Eclipse Public License, Version 1.0", "EPL 1.0", "epl1.html");
|
||||
|
||||
private StandardLicenses() { }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,15 +146,15 @@ public final class VideoDetailFragment
|
|||
private static final float MAX_PLAYER_HEIGHT = 0.7f;
|
||||
|
||||
public static final String ACTION_SHOW_MAIN_PLAYER =
|
||||
"org.schabi.newpipe.VideoDetailFragment.ACTION_SHOW_MAIN_PLAYER";
|
||||
App.PACKAGE_NAME + ".VideoDetailFragment.ACTION_SHOW_MAIN_PLAYER";
|
||||
public static final String ACTION_HIDE_MAIN_PLAYER =
|
||||
"org.schabi.newpipe.VideoDetailFragment.ACTION_HIDE_MAIN_PLAYER";
|
||||
App.PACKAGE_NAME + ".VideoDetailFragment.ACTION_HIDE_MAIN_PLAYER";
|
||||
public static final String ACTION_PLAYER_STARTED =
|
||||
"org.schabi.newpipe.VideoDetailFragment.ACTION_PLAYER_STARTED";
|
||||
App.PACKAGE_NAME + ".VideoDetailFragment.ACTION_PLAYER_STARTED";
|
||||
public static final String ACTION_VIDEO_FRAGMENT_RESUMED =
|
||||
"org.schabi.newpipe.VideoDetailFragment.ACTION_VIDEO_FRAGMENT_RESUMED";
|
||||
App.PACKAGE_NAME + ".VideoDetailFragment.ACTION_VIDEO_FRAGMENT_RESUMED";
|
||||
public static final String ACTION_VIDEO_FRAGMENT_STOPPED =
|
||||
"org.schabi.newpipe.VideoDetailFragment.ACTION_VIDEO_FRAGMENT_STOPPED";
|
||||
App.PACKAGE_NAME + ".VideoDetailFragment.ACTION_VIDEO_FRAGMENT_STOPPED";
|
||||
|
||||
private static final String COMMENTS_TAB_TAG = "COMMENTS";
|
||||
private static final String RELATED_TAB_TAG = "NEXT VIDEO";
|
||||
|
|
@ -498,10 +498,10 @@ public final class VideoDetailFragment
|
|||
|
||||
final PlaylistAppendDialog d = PlaylistAppendDialog.fromStreamInfo(currentInfo);
|
||||
disposables.add(
|
||||
PlaylistAppendDialog.onPlaylistFound(getContext(),
|
||||
() -> d.show(getFM(), TAG),
|
||||
() -> PlaylistCreationDialog.newInstance(d).show(getFM(), TAG)
|
||||
)
|
||||
PlaylistAppendDialog.onPlaylistFound(getContext(),
|
||||
() -> d.show(getFM(), TAG),
|
||||
() -> PlaylistCreationDialog.newInstance(d).show(getFM(), TAG)
|
||||
)
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
|
@ -1891,8 +1891,10 @@ public final class VideoDetailFragment
|
|||
|
||||
if (fullscreen) {
|
||||
hideSystemUiIfNeeded();
|
||||
viewPager.setVisibility(View.GONE);
|
||||
} else {
|
||||
showSystemUi();
|
||||
viewPager.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (relatedStreamsLayout != null) {
|
||||
|
|
@ -2048,6 +2050,10 @@ public final class VideoDetailFragment
|
|||
// Apply system brightness when the player is not in fullscreen
|
||||
restoreDefaultBrightness();
|
||||
} else {
|
||||
// Do not restore if user has disabled brightness gesture
|
||||
if (!PlayerHelper.isBrightnessGestureEnabled(activity)) {
|
||||
return;
|
||||
}
|
||||
// Restore already saved brightness level
|
||||
final float brightnessLevel = PlayerHelper.getScreenBrightness(activity);
|
||||
if (brightnessLevel == lp.screenBrightness) {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,8 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder {
|
|||
} else {
|
||||
itemProgressView.setVisibility(View.GONE);
|
||||
}
|
||||
} else if (item.getStreamType() == StreamType.LIVE_STREAM) {
|
||||
} else if (item.getStreamType() == StreamType.LIVE_STREAM
|
||||
|| item.getStreamType() == StreamType.AUDIO_LIVE_STREAM) {
|
||||
itemDurationView.setText(R.string.duration_live);
|
||||
itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(),
|
||||
R.color.live_duration_background_color));
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ import io.reactivex.rxjava3.processors.PublishProcessor
|
|||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.reactivestreams.Subscriber
|
||||
import org.reactivestreams.Subscription
|
||||
import org.schabi.newpipe.App
|
||||
import org.schabi.newpipe.MainActivity.DEBUG
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
|
||||
|
|
@ -68,7 +69,7 @@ class FeedLoadService : Service() {
|
|||
companion object {
|
||||
private val TAG = FeedLoadService::class.java.simpleName
|
||||
private const val NOTIFICATION_ID = 7293450
|
||||
private const val ACTION_CANCEL = "org.schabi.newpipe.local.feed.service.FeedLoadService.CANCEL"
|
||||
private const val ACTION_CANCEL = App.PACKAGE_NAME + ".local.feed.service.FeedLoadService.CANCEL"
|
||||
|
||||
/**
|
||||
* How often the notification will be updated.
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|||
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
import org.schabi.newpipe.App;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
||||
import org.schabi.newpipe.extractor.subscription.SubscriptionItem;
|
||||
|
|
@ -50,7 +51,7 @@ public class SubscriptionsExportService extends BaseImportExportService {
|
|||
* A {@link LocalBroadcastManager local broadcast} will be made with this action
|
||||
* when the export is successfully completed.
|
||||
*/
|
||||
public static final String EXPORT_COMPLETE_ACTION = "org.schabi.newpipe.local.subscription"
|
||||
public static final String EXPORT_COMPLETE_ACTION = App.PACKAGE_NAME + ".local.subscription"
|
||||
+ ".services.SubscriptionsExportService.EXPORT_COMPLETE";
|
||||
|
||||
private Subscription subscription;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|||
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
import org.schabi.newpipe.App;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
|
|
@ -66,7 +67,7 @@ public class SubscriptionsImportService extends BaseImportExportService {
|
|||
* A {@link LocalBroadcastManager local broadcast} will be made with this action
|
||||
* when the import is successfully completed.
|
||||
*/
|
||||
public static final String IMPORT_COMPLETE_ACTION = "org.schabi.newpipe.local.subscription"
|
||||
public static final String IMPORT_COMPLETE_ACTION = App.PACKAGE_NAME + ".local.subscription"
|
||||
+ ".services.SubscriptionsImportService.IMPORT_COMPLETE";
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -19,6 +19,12 @@
|
|||
|
||||
package org.schabi.newpipe.player;
|
||||
|
||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_INTERNAL;
|
||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_PERIOD_TRANSITION;
|
||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK;
|
||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
|
@ -30,11 +36,9 @@ import android.media.AudioManager;
|
|||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.DefaultRenderersFactory;
|
||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||
|
|
@ -53,7 +57,12 @@ import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
|||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
import io.reactivex.rxjava3.disposables.SerialDisposable;
|
||||
import java.io.IOException;
|
||||
import org.schabi.newpipe.DownloaderImpl;
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.R;
|
||||
|
|
@ -75,20 +84,6 @@ import org.schabi.newpipe.player.resolver.MediaSourceTag;
|
|||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||
import org.schabi.newpipe.util.SerializedCache;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
import io.reactivex.rxjava3.disposables.SerialDisposable;
|
||||
|
||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_INTERNAL;
|
||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_PERIOD_TRANSITION;
|
||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK;
|
||||
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
/**
|
||||
* Base for the players, joining the common properties.
|
||||
*
|
||||
|
|
@ -342,37 +337,36 @@ public abstract class BasePlayer implements
|
|||
simpleExoPlayer.setPlayWhenReady(playWhenReady);
|
||||
|
||||
} else if (intent.getBooleanExtra(RESUME_PLAYBACK, false)
|
||||
&& isPlaybackResumeEnabled()
|
||||
&& !samePlayQueue) {
|
||||
final PlayQueueItem item = queue.getItem();
|
||||
if (item != null && item.getRecoveryPosition() == PlayQueueItem.RECOVERY_UNSET) {
|
||||
stateLoader = recordManager.loadStreamState(item)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
// Do not place initPlayback() in doFinally() because
|
||||
// it restarts playback after destroy()
|
||||
//.doFinally()
|
||||
.subscribe(
|
||||
state -> {
|
||||
queue.setRecovery(queue.getIndex(), state.getProgressTime());
|
||||
initPlayback(queue, repeatMode, playbackSpeed, playbackPitch,
|
||||
playbackSkipSilence, playWhenReady, isMuted);
|
||||
},
|
||||
error -> {
|
||||
if (DEBUG) {
|
||||
error.printStackTrace();
|
||||
}
|
||||
// In case any error we can start playback without history
|
||||
initPlayback(queue, repeatMode, playbackSpeed, playbackPitch,
|
||||
playbackSkipSilence, playWhenReady, isMuted);
|
||||
},
|
||||
() -> {
|
||||
// Completed but not found in history
|
||||
&& isPlaybackResumeEnabled()
|
||||
&& !samePlayQueue
|
||||
&& !queue.isEmpty()
|
||||
&& queue.getItem().getRecoveryPosition() == PlayQueueItem.RECOVERY_UNSET) {
|
||||
stateLoader = recordManager.loadStreamState(queue.getItem())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
// Do not place initPlayback() in doFinally() because
|
||||
// it restarts playback after destroy()
|
||||
//.doFinally()
|
||||
.subscribe(
|
||||
state -> {
|
||||
queue.setRecovery(queue.getIndex(), state.getProgressTime());
|
||||
initPlayback(queue, repeatMode, playbackSpeed, playbackPitch,
|
||||
playbackSkipSilence, playWhenReady, isMuted);
|
||||
},
|
||||
error -> {
|
||||
if (DEBUG) {
|
||||
error.printStackTrace();
|
||||
}
|
||||
// In case any error we can start playback without history
|
||||
initPlayback(queue, repeatMode, playbackSpeed, playbackPitch,
|
||||
playbackSkipSilence, playWhenReady, isMuted);
|
||||
},
|
||||
() -> {
|
||||
// Completed but not found in history
|
||||
initPlayback(queue, repeatMode, playbackSpeed, playbackPitch,
|
||||
playbackSkipSilence, playWhenReady, isMuted);
|
||||
}
|
||||
);
|
||||
databaseUpdateReactor.add(stateLoader);
|
||||
}
|
||||
} else {
|
||||
// Good to go...
|
||||
// In a case of equal PlayQueues we can re-init old one but only when it is disposed
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import android.view.WindowManager;
|
|||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.schabi.newpipe.App;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
|
|
@ -64,25 +65,25 @@ public final class MainPlayer extends Service {
|
|||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
static final String ACTION_CLOSE
|
||||
= "org.schabi.newpipe.player.MainPlayer.CLOSE";
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.CLOSE";
|
||||
static final String ACTION_PLAY_PAUSE
|
||||
= "org.schabi.newpipe.player.MainPlayer.PLAY_PAUSE";
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.PLAY_PAUSE";
|
||||
static final String ACTION_OPEN_CONTROLS
|
||||
= "org.schabi.newpipe.player.MainPlayer.OPEN_CONTROLS";
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.OPEN_CONTROLS";
|
||||
static final String ACTION_REPEAT
|
||||
= "org.schabi.newpipe.player.MainPlayer.REPEAT";
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.REPEAT";
|
||||
static final String ACTION_PLAY_NEXT
|
||||
= "org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_NEXT";
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.ACTION_PLAY_NEXT";
|
||||
static final String ACTION_PLAY_PREVIOUS
|
||||
= "org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_PREVIOUS";
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.ACTION_PLAY_PREVIOUS";
|
||||
static final String ACTION_FAST_REWIND
|
||||
= "org.schabi.newpipe.player.MainPlayer.ACTION_FAST_REWIND";
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.ACTION_FAST_REWIND";
|
||||
static final String ACTION_FAST_FORWARD
|
||||
= "org.schabi.newpipe.player.MainPlayer.ACTION_FAST_FORWARD";
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.ACTION_FAST_FORWARD";
|
||||
static final String ACTION_SHUFFLE
|
||||
= "org.schabi.newpipe.player.MainPlayer.ACTION_SHUFFLE";
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.ACTION_SHUFFLE";
|
||||
public static final String ACTION_RECREATE_NOTIFICATION
|
||||
= "org.schabi.newpipe.player.MainPlayer.ACTION_RECREATE_NOTIFICATION";
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.ACTION_RECREATE_NOTIFICATION";
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Service's LifeCycle
|
||||
|
|
|
|||
|
|
@ -638,12 +638,12 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
|||
case BasePlayer.STATE_COMPLETED:
|
||||
queueControlBinding.controlPlayPause.setClickable(true);
|
||||
queueControlBinding.controlPlayPause.setVisibility(View.VISIBLE);
|
||||
queueControlBinding.progressBar.setVisibility(View.GONE);
|
||||
queueControlBinding.controlProgressBar.setVisibility(View.GONE);
|
||||
break;
|
||||
default:
|
||||
queueControlBinding.controlPlayPause.setClickable(false);
|
||||
queueControlBinding.controlPlayPause.setVisibility(View.INVISIBLE);
|
||||
queueControlBinding.progressBar.setVisibility(View.VISIBLE);
|
||||
queueControlBinding.controlProgressBar.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -505,6 +505,11 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
switch (keyCode) {
|
||||
default:
|
||||
break;
|
||||
case KeyEvent.KEYCODE_SPACE:
|
||||
if (isFullscreen) {
|
||||
onPlayPause();
|
||||
}
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BACK:
|
||||
if (DeviceUtils.isTv(service) && isControlsVisible()) {
|
||||
hideControls(0, 0);
|
||||
|
|
@ -1071,11 +1076,25 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
|
||||
private void animatePlayButtons(final boolean show, final int duration) {
|
||||
animateView(playPauseButton, AnimationUtils.Type.SCALE_AND_ALPHA, show, duration);
|
||||
if (playQueue.getIndex() > 0 || !show) {
|
||||
animateView(playPreviousButton, AnimationUtils.Type.SCALE_AND_ALPHA, show, duration);
|
||||
|
||||
boolean showQueueButtons = show;
|
||||
if (playQueue == null) {
|
||||
showQueueButtons = false;
|
||||
}
|
||||
if (playQueue.getIndex() + 1 < playQueue.getStreams().size() || !show) {
|
||||
animateView(playNextButton, AnimationUtils.Type.SCALE_AND_ALPHA, show, duration);
|
||||
|
||||
if (!showQueueButtons || playQueue.getIndex() > 0) {
|
||||
animateView(
|
||||
playPreviousButton,
|
||||
AnimationUtils.Type.SCALE_AND_ALPHA,
|
||||
showQueueButtons,
|
||||
duration);
|
||||
}
|
||||
if (!showQueueButtons || playQueue.getIndex() + 1 < playQueue.getStreams().size()) {
|
||||
animateView(
|
||||
playNextButton,
|
||||
AnimationUtils.Type.SCALE_AND_ALPHA,
|
||||
showQueueButtons,
|
||||
duration);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@ import android.animation.AnimatorListenerAdapter;
|
|||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.media.AudioFocusRequest;
|
||||
import android.media.AudioManager;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.media.AudioFocusRequestCompat;
|
||||
import androidx.media.AudioManagerCompat;
|
||||
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.analytics.AnalyticsListener;
|
||||
|
|
@ -21,20 +21,17 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, An
|
|||
|
||||
private static final String TAG = "AudioFocusReactor";
|
||||
|
||||
private static final boolean SHOULD_BUILD_FOCUS_REQUEST =
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
|
||||
private static final int DUCK_DURATION = 1500;
|
||||
private static final float DUCK_AUDIO_TO = .2f;
|
||||
|
||||
private static final int FOCUS_GAIN_TYPE = AudioManager.AUDIOFOCUS_GAIN;
|
||||
private static final int FOCUS_GAIN_TYPE = AudioManagerCompat.AUDIOFOCUS_GAIN;
|
||||
private static final int STREAM_TYPE = AudioManager.STREAM_MUSIC;
|
||||
|
||||
private final SimpleExoPlayer player;
|
||||
private final Context context;
|
||||
private final AudioManager audioManager;
|
||||
|
||||
private final AudioFocusRequest request;
|
||||
private final AudioFocusRequestCompat request;
|
||||
|
||||
public AudioReactor(@NonNull final Context context,
|
||||
@NonNull final SimpleExoPlayer player) {
|
||||
|
|
@ -43,15 +40,11 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, An
|
|||
this.audioManager = ContextCompat.getSystemService(context, AudioManager.class);
|
||||
player.addAnalyticsListener(this);
|
||||
|
||||
if (SHOULD_BUILD_FOCUS_REQUEST) {
|
||||
request = new AudioFocusRequest.Builder(FOCUS_GAIN_TYPE)
|
||||
.setAcceptsDelayedFocusGain(true)
|
||||
.setWillPauseWhenDucked(true)
|
||||
.setOnAudioFocusChangeListener(this)
|
||||
.build();
|
||||
} else {
|
||||
request = null;
|
||||
}
|
||||
request = new AudioFocusRequestCompat.Builder(FOCUS_GAIN_TYPE)
|
||||
//.setAcceptsDelayedFocusGain(true)
|
||||
.setWillPauseWhenDucked(true)
|
||||
.setOnAudioFocusChangeListener(this)
|
||||
.build();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
|
|
@ -64,19 +57,11 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, An
|
|||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public void requestAudioFocus() {
|
||||
if (SHOULD_BUILD_FOCUS_REQUEST) {
|
||||
audioManager.requestAudioFocus(request);
|
||||
} else {
|
||||
audioManager.requestAudioFocus(this, STREAM_TYPE, FOCUS_GAIN_TYPE);
|
||||
}
|
||||
AudioManagerCompat.requestAudioFocus(audioManager, request);
|
||||
}
|
||||
|
||||
public void abandonAudioFocus() {
|
||||
if (SHOULD_BUILD_FOCUS_REQUEST) {
|
||||
audioManager.abandonAudioFocusRequest(request);
|
||||
} else {
|
||||
audioManager.abandonAudioFocus(this);
|
||||
}
|
||||
AudioManagerCompat.abandonAudioFocusRequest(audioManager, request);
|
||||
}
|
||||
|
||||
public int getVolume() {
|
||||
|
|
@ -88,7 +73,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, An
|
|||
}
|
||||
|
||||
public int getMaxVolume() {
|
||||
return audioManager.getStreamMaxVolume(STREAM_TYPE);
|
||||
return AudioManagerCompat.getStreamMaxVolume(audioManager, STREAM_TYPE);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -246,10 +246,7 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
|||
|
||||
|
||||
// revoke permissions on the old save path (required for SAF only)
|
||||
final Context context = getContext();
|
||||
if (context == null) {
|
||||
throw new NullPointerException("getContext()");
|
||||
}
|
||||
final Context context = requireContext();
|
||||
|
||||
forgetSAFTree(context, defaultPreferences.getString(key, ""));
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ public final class KioskTranslator {
|
|||
return c.getString(R.string.most_liked);
|
||||
case "conferences":
|
||||
return c.getString(R.string.conferences);
|
||||
case "recent":
|
||||
return c.getString(R.string.recent);
|
||||
case "live":
|
||||
return c.getString(R.string.duration_live);
|
||||
default:
|
||||
return kioskId;
|
||||
}
|
||||
|
|
@ -59,9 +63,12 @@ public final class KioskTranslator {
|
|||
case "Local":
|
||||
return ThemeHelper.resolveResourceIdFromAttr(c, R.attr.ic_kiosk_local);
|
||||
case "Recently added":
|
||||
case "recent":
|
||||
return ThemeHelper.resolveResourceIdFromAttr(c, R.attr.ic_kiosk_recent);
|
||||
case "Most liked":
|
||||
return ThemeHelper.resolveResourceIdFromAttr(c, R.attr.ic_thumb_up);
|
||||
case "live":
|
||||
return ThemeHelper.resolveResourceIdFromAttr(c, R.attr.ic_live_tv);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import java.net.SocketTimeoutException;
|
|||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.channels.ClosedByInterruptException;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
|
|
@ -154,8 +155,8 @@ public class DownloadMission extends Mission {
|
|||
public transient Thread init = null;
|
||||
|
||||
public DownloadMission(String[] urls, StoredFileHelper storage, char kind, Postprocessing psInstance) {
|
||||
if (urls == null) throw new NullPointerException("urls is null");
|
||||
if (urls.length < 1) throw new IllegalArgumentException("urls is empty");
|
||||
if (Objects.requireNonNull(urls).length < 1)
|
||||
throw new IllegalArgumentException("urls array is empty");
|
||||
this.urls = urls;
|
||||
this.kind = kind;
|
||||
this.offsets = new long[urls.length];
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.nio.channels.ClosedByInterruptException;
|
||||
import java.util.Objects;
|
||||
|
||||
import us.shandian.giga.get.DownloadMission.Block;
|
||||
import us.shandian.giga.get.DownloadMission.HttpError;
|
||||
|
|
@ -29,8 +30,7 @@ public class DownloadRunnable extends Thread {
|
|||
private HttpURLConnection mConn;
|
||||
|
||||
DownloadRunnable(DownloadMission mission, int id) {
|
||||
if (mission == null) throw new NullPointerException("mission is null");
|
||||
mMission = mission;
|
||||
mMission = Objects.requireNonNull(mission);
|
||||
mId = id;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import androidx.annotation.NonNull;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
|
||||
import us.shandian.giga.get.DownloadMission;
|
||||
import us.shandian.giga.get.FinishedMission;
|
||||
|
|
@ -140,9 +141,7 @@ public class FinishedMissionStore extends SQLiteOpenHelper {
|
|||
}
|
||||
|
||||
private FinishedMission getMissionFromCursor(Cursor cursor) {
|
||||
if (cursor == null) throw new NullPointerException("cursor is null");
|
||||
|
||||
String kind = cursor.getString(cursor.getColumnIndex(KEY_KIND));
|
||||
String kind = Objects.requireNonNull(cursor).getString(cursor.getColumnIndex(KEY_KIND));
|
||||
if (kind == null || kind.isEmpty()) kind = "?";
|
||||
|
||||
String path = cursor.getString(cursor.getColumnIndexOrThrow(KEY_PATH));
|
||||
|
|
@ -186,15 +185,13 @@ public class FinishedMissionStore extends SQLiteOpenHelper {
|
|||
}
|
||||
|
||||
public void addFinishedMission(DownloadMission downloadMission) {
|
||||
if (downloadMission == null) throw new NullPointerException("downloadMission is null");
|
||||
ContentValues values = getValuesOfMission(Objects.requireNonNull(downloadMission));
|
||||
SQLiteDatabase database = getWritableDatabase();
|
||||
ContentValues values = getValuesOfMission(downloadMission);
|
||||
database.insert(FINISHED_TABLE_NAME, null, values);
|
||||
}
|
||||
|
||||
public void deleteMission(Mission mission) {
|
||||
if (mission == null) throw new NullPointerException("mission is null");
|
||||
String ts = String.valueOf(mission.timestamp);
|
||||
String ts = String.valueOf(Objects.requireNonNull(mission).timestamp);
|
||||
|
||||
SQLiteDatabase database = getWritableDatabase();
|
||||
|
||||
|
|
@ -212,9 +209,8 @@ public class FinishedMissionStore extends SQLiteOpenHelper {
|
|||
}
|
||||
|
||||
public void updateMission(Mission mission) {
|
||||
if (mission == null) throw new NullPointerException("mission is null");
|
||||
ContentValues values = getValuesOfMission(Objects.requireNonNull(mission));
|
||||
SQLiteDatabase database = getWritableDatabase();
|
||||
ContentValues values = getValuesOfMission(mission);
|
||||
String ts = String.valueOf(mission.timestamp);
|
||||
|
||||
int rowsAffected;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import org.schabi.newpipe.streams.io.SharpStream;
|
|||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class CircularFileWriter extends SharpStream {
|
||||
|
||||
|
|
@ -27,9 +28,7 @@ public class CircularFileWriter extends SharpStream {
|
|||
private BufferedFile aux;
|
||||
|
||||
public CircularFileWriter(SharpStream target, File temp, OffsetChecker checker) throws IOException {
|
||||
if (checker == null) {
|
||||
throw new NullPointerException("checker is null");
|
||||
}
|
||||
Objects.requireNonNull(checker);
|
||||
|
||||
if (!temp.exists()) {
|
||||
if (!temp.createNewFile()) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue