From 1164ea52f97247d968e717a6df5381d53dac68dc Mon Sep 17 00:00:00 2001 From: wb9688 Date: Sun, 14 Jun 2020 19:37:45 +0200 Subject: [PATCH] Move Stored(File|Directory)Helper into NewPipe --- .../newpipe/download/DownloadDialog.java | 4 +- .../subscription/SubscriptionFragment.kt | 2 +- .../SubscriptionsImportFragment.java | 2 +- .../services/SubscriptionsExportService.java | 2 +- .../services/SubscriptionsImportService.java | 4 +- .../settings/ContentSettingsFragment.java | 4 +- .../settings/DownloadSettingsFragment.java | 2 +- .../streams}/io/StoredDirectoryHelper.java | 171 +++++++------ .../newpipe/streams}/io/StoredFileHelper.java | 234 +++++++++++------- .../org/schabi/newpipe/util/ZipHelper.java | 2 +- .../us/shandian/giga/get/DownloadMission.java | 2 +- .../java/us/shandian/giga/get/Mission.java | 12 +- .../giga/get/sqlite/FinishedMissionStore.java | 2 +- .../giga/service/DownloadManager.java | 4 +- .../giga/service/DownloadManagerService.java | 4 +- .../giga/ui/adapter/MissionAdapter.java | 2 +- .../giga/ui/fragment/MissionsFragment.java | 2 +- .../java/us/shandian/giga/util/Utility.java | 2 +- 18 files changed, 271 insertions(+), 186 deletions(-) rename app/src/main/java/{us/shandian/giga => org/schabi/newpipe/streams}/io/StoredDirectoryHelper.java (60%) rename app/src/main/java/{us/shandian/giga => org/schabi/newpipe/streams}/io/StoredFileHelper.java (65%) diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index 051e9b752..4cb597b6e 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -49,6 +49,8 @@ import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.SubtitlesStream; import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.settings.NewPipeSettings; +import org.schabi.newpipe.streams.io.StoredDirectoryHelper; +import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.FilePickerActivityHelper; import org.schabi.newpipe.util.FilenameUtils; import org.schabi.newpipe.util.ListHelper; @@ -68,8 +70,6 @@ import icepick.Icepick; import icepick.State; import io.reactivex.rxjava3.disposables.CompositeDisposable; import us.shandian.giga.get.MissionRecoveryInfo; -import us.shandian.giga.io.StoredDirectoryHelper; -import us.shandian.giga.io.StoredFileHelper; import us.shandian.giga.postprocessing.Postprocessing; import us.shandian.giga.service.DownloadManager; import us.shandian.giga.service.DownloadManagerService; diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 981433e83..87b1de1e7 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -57,11 +57,11 @@ import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_VALUE import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE +import org.schabi.newpipe.streams.io.StoredFileHelper import org.schabi.newpipe.util.FilePickerActivityHelper import org.schabi.newpipe.util.NavigationHelper import org.schabi.newpipe.util.OnClickGesture import org.schabi.newpipe.util.ShareUtils -import us.shandian.giga.io.StoredFileHelper import java.text.SimpleDateFormat import java.util.Date import java.util.Locale diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java index 120b81681..27786bd44 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java @@ -34,7 +34,7 @@ import java.util.Collections; import java.util.List; import icepick.State; -import us.shandian.giga.io.StoredFileHelper; +import org.schabi.newpipe.streams.io.StoredFileHelper; import static org.schabi.newpipe.extractor.subscription.SubscriptionExtractor.ContentSource.CHANNEL_URL; import static org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.CHANNEL_URL_MODE; diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/services/SubscriptionsExportService.java b/app/src/main/java/org/schabi/newpipe/local/subscription/services/SubscriptionsExportService.java index cbf7bc95e..063103597 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/services/SubscriptionsExportService.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/services/SubscriptionsExportService.java @@ -32,6 +32,7 @@ import org.schabi.newpipe.R; import org.schabi.newpipe.database.subscription.SubscriptionEntity; import org.schabi.newpipe.extractor.subscription.SubscriptionItem; import org.schabi.newpipe.streams.io.SharpOutputStream; +import org.schabi.newpipe.streams.io.StoredFileHelper; import java.io.IOException; import java.io.OutputStream; @@ -41,7 +42,6 @@ import java.util.List; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.schedulers.Schedulers; -import us.shandian.giga.io.StoredFileHelper; import static org.schabi.newpipe.MainActivity.DEBUG; diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/services/SubscriptionsImportService.java b/app/src/main/java/org/schabi/newpipe/local/subscription/services/SubscriptionsImportService.java index 896775d49..a843ad77c 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/services/SubscriptionsImportService.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/services/SubscriptionsImportService.java @@ -38,6 +38,7 @@ import org.schabi.newpipe.extractor.channel.ChannelInfo; import org.schabi.newpipe.extractor.subscription.SubscriptionItem; import org.schabi.newpipe.ktx.ExceptionUtils; import org.schabi.newpipe.streams.io.SharpInputStream; +import org.schabi.newpipe.streams.io.StoredFileHelper; import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.ExtractorHelper; @@ -52,10 +53,9 @@ import io.reactivex.rxjava3.core.Notification; import io.reactivex.rxjava3.functions.Consumer; import io.reactivex.rxjava3.functions.Function; import io.reactivex.rxjava3.schedulers.Schedulers; -import us.shandian.giga.io.StoredFileHelper; import static org.schabi.newpipe.MainActivity.DEBUG; -import static us.shandian.giga.io.StoredFileHelper.DEFAULT_MIME; +import static org.schabi.newpipe.streams.io.StoredFileHelper.DEFAULT_MIME; public class SubscriptionsImportService extends BaseImportExportService { public static final int CHANNEL_URL_MODE = 0; diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java index e3193ba0f..6e020e368 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -36,8 +36,8 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; -import us.shandian.giga.io.StoredDirectoryHelper; -import us.shandian.giga.io.StoredFileHelper; +import org.schabi.newpipe.streams.io.StoredDirectoryHelper; +import org.schabi.newpipe.streams.io.StoredFileHelper; import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; diff --git a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java index ab513940d..14883092e 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/DownloadSettingsFragment.java @@ -26,7 +26,7 @@ import java.net.URI; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; -import us.shandian.giga.io.StoredDirectoryHelper; +import org.schabi.newpipe.streams.io.StoredDirectoryHelper; import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; diff --git a/app/src/main/java/us/shandian/giga/io/StoredDirectoryHelper.java b/app/src/main/java/org/schabi/newpipe/streams/io/StoredDirectoryHelper.java similarity index 60% rename from app/src/main/java/us/shandian/giga/io/StoredDirectoryHelper.java rename to app/src/main/java/org/schabi/newpipe/streams/io/StoredDirectoryHelper.java index 72193aa1b..5bd03e624 100644 --- a/app/src/main/java/us/shandian/giga/io/StoredDirectoryHelper.java +++ b/app/src/main/java/org/schabi/newpipe/streams/io/StoredDirectoryHelper.java @@ -1,6 +1,5 @@ -package us.shandian.giga.io; +package org.schabi.newpipe.streams.io; -import android.annotation.TargetApi; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -24,10 +23,11 @@ import java.util.Collections; import static android.provider.DocumentsContract.Document.COLUMN_DISPLAY_NAME; import static android.provider.DocumentsContract.Root.COLUMN_DOCUMENT_ID; - +import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; public class StoredDirectoryHelper { - public final static int PERMISSION_FLAGS = Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION; + public static final int PERMISSION_FLAGS = Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION; private File ioTree; private DocumentFile docTree; @@ -36,7 +36,8 @@ public class StoredDirectoryHelper { private final String tag; - public StoredDirectoryHelper(@NonNull Context context, @NonNull Uri path, String tag) throws IOException { + public StoredDirectoryHelper(@NonNull final Context context, @NonNull final Uri path, + final String tag) throws IOException { this.tag = tag; if (ContentResolver.SCHEME_FILE.equalsIgnoreCase(path.getScheme())) { @@ -48,51 +49,49 @@ public class StoredDirectoryHelper { try { this.context.getContentResolver().takePersistableUriPermission(path, PERMISSION_FLAGS); - } catch (Exception e) { + } catch (final Exception e) { throw new IOException(e); } - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { throw new IOException("Storage Access Framework with Directory API is not available"); + } this.docTree = DocumentFile.fromTreeUri(context, path); - if (this.docTree == null) + if (this.docTree == null) { throw new IOException("Failed to create the tree from Uri"); + } } - @TargetApi(Build.VERSION_CODES.KITKAT) - public StoredDirectoryHelper(@NonNull URI location, String tag) { - ioTree = new File(location); - this.tag = tag; - } - - public StoredFileHelper createFile(String filename, String mime) { + public StoredFileHelper createFile(final String filename, final String mime) { return createFile(filename, mime, false); } - public StoredFileHelper createUniqueFile(String name, String mime) { - ArrayList matches = new ArrayList<>(); - String[] filename = splitFilename(name); - String lcFilename = filename[0].toLowerCase(); + public StoredFileHelper createUniqueFile(final String name, final String mime) { + final ArrayList matches = new ArrayList<>(); + final String[] filename = splitFilename(name); + final String lcFilename = filename[0].toLowerCase(); if (docTree == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - for (File file : ioTree.listFiles()) + for (final File file : ioTree.listFiles()) { addIfStartWith(matches, lcFilename, file.getName()); + } } else { // warning: SAF file listing is very slow - Uri docTreeChildren = DocumentsContract.buildChildDocumentsUriUsingTree( - docTree.getUri(), DocumentsContract.getDocumentId(docTree.getUri()) - ); + final Uri docTreeChildren = DocumentsContract.buildChildDocumentsUriUsingTree( + docTree.getUri(), DocumentsContract.getDocumentId(docTree.getUri())); - String[] projection = {COLUMN_DISPLAY_NAME}; - String selection = "(LOWER(" + COLUMN_DISPLAY_NAME + ") LIKE ?%"; - ContentResolver cr = context.getContentResolver(); + final String[] projection = new String[]{COLUMN_DISPLAY_NAME}; + final String selection = "(LOWER(" + COLUMN_DISPLAY_NAME + ") LIKE ?%"; + final ContentResolver cr = context.getContentResolver(); - try (Cursor cursor = cr.query(docTreeChildren, projection, selection, new String[]{lcFilename}, null)) { + try (Cursor cursor = cr.query(docTreeChildren, projection, selection, + new String[]{lcFilename}, null)) { if (cursor != null) { - while (cursor.moveToNext()) + while (cursor.moveToNext()) { addIfStartWith(matches, lcFilename, cursor.getString(0)); + } } } } @@ -102,7 +101,7 @@ public class StoredDirectoryHelper { } else { // check if the filename is in use String lcName = name.toLowerCase(); - for (String testName : matches) { + for (final String testName : matches) { if (testName.equals(lcName)) { lcName = null; break; @@ -110,28 +109,34 @@ public class StoredDirectoryHelper { } // check if not in use - if (lcName != null) return createFile(name, mime, true); + if (lcName != null) { + return createFile(name, mime, true); + } } Collections.sort(matches, String::compareTo); for (int i = 1; i < 1000; i++) { - if (Collections.binarySearch(matches, makeFileName(lcFilename, i, filename[1])) < 0) + if (Collections.binarySearch(matches, makeFileName(lcFilename, i, filename[1])) < 0) { return createFile(makeFileName(filename[0], i, filename[1]), mime, true); + } } - return createFile(String.valueOf(System.currentTimeMillis()).concat(filename[1]), mime, false); + return createFile(String.valueOf(System.currentTimeMillis()).concat(filename[1]), mime, + false); } - private StoredFileHelper createFile(String filename, String mime, boolean safe) { - StoredFileHelper storage; + private StoredFileHelper createFile(final String filename, final String mime, + final boolean safe) { + final StoredFileHelper storage; try { - if (docTree == null) + if (docTree == null) { storage = new StoredFileHelper(ioTree, filename, mime); - else + } else { storage = new StoredFileHelper(context, docTree, filename, mime, safe); - } catch (IOException e) { + } + } catch (final IOException e) { return null; } @@ -149,7 +154,7 @@ public class StoredDirectoryHelper { } /** - * Indicates whatever if is possible access using the {@code java.io} API + * Indicates whether it's using the {@code java.io} API. * * @return {@code true} for Java I/O API, otherwise, {@code false} for Storage Access Framework */ @@ -172,7 +177,9 @@ public class StoredDirectoryHelper { return ioTree.exists() || ioTree.mkdirs(); } - if (docTree.exists()) return true; + if (docTree.exists()) { + return true; + } try { DocumentFile parent; @@ -180,14 +187,18 @@ public class StoredDirectoryHelper { while (true) { parent = docTree.getParentFile(); - if (parent == null || child == null) break; - if (parent.exists()) return true; + if (parent == null || child == null) { + break; + } + if (parent.exists()) { + return true; + } parent.createDirectory(child); - child = parent.getName();// for the next iteration + child = parent.getName(); // for the next iteration } - } catch (Exception e) { + } catch (final Exception ignored) { // no more parent directories or unsupported by the storage provider } @@ -198,13 +209,13 @@ public class StoredDirectoryHelper { return tag; } - public Uri findFile(String filename) { + public Uri findFile(final String filename) { if (docTree == null) { - File res = new File(ioTree, filename); + final File res = new File(ioTree, filename); return res.exists() ? Uri.fromFile(res) : null; } - DocumentFile res = findFileSAFHelper(context, docTree, filename); + final DocumentFile res = findFileSAFHelper(context, docTree, filename); return res == null ? null : res.getUri(); } @@ -218,72 +229,82 @@ public class StoredDirectoryHelper { return (docTree == null ? Uri.fromFile(ioTree) : docTree.getUri()).toString(); } - //////////////////// // Utils /////////////////// - private static void addIfStartWith(ArrayList list, @NonNull String base, String str) { - if (str == null || str.isEmpty()) return; - str = str.toLowerCase(); - if (str.startsWith(base)) list.add(str); + private static void addIfStartWith(final ArrayList list, @NonNull final String base, + final String str) { + if (isNullOrEmpty(str)) { + return; + } + final String lowerStr = str.toLowerCase(); + if (lowerStr.startsWith(base)) { + list.add(lowerStr); + } } - private static String[] splitFilename(@NonNull String filename) { - int dotIndex = filename.lastIndexOf('.'); + private static String[] splitFilename(@NonNull final String filename) { + final int dotIndex = filename.lastIndexOf('.'); - if (dotIndex < 0 || (dotIndex == filename.length() - 1)) + if (dotIndex < 0 || (dotIndex == filename.length() - 1)) { return new String[]{filename, ""}; + } return new String[]{filename.substring(0, dotIndex), filename.substring(dotIndex)}; } - private static String makeFileName(String name, int idx, String ext) { + private static String makeFileName(final String name, final int idx, final String ext) { return name.concat(" (").concat(String.valueOf(idx)).concat(")").concat(ext); } /** - * Fast (but not enough) file/directory finder under the storage access framework + * Fast (but not enough) file/directory finder under the storage access framework. * * @param context The context * @param tree Directory where search * @param filename Target filename * @return A {@link DocumentFile} contain the reference, otherwise, null */ - static DocumentFile findFileSAFHelper(@Nullable Context context, DocumentFile tree, String filename) { + static DocumentFile findFileSAFHelper(@Nullable final Context context, final DocumentFile tree, + final String filename) { if (context == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - return tree.findFile(filename);// warning: this is very slow + return tree.findFile(filename); // warning: this is very slow } - if (!tree.canRead()) return null;// missing read permission + if (!tree.canRead()) { + return null; // missing read permission + } final int name = 0; final int documentId = 1; // LOWER() SQL function is not supported - String selection = COLUMN_DISPLAY_NAME + " = ?"; - //String selection = COLUMN_DISPLAY_NAME + " LIKE ?%"; + final String selection = COLUMN_DISPLAY_NAME + " = ?"; + //final String selection = COLUMN_DISPLAY_NAME + " LIKE ?%"; - Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree( - tree.getUri(), DocumentsContract.getDocumentId(tree.getUri()) - ); - String[] projection = {COLUMN_DISPLAY_NAME, COLUMN_DOCUMENT_ID}; - ContentResolver contentResolver = context.getContentResolver(); + final Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(tree.getUri(), + DocumentsContract.getDocumentId(tree.getUri())); + final String[] projection = {COLUMN_DISPLAY_NAME, COLUMN_DOCUMENT_ID}; + final ContentResolver contentResolver = context.getContentResolver(); - filename = filename.toLowerCase(); + final String lowerFilename = filename.toLowerCase(); - try (Cursor cursor = contentResolver.query(childrenUri, projection, selection, new String[]{filename}, null)) { - if (cursor == null) return null; + try (Cursor cursor = contentResolver.query(childrenUri, projection, selection, + new String[]{lowerFilename}, null)) { + if (cursor == null) { + return null; + } while (cursor.moveToNext()) { - if (cursor.isNull(name) || !cursor.getString(name).toLowerCase().startsWith(filename)) + if (cursor.isNull(name) + || !cursor.getString(name).toLowerCase().startsWith(lowerFilename)) { continue; + } - return DocumentFile.fromSingleUri( - context, DocumentsContract.buildDocumentUriUsingTree( - tree.getUri(), cursor.getString(documentId) - ) - ); + return DocumentFile.fromSingleUri(context, + DocumentsContract.buildDocumentUriUsingTree(tree.getUri(), + cursor.getString(documentId))); } } diff --git a/app/src/main/java/us/shandian/giga/io/StoredFileHelper.java b/app/src/main/java/org/schabi/newpipe/streams/io/StoredFileHelper.java similarity index 65% rename from app/src/main/java/us/shandian/giga/io/StoredFileHelper.java rename to app/src/main/java/org/schabi/newpipe/streams/io/StoredFileHelper.java index 4a9c170eb..d2b694247 100644 --- a/app/src/main/java/us/shandian/giga/io/StoredFileHelper.java +++ b/app/src/main/java/org/schabi/newpipe/streams/io/StoredFileHelper.java @@ -1,4 +1,4 @@ -package us.shandian.giga.io; +package org.schabi.newpipe.streams.io; import android.annotation.TargetApi; import android.content.ContentResolver; @@ -16,7 +16,6 @@ import androidx.documentfile.provider.DocumentFile; import com.nononsenseapps.filepicker.Utils; import org.schabi.newpipe.settings.NewPipeSettings; -import org.schabi.newpipe.streams.io.SharpStream; import org.schabi.newpipe.util.FilePickerActivityHelper; import java.io.File; @@ -24,6 +23,9 @@ import java.io.IOException; import java.io.Serializable; import java.net.URI; +import us.shandian.giga.io.FileStream; +import us.shandian.giga.io.FileStreamSAF; + public class StoredFileHelper implements Serializable { private static final long serialVersionUID = 0L; public static final String DEFAULT_MIME = "application/octet-stream"; @@ -54,27 +56,34 @@ public class StoredFileHelper implements Serializable { this.srcType = mime; } - public StoredFileHelper(@Nullable Uri parent, String filename, String mime, String tag) { - this.source = null;// this instance will be "invalid" see invalidate()/isInvalid() methods + public StoredFileHelper(@Nullable final Uri parent, final String filename, final String mime, + final String tag) { + this.source = null; // this instance will be "invalid" see invalidate()/isInvalid() methods this.srcName = filename; this.srcType = mime == null ? DEFAULT_MIME : mime; - if (parent != null) this.sourceTree = parent.toString(); + if (parent != null) { + this.sourceTree = parent.toString(); + } this.tag = tag; } @TargetApi(Build.VERSION_CODES.LOLLIPOP) - StoredFileHelper(@Nullable Context context, DocumentFile tree, String filename, String mime, boolean safe) throws IOException { + StoredFileHelper(@Nullable final Context context, final DocumentFile tree, + final String filename, final String mime, final boolean safe) + throws IOException { this.docTree = tree; this.context = context; - DocumentFile res; + final DocumentFile res; if (safe) { // no conflicts (the filename is not in use) res = this.docTree.createFile(mime, filename); - if (res == null) throw new IOException("Cannot create the file"); + if (res == null) { + throw new IOException("Cannot create the file"); + } } else { res = createSAF(context, mime, filename); } @@ -88,15 +97,19 @@ public class StoredFileHelper implements Serializable { this.srcType = this.docFile.getType(); } - StoredFileHelper(File location, String filename, String mime) throws IOException { + StoredFileHelper(final File location, final String filename, final String mime) + throws IOException { this.ioFile = new File(location, filename); if (this.ioFile.exists()) { - if (!this.ioFile.isFile() && !this.ioFile.delete()) - throw new IOException("The filename is already in use by non-file entity and cannot overwrite it"); + if (!this.ioFile.isFile() && !this.ioFile.delete()) { + throw new IOException("The filename is already in use by non-file entity " + + "and cannot overwrite it"); + } } else { - if (!this.ioFile.createNewFile()) + if (!this.ioFile.createNewFile()) { throw new IOException("Cannot create the file"); + } } this.source = Uri.fromFile(this.ioFile).toString(); @@ -107,16 +120,20 @@ public class StoredFileHelper implements Serializable { } @TargetApi(Build.VERSION_CODES.KITKAT) - public StoredFileHelper(Context context, @Nullable Uri parent, @NonNull Uri path, String tag) throws IOException { + public StoredFileHelper(final Context context, @Nullable final Uri parent, + @NonNull final Uri path, final String tag) throws IOException { this.tag = tag; this.source = path.toString(); - if (path.getScheme() == null || path.getScheme().equalsIgnoreCase(ContentResolver.SCHEME_FILE)) { + if (path.getScheme() == null + || path.getScheme().equalsIgnoreCase(ContentResolver.SCHEME_FILE)) { this.ioFile = new File(URI.create(this.source)); } else { - DocumentFile file = DocumentFile.fromSingleUri(context, path); + final DocumentFile file = DocumentFile.fromSingleUri(context, path); - if (file == null) throw new RuntimeException("SAF not available"); + if (file == null) { + throw new RuntimeException("SAF not available"); + } this.context = context; @@ -130,8 +147,9 @@ public class StoredFileHelper implements Serializable { } if (parent != null) { - if (!ContentResolver.SCHEME_FILE.equals(parent.getScheme())) + if (!ContentResolver.SCHEME_FILE.equals(parent.getScheme())) { this.docTree = DocumentFile.fromTreeUri(context, parent); + } this.sourceTree = parent.toString(); } @@ -141,37 +159,45 @@ public class StoredFileHelper implements Serializable { } - public static StoredFileHelper deserialize(@NonNull StoredFileHelper storage, Context context) throws IOException { - Uri treeUri = storage.sourceTree == null ? null : Uri.parse(storage.sourceTree); + public static StoredFileHelper deserialize(@NonNull final StoredFileHelper storage, + final Context context) throws IOException { + final Uri treeUri = storage.sourceTree == null ? null : Uri.parse(storage.sourceTree); - if (storage.isInvalid()) + if (storage.isInvalid()) { return new StoredFileHelper(treeUri, storage.srcName, storage.srcType, storage.tag); + } - StoredFileHelper instance = new StoredFileHelper(context, treeUri, Uri.parse(storage.source), storage.tag); + final StoredFileHelper instance = new StoredFileHelper(context, treeUri, + Uri.parse(storage.source), storage.tag); // under SAF, if the target document is deleted, conserve the filename and mime - if (instance.srcName == null) instance.srcName = storage.srcName; - if (instance.srcType == null) instance.srcType = storage.srcType; + if (instance.srcName == null) { + instance.srcName = storage.srcName; + } + if (instance.srcType == null) { + instance.srcType = storage.srcType; + } return instance; } public SharpStream getStream() throws IOException { - invalid(); + assertValid(); - if (docFile == null) + if (docFile == null) { return new FileStream(ioFile); - else + } else { return new FileStreamSAF(context.getContentResolver(), docFile.getUri()); + } } /** - * Indicates whatever if is possible access using the {@code java.io} API + * Indicates whether it's using the {@code java.io} API. * * @return {@code true} for Java I/O API, otherwise, {@code false} for Storage Access Framework */ public boolean isDirect() { - invalid(); + assertValid(); return docFile == null; } @@ -181,19 +207,19 @@ public class StoredFileHelper implements Serializable { } public Uri getUri() { - invalid(); + assertValid(); return docFile == null ? Uri.fromFile(ioFile) : docFile.getUri(); } public Uri getParentUri() { - invalid(); + assertValid(); return sourceTree == null ? null : Uri.parse(sourceTree); } public void truncate() throws IOException { - invalid(); + assertValid(); try (SharpStream fs = getStream()) { fs.setLength(0); @@ -201,16 +227,20 @@ public class StoredFileHelper implements Serializable { } public boolean delete() { - if (source == null) return true; - if (docFile == null) return ioFile.delete(); + if (source == null) { + return true; + } + if (docFile == null) { + return ioFile.delete(); + } - - boolean res = docFile.delete(); + final boolean res = docFile.delete(); try { - int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION; + final int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION; context.getContentResolver().releasePersistableUriPermission(docFile.getUri(), flags); - } catch (Exception ex) { + } catch (final Exception ex) { // nothing to do } @@ -218,31 +248,35 @@ public class StoredFileHelper implements Serializable { } public long length() { - invalid(); + assertValid(); return docFile == null ? ioFile.length() : docFile.length(); } public boolean canWrite() { - if (source == null) return false; + if (source == null) { + return false; + } return docFile == null ? ioFile.canWrite() : docFile.canWrite(); } public String getName() { - if (source == null) + if (source == null) { return srcName; - else if (docFile == null) + } else if (docFile == null) { return ioFile.getName(); + } - String name = docFile.getName(); + final String name = docFile.getName(); return name == null ? srcName : name; } public String getType() { - if (source == null || docFile == null) + if (source == null || docFile == null) { return srcType; + } - String type = docFile.getType(); + final String type = docFile.getType(); return type == null ? srcType : type; } @@ -251,34 +285,41 @@ public class StoredFileHelper implements Serializable { } public boolean existsAsFile() { - if (source == null) return false; + if (source == null) { + return false; + } // WARNING: DocumentFile.exists() and DocumentFile.isFile() methods are slow - boolean exists = docFile == null ? ioFile.exists() : docFile.exists(); - boolean isFile = docFile == null ? ioFile.isFile() : docFile.isFile();// ¿docFile.isVirtual() means is no-physical? + final boolean exists = docFile == null ? ioFile.exists() : docFile.exists(); + // ¿docFile.isVirtual() means is no-physical? + final boolean isFile = docFile == null ? ioFile.isFile() : docFile.isFile(); return exists && isFile; } public boolean create() { - invalid(); - boolean result; + assertValid(); + final boolean result; if (docFile == null) { try { result = ioFile.createNewFile(); - } catch (IOException e) { + } catch (final IOException e) { return false; } } else if (docTree == null) { result = false; } else { - if (!docTree.canRead() || !docTree.canWrite()) return false; + if (!docTree.canRead() || !docTree.canWrite()) { + return false; + } try { docFile = createSAF(context, srcType, srcName); - if (docFile.getName() == null) return false; + if (docFile.getName() == null) { + return false; + } result = true; - } catch (IOException e) { + } catch (final IOException e) { return false; } } @@ -293,7 +334,9 @@ public class StoredFileHelper implements Serializable { } public void invalidate() { - if (source == null) return; + if (source == null) { + return; + } srcName = getName(); srcType = getType(); @@ -306,81 +349,102 @@ public class StoredFileHelper implements Serializable { context = null; } - public boolean equals(StoredFileHelper storage) { - if (this == storage) return true; + public boolean equals(final StoredFileHelper storage) { + if (this == storage) { + return true; + } // note: do not compare tags, files can have the same parent folder //if (stringMismatch(this.tag, storage.tag)) return false; - if (stringMismatch(getLowerCase(this.sourceTree), getLowerCase(this.sourceTree))) + if (stringMismatch(getLowerCase(this.sourceTree), getLowerCase(this.sourceTree))) { return false; - - if (this.isInvalid() || storage.isInvalid()) { - if (this.srcName == null || storage.srcName == null || this.srcType == null || storage.srcType == null) return false; - return this.srcName.equalsIgnoreCase(storage.srcName) && this.srcType.equalsIgnoreCase(storage.srcType); } - if (this.isDirect() != storage.isDirect()) return false; + if (this.isInvalid() || storage.isInvalid()) { + if (this.srcName == null || storage.srcName == null || this.srcType == null + || storage.srcType == null) { + return false; + } - if (this.isDirect()) + return this.srcName.equalsIgnoreCase(storage.srcName) + && this.srcType.equalsIgnoreCase(storage.srcType); + } + + if (this.isDirect() != storage.isDirect()) { + return false; + } + + if (this.isDirect()) { return this.ioFile.getPath().equalsIgnoreCase(storage.ioFile.getPath()); + } - return DocumentsContract.getDocumentId( - this.docFile.getUri() - ).equalsIgnoreCase(DocumentsContract.getDocumentId( - storage.docFile.getUri() - )); + return DocumentsContract.getDocumentId(this.docFile.getUri()) + .equalsIgnoreCase(DocumentsContract.getDocumentId(storage.docFile.getUri())); } @NonNull @Override public String toString() { - if (source == null) + if (source == null) { return "[Invalid state] name=" + srcName + " type=" + srcType + " tag=" + tag; - else - return "sourceFile=" + source + " treeSource=" + (sourceTree == null ? "" : sourceTree) + " tag=" + tag; + } else { + return "sourceFile=" + source + " treeSource=" + (sourceTree == null ? "" : sourceTree) + + " tag=" + tag; + } } - private void invalid() { - if (source == null) + private void assertValid() { + if (source == null) { throw new IllegalStateException("In invalid state"); + } } private void takePermissionSAF() throws IOException { try { - context.getContentResolver().takePersistableUriPermission(docFile.getUri(), StoredDirectoryHelper.PERMISSION_FLAGS); - } catch (Exception e) { - if (docFile.getName() == null) throw new IOException(e); + context.getContentResolver().takePersistableUriPermission(docFile.getUri(), + StoredDirectoryHelper.PERMISSION_FLAGS); + } catch (final Exception e) { + if (docFile.getName() == null) { + throw new IOException(e); + } } } @NonNull - private DocumentFile createSAF(@Nullable Context context, String mime, String filename) - throws IOException { - DocumentFile res = StoredDirectoryHelper.findFileSAFHelper(context, docTree, filename); + private DocumentFile createSAF(@Nullable final Context ctx, final String mime, + final String filename) throws IOException { + DocumentFile res = StoredDirectoryHelper.findFileSAFHelper(ctx, docTree, filename); if (res != null && res.exists() && res.isDirectory()) { - if (!res.delete()) + if (!res.delete()) { throw new IOException("Directory with the same name found but cannot delete"); + } res = null; } if (res == null) { res = this.docTree.createFile(srcType == null ? DEFAULT_MIME : mime, filename); - if (res == null) throw new IOException("Cannot create the file"); + if (res == null) { + throw new IOException("Cannot create the file"); + } } return res; } - private String getLowerCase(String str) { + private String getLowerCase(final String str) { return str == null ? null : str.toLowerCase(); } - private boolean stringMismatch(String str1, String str2) { - if (str1 == null && str2 == null) return false; - if ((str1 == null) != (str2 == null)) return true; + private boolean stringMismatch(final String str1, final String str2) { + if (str1 == null && str2 == null) { + return false; + } + if ((str1 == null) != (str2 == null)) { + return true; + } return !str1.equals(str2); } diff --git a/app/src/main/java/org/schabi/newpipe/util/ZipHelper.java b/app/src/main/java/org/schabi/newpipe/util/ZipHelper.java index 32964490e..bc08e6197 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ZipHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ZipHelper.java @@ -11,7 +11,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; -import us.shandian.giga.io.StoredFileHelper; +import org.schabi.newpipe.streams.io.StoredFileHelper; /** * Created by Christian Schabesberger on 28.01.18. diff --git a/app/src/main/java/us/shandian/giga/get/DownloadMission.java b/app/src/main/java/us/shandian/giga/get/DownloadMission.java index 2b3faa3e0..628058f55 100644 --- a/app/src/main/java/us/shandian/giga/get/DownloadMission.java +++ b/app/src/main/java/us/shandian/giga/get/DownloadMission.java @@ -26,7 +26,7 @@ import java.util.Objects; import javax.net.ssl.SSLException; -import us.shandian.giga.io.StoredFileHelper; +import org.schabi.newpipe.streams.io.StoredFileHelper; import us.shandian.giga.postprocessing.Postprocessing; import us.shandian.giga.service.DownloadManagerService; import us.shandian.giga.util.Utility; diff --git a/app/src/main/java/us/shandian/giga/get/Mission.java b/app/src/main/java/us/shandian/giga/get/Mission.java index ecb0eaebd..77b9c1e33 100644 --- a/app/src/main/java/us/shandian/giga/get/Mission.java +++ b/app/src/main/java/us/shandian/giga/get/Mission.java @@ -5,7 +5,7 @@ import androidx.annotation.NonNull; import java.io.Serializable; import java.util.Calendar; -import us.shandian.giga.io.StoredFileHelper; +import org.schabi.newpipe.streams.io.StoredFileHelper; public abstract class Mission implements Serializable { private static final long serialVersionUID = 1L;// last bump: 27 march 2019 @@ -25,6 +25,10 @@ public abstract class Mission implements Serializable { */ public long timestamp; + public long getTimestamp() { + return timestamp; + } + /** * pre-defined content type */ @@ -35,10 +39,6 @@ public abstract class Mission implements Serializable { */ public StoredFileHelper storage; - public long getTimestamp() { - return timestamp; - } - /** * Delete the downloaded file * @@ -57,7 +57,7 @@ public abstract class Mission implements Serializable { @NonNull @Override public String toString() { - Calendar calendar = Calendar.getInstance(); + final Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(timestamp); return "[" + calendar.getTime().toString() + "] " + (storage.isInvalid() ? storage.getName() : storage.getUri()); } diff --git a/app/src/main/java/us/shandian/giga/get/sqlite/FinishedMissionStore.java b/app/src/main/java/us/shandian/giga/get/sqlite/FinishedMissionStore.java index 15c45c6fd..704385212 100644 --- a/app/src/main/java/us/shandian/giga/get/sqlite/FinishedMissionStore.java +++ b/app/src/main/java/us/shandian/giga/get/sqlite/FinishedMissionStore.java @@ -17,7 +17,7 @@ import java.util.Objects; import us.shandian.giga.get.DownloadMission; import us.shandian.giga.get.FinishedMission; import us.shandian.giga.get.Mission; -import us.shandian.giga.io.StoredFileHelper; +import org.schabi.newpipe.streams.io.StoredFileHelper; /** * SQLite helper to store finished {@link us.shandian.giga.get.FinishedMission}'s diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManager.java b/app/src/main/java/us/shandian/giga/service/DownloadManager.java index 8359fce9a..283517e01 100644 --- a/app/src/main/java/us/shandian/giga/service/DownloadManager.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManager.java @@ -19,8 +19,8 @@ import us.shandian.giga.get.DownloadMission; import us.shandian.giga.get.FinishedMission; import us.shandian.giga.get.Mission; import us.shandian.giga.get.sqlite.FinishedMissionStore; -import us.shandian.giga.io.StoredDirectoryHelper; -import us.shandian.giga.io.StoredFileHelper; +import org.schabi.newpipe.streams.io.StoredDirectoryHelper; +import org.schabi.newpipe.streams.io.StoredFileHelper; import us.shandian.giga.util.Utility; import static org.schabi.newpipe.BuildConfig.DEBUG; diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java index 568c3497a..52c28828d 100755 --- a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java @@ -47,8 +47,8 @@ import java.util.ArrayList; import us.shandian.giga.get.DownloadMission; import us.shandian.giga.get.MissionRecoveryInfo; -import us.shandian.giga.io.StoredDirectoryHelper; -import us.shandian.giga.io.StoredFileHelper; +import org.schabi.newpipe.streams.io.StoredDirectoryHelper; +import org.schabi.newpipe.streams.io.StoredFileHelper; import us.shandian.giga.postprocessing.Postprocessing; import us.shandian.giga.service.DownloadManager.NetworkState; diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java index 41a254b49..45ee290f6 100644 --- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java +++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java @@ -61,7 +61,7 @@ import us.shandian.giga.get.DownloadMission; import us.shandian.giga.get.FinishedMission; import us.shandian.giga.get.Mission; import us.shandian.giga.get.MissionRecoveryInfo; -import us.shandian.giga.io.StoredFileHelper; +import org.schabi.newpipe.streams.io.StoredFileHelper; import us.shandian.giga.service.DownloadManager; import us.shandian.giga.service.DownloadManagerService; import us.shandian.giga.ui.common.Deleter; diff --git a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java index bfb7926dd..ac3579b79 100644 --- a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java +++ b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java @@ -36,7 +36,7 @@ import java.io.File; import java.io.IOException; import us.shandian.giga.get.DownloadMission; -import us.shandian.giga.io.StoredFileHelper; +import org.schabi.newpipe.streams.io.StoredFileHelper; import us.shandian.giga.service.DownloadManager; import us.shandian.giga.service.DownloadManagerService; import us.shandian.giga.service.DownloadManagerService.DownloadManagerBinder; diff --git a/app/src/main/java/us/shandian/giga/util/Utility.java b/app/src/main/java/us/shandian/giga/util/Utility.java index ab584f0e6..9e6787d5d 100644 --- a/app/src/main/java/us/shandian/giga/util/Utility.java +++ b/app/src/main/java/us/shandian/giga/util/Utility.java @@ -29,7 +29,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Locale; -import us.shandian.giga.io.StoredFileHelper; +import org.schabi.newpipe.streams.io.StoredFileHelper; public class Utility {