diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index d38a631a2..1b2ac6835 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -24,4 +24,14 @@ -dontwarn org.mozilla.javascript.tools.** -dontwarn android.arch.util.paging.CountedDataSource --dontwarn android.arch.persistence.room.paging.LimitOffsetDataSource \ No newline at end of file +-dontwarn android.arch.persistence.room.paging.LimitOffsetDataSource + + +# Rules for icepick. Copy paste from https://github.com/frankiesardo/icepick +-dontwarn icepick.** +-keep class icepick.** { *; } +-keep class **$$Icepick { *; } +-keepclasseswithmembernames class * { + @icepick.* ; +} +-keepnames class * { @icepick.State *;} diff --git a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java index 567bec309..12d1764cc 100644 --- a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java +++ b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java @@ -7,6 +7,7 @@ import android.arch.persistence.room.Index; import android.arch.persistence.room.PrimaryKey; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; +import org.schabi.newpipe.util.Constants; import static org.schabi.newpipe.database.subscription.SubscriptionEntity.SUBSCRIPTION_SERVICE_ID; import static org.schabi.newpipe.database.subscription.SubscriptionEntity.SUBSCRIPTION_TABLE; @@ -28,7 +29,7 @@ public class SubscriptionEntity { private long uid = 0; @ColumnInfo(name = SUBSCRIPTION_SERVICE_ID) - private int serviceId = -1; + private int serviceId = Constants.NO_SERVICE_ID; @ColumnInfo(name = SUBSCRIPTION_URL) private String url; diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 5f954cad2..4bb0c2cca 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -65,6 +65,7 @@ import org.schabi.newpipe.player.PopupVideoPlayer; import org.schabi.newpipe.player.old.PlayVideoActivity; import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.UserAction; +import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.InfoCache; import org.schabi.newpipe.util.ListHelper; @@ -110,7 +111,7 @@ public class VideoDetailFragment extends BaseStateFragment implement private boolean wasRelatedStreamsExpanded = false; @State - protected int serviceId = -1; + protected int serviceId = Constants.NO_SERVICE_ID; @State protected String name; @State 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 34fcaf873..4baf323ff 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 @@ -8,6 +8,7 @@ import android.view.View; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.ListInfo; +import org.schabi.newpipe.util.Constants; import java.util.Queue; @@ -21,7 +22,7 @@ import io.reactivex.schedulers.Schedulers; public abstract class BaseListInfoFragment extends BaseListFragment { @State - protected int serviceId = -1; + protected int serviceId = Constants.NO_SERVICE_ID; @State protected String name; @State diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java index 2903d8a73..90d4d9741 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java @@ -46,6 +46,7 @@ import org.schabi.newpipe.fragments.BackPressable; import org.schabi.newpipe.fragments.list.BaseListFragment; import org.schabi.newpipe.history.HistoryListener; import org.schabi.newpipe.report.UserAction; +import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.AnimationUtils; import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.LayoutManagerSmoothScroller; @@ -100,7 +101,7 @@ public class SearchFragment extends BaseListFragment searchFor(final int serviceId, final String query, final int pageNumber, final String searchLanguage, final SearchEngine.Filter filter) { + checkServiceId(serviceId); return Single.fromCallable(new Callable() { @Override public SearchResult call() throws Exception { @@ -61,6 +68,7 @@ public final class ExtractorHelper { } public static Single getMoreSearchItems(final int serviceId, final String query, final int nextPageNumber, final String searchLanguage, final SearchEngine.Filter filter) { + checkServiceId(serviceId); return searchFor(serviceId, query, nextPageNumber, searchLanguage, filter) .map(new Function() { @Override @@ -71,6 +79,7 @@ public final class ExtractorHelper { } public static Single> suggestionsFor(final int serviceId, final String query, final String searchLanguage) { + checkServiceId(serviceId); return Single.fromCallable(new Callable>() { @Override public List call() throws Exception { @@ -80,6 +89,7 @@ public final class ExtractorHelper { } public static Single getStreamInfo(final int serviceId, final String url, boolean forceLoad) { + checkServiceId(serviceId); return checkCache(forceLoad, serviceId, url, Single.fromCallable(new Callable() { @Override public StreamInfo call() throws Exception { @@ -89,6 +99,7 @@ public final class ExtractorHelper { } public static Single getChannelInfo(final int serviceId, final String url, boolean forceLoad) { + checkServiceId(serviceId); return checkCache(forceLoad, serviceId, url, Single.fromCallable(new Callable() { @Override public ChannelInfo call() throws Exception { @@ -98,6 +109,7 @@ public final class ExtractorHelper { } public static Single getMoreChannelItems(final int serviceId, final String url, final String nextStreamsUrl) { + checkServiceId(serviceId); return Single.fromCallable(new Callable() { @Override public NextItemsResult call() throws Exception { @@ -107,6 +119,7 @@ public final class ExtractorHelper { } public static Single getPlaylistInfo(final int serviceId, final String url, boolean forceLoad) { + checkServiceId(serviceId); return checkCache(forceLoad, serviceId, url, Single.fromCallable(new Callable() { @Override public PlaylistInfo call() throws Exception { @@ -116,6 +129,7 @@ public final class ExtractorHelper { } public static Single getMorePlaylistItems(final int serviceId, final String url, final String nextStreamsUrl) { + checkServiceId(serviceId); return Single.fromCallable(new Callable() { @Override public NextItemsResult call() throws Exception { @@ -133,6 +147,7 @@ public final class ExtractorHelper { * and put the results in the cache. */ private static Single checkCache(boolean forceLoad, int serviceId, String url, Single loadFromNetwork) { + checkServiceId(serviceId); loadFromNetwork = loadFromNetwork.doOnSuccess(new Consumer() { @Override public void accept(@NonNull I i) throws Exception { @@ -157,6 +172,7 @@ public final class ExtractorHelper { * Default implementation uses the {@link InfoCache} to get cached results */ public static Maybe loadFromCache(final int serviceId, final String url) { + checkServiceId(serviceId); return Maybe.defer(new Callable>() { @Override public MaybeSource call() throws Exception { diff --git a/app/src/main/java/org/schabi/newpipe/util/StateSaver.java b/app/src/main/java/org/schabi/newpipe/util/StateSaver.java index bd268abf7..51dceddf3 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StateSaver.java +++ b/app/src/main/java/org/schabi/newpipe/util/StateSaver.java @@ -21,6 +21,7 @@ package org.schabi.newpipe.util; import android.content.Context; +import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -29,6 +30,7 @@ import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; +import org.schabi.newpipe.BuildConfig; import org.schabi.newpipe.MainActivity; import java.io.File; @@ -110,6 +112,7 @@ public class StateSaver { /** * Try to restore the state from memory and disk, using the {@link StateSaver.WriteRead#readFrom(Queue)} from the writeRead. */ + @Nullable private static SavedState tryToRestore(@NonNull SavedState savedState, @NonNull WriteRead writeRead) { if (MainActivity.DEBUG) { Log.d(TAG, "tryToRestore() called with: savedState = [" + savedState + "], writeRead = [" + writeRead + "]"); @@ -117,7 +120,7 @@ public class StateSaver { FileInputStream fileInputStream = null; try { - Queue savedObjects = stateObjectsHolder.remove(savedState.prefixFileSaved); + Queue savedObjects = stateObjectsHolder.remove(savedState.getPrefixFileSaved()); if (savedObjects != null) { writeRead.readFrom(savedObjects); if (MainActivity.DEBUG) { @@ -126,8 +129,13 @@ public class StateSaver { return savedState; } - File file = new File(savedState.pathFileSaved); - if (!file.exists()) return null; + File file = new File(savedState.getPathFileSaved()); + if (!file.exists()) { + if(MainActivity.DEBUG) { + Log.d(TAG, "Cache file doesn't exist: " + file.getAbsolutePath()); + } + return null; + } fileInputStream = new FileInputStream(file); ObjectInputStream inputStream = new ObjectInputStream(fileInputStream); @@ -139,7 +147,7 @@ public class StateSaver { return savedState; } catch (Exception e) { - e.printStackTrace(); + Log.e(TAG, "Failed to restore state", e); } finally { if (fileInputStream != null) { try { @@ -154,10 +162,17 @@ public class StateSaver { /** * @see #tryToSave(boolean, String, String, WriteRead) */ + @Nullable public static SavedState tryToSave(boolean isChangingConfig, @Nullable SavedState savedState, Bundle outState, WriteRead writeRead) { - String currentSavedPrefix = savedState == null || TextUtils.isEmpty(savedState.prefixFileSaved) - ? System.nanoTime() - writeRead.hashCode() + "" - : savedState.prefixFileSaved; + @NonNull + String currentSavedPrefix; + if (savedState == null || TextUtils.isEmpty(savedState.getPrefixFileSaved())) { + // Generate unique prefix + currentSavedPrefix = System.nanoTime() - writeRead.hashCode() + ""; + } else { + // Reuse prefix + currentSavedPrefix = savedState.getPrefixFileSaved(); + } savedState = tryToSave(isChangingConfig, currentSavedPrefix, writeRead.generateSuffix(), writeRead); if (savedState != null) { @@ -173,22 +188,33 @@ public class StateSaver { * to the file with the name of prefixFileName + suffixFileName, in a cache folder got from the {@link #init(Context)}. *

* It checks if the file already exists and if it does, just return the path, so a good way to save is: - *

  • A fixed prefix for the file - *
  • A changing suffix + *
      + *
    • A fixed prefix for the file
    • + *
    • A changing suffix
    • + *
    + * + * @param isChangingConfig + * @param prefixFileName + * @param suffixFileName + * @param writeRead */ + @Nullable private static SavedState tryToSave(boolean isChangingConfig, final String prefixFileName, String suffixFileName, WriteRead writeRead) { if (MainActivity.DEBUG) { Log.d(TAG, "tryToSave() called with: isChangingConfig = [" + isChangingConfig + "], prefixFileName = [" + prefixFileName + "], suffixFileName = [" + suffixFileName + "], writeRead = [" + writeRead + "]"); } - Queue savedObjects = new LinkedList<>(); + LinkedList savedObjects = new LinkedList<>(); writeRead.writeTo(savedObjects); if (isChangingConfig) { if (savedObjects.size() > 0) { stateObjectsHolder.put(prefixFileName, savedObjects); return new SavedState(prefixFileName, ""); - } else return null; + } else { + if(MainActivity.DEBUG) Log.d(TAG, "Nothing to save"); + return null; + } } FileOutputStream fileOutputStream = null; @@ -197,8 +223,12 @@ public class StateSaver { if (!cacheDir.exists()) throw new RuntimeException("Cache dir does not exist > " + cacheDirPath); cacheDir = new File(cacheDir, CACHE_DIR_NAME); if (!cacheDir.exists()) { - boolean mkdirResult = cacheDir.mkdir(); - if (!mkdirResult) return null; + if(!cacheDir.mkdir()) { + if(BuildConfig.DEBUG) { + Log.e(TAG, "Failed to create cache directory " + cacheDir.getAbsolutePath()); + } + return null; + } } if (TextUtils.isEmpty(suffixFileName)) suffixFileName = ".cache"; @@ -214,7 +244,9 @@ public class StateSaver { return name.contains(prefixFileName); } }); - for (File file1 : files) file1.delete(); + for (File fileToDelete : files) { + fileToDelete.delete(); + } } fileOutputStream = new FileOutputStream(file); @@ -223,7 +255,7 @@ public class StateSaver { return new SavedState(prefixFileName, file.getAbsolutePath()); } catch (Exception e) { - e.printStackTrace(); + Log.e(TAG, "Failed to save state", e); } finally { if (fileOutputStream != null) { try { @@ -241,11 +273,11 @@ public class StateSaver { public static void onDestroy(SavedState savedState) { if (MainActivity.DEBUG) Log.d(TAG, "onDestroy() called with: savedState = [" + savedState + "]"); - if (savedState != null && !TextUtils.isEmpty(savedState.pathFileSaved)) { - stateObjectsHolder.remove(savedState.prefixFileSaved); + if (savedState != null && !TextUtils.isEmpty(savedState.getPathFileSaved())) { + stateObjectsHolder.remove(savedState.getPrefixFileSaved()); try { //noinspection ResultOfMethodCallIgnored - new File(savedState.pathFileSaved).delete(); + new File(savedState.getPathFileSaved()).delete(); } catch (Exception ignored) { } } @@ -271,9 +303,12 @@ public class StateSaver { // Inner //////////////////////////////////////////////////////////////////////////*/ + /** + * Information about the saved state on the disk + */ public static class SavedState implements Parcelable { - public String prefixFileSaved; - public String pathFileSaved; + private final String prefixFileSaved; + private final String pathFileSaved; public SavedState(String prefixFileSaved, String pathFileSaved) { this.prefixFileSaved = prefixFileSaved; @@ -287,7 +322,7 @@ public class StateSaver { @Override public String toString() { - return prefixFileSaved + " > " + pathFileSaved; + return getPrefixFileSaved() + " > " + getPathFileSaved(); } @Override @@ -313,6 +348,22 @@ public class StateSaver { return new SavedState[size]; } }; + + /** + * Get the prefix of the saved file + * @return the file prefix + */ + public String getPrefixFileSaved() { + return prefixFileSaved; + } + + /** + * Get the path to the saved file + * @return the path to the saved file + */ + public String getPathFileSaved() { + return pathFileSaved; + } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 8c0fb64a8..ed88a042a 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f3ed0a0af..74bb77845 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Tue Mar 07 14:05:42 CET 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.2.1-bin.zip diff --git a/gradlew b/gradlew index 91a7e269e..cccdd3d51 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,47 +6,6 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" @@ -61,9 +20,49 @@ while [ -h "$PRG" ] ; do fi done SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- +cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" -cd "$SAVED" >&- +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -90,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -114,6 +113,7 @@ fi if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` @@ -154,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index aec99730b..e95643d6a 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +46,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line