mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 15:23:00 +00:00 
			
		
		
		
	Use Path in the download helper classes.
This commit is contained in:
		 Isira Seneviratne
					Isira Seneviratne
				
			
				
					committed by
					
						 TobiGr
						TobiGr
					
				
			
			
				
	
			
			
			 TobiGr
						TobiGr
					
				
			
						parent
						
							2cb973f150
						
					
				
				
					commit
					6df808f266
				
			| @@ -6,6 +6,7 @@ import android.content.Intent; | |||||||
| import android.database.Cursor; | import android.database.Cursor; | ||||||
| import android.net.Uri; | import android.net.Uri; | ||||||
| import android.provider.DocumentsContract; | import android.provider.DocumentsContract; | ||||||
|  | import android.util.Log; | ||||||
|  |  | ||||||
| import androidx.annotation.NonNull; | import androidx.annotation.NonNull; | ||||||
| import androidx.annotation.Nullable; | import androidx.annotation.Nullable; | ||||||
| @@ -14,21 +15,27 @@ import androidx.documentfile.provider.DocumentFile; | |||||||
| import org.schabi.newpipe.settings.NewPipeSettings; | import org.schabi.newpipe.settings.NewPipeSettings; | ||||||
| import org.schabi.newpipe.util.FilePickerActivityHelper; | import org.schabi.newpipe.util.FilePickerActivityHelper; | ||||||
|  |  | ||||||
| import java.io.File; |  | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.net.URI; | import java.net.URI; | ||||||
|  | import java.nio.file.Files; | ||||||
|  | import java.nio.file.Path; | ||||||
|  | import java.nio.file.Paths; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | import java.util.stream.Stream; | ||||||
|  |  | ||||||
| import static android.provider.DocumentsContract.Document.COLUMN_DISPLAY_NAME; | import static android.provider.DocumentsContract.Document.COLUMN_DISPLAY_NAME; | ||||||
| import static android.provider.DocumentsContract.Root.COLUMN_DOCUMENT_ID; | import static android.provider.DocumentsContract.Root.COLUMN_DOCUMENT_ID; | ||||||
| import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; | import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; | ||||||
|  |  | ||||||
| public class StoredDirectoryHelper { | public class StoredDirectoryHelper { | ||||||
|  |     private static final String TAG = StoredDirectoryHelper.class.getSimpleName(); | ||||||
|     public static final int PERMISSION_FLAGS = Intent.FLAG_GRANT_READ_URI_PERMISSION |     public static final int PERMISSION_FLAGS = Intent.FLAG_GRANT_READ_URI_PERMISSION | ||||||
|             | Intent.FLAG_GRANT_WRITE_URI_PERMISSION; |             | Intent.FLAG_GRANT_WRITE_URI_PERMISSION; | ||||||
|  |  | ||||||
|     private File ioTree; |     private Path ioTree; | ||||||
|     private DocumentFile docTree; |     private DocumentFile docTree; | ||||||
|  |  | ||||||
|     private Context context; |     private Context context; | ||||||
| @@ -40,7 +47,7 @@ public class StoredDirectoryHelper { | |||||||
|         this.tag = tag; |         this.tag = tag; | ||||||
|  |  | ||||||
|         if (ContentResolver.SCHEME_FILE.equalsIgnoreCase(path.getScheme())) { |         if (ContentResolver.SCHEME_FILE.equalsIgnoreCase(path.getScheme())) { | ||||||
|             this.ioTree = new File(URI.create(path.toString())); |             ioTree = Paths.get(URI.create(path.toString())); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -64,13 +71,17 @@ public class StoredDirectoryHelper { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public StoredFileHelper createUniqueFile(final String name, final String mime) { |     public StoredFileHelper createUniqueFile(final String name, final String mime) { | ||||||
|         final ArrayList<String> matches = new ArrayList<>(); |         final List<String> matches = new ArrayList<>(); | ||||||
|         final String[] filename = splitFilename(name); |         final String[] filename = splitFilename(name); | ||||||
|         final String lcFilename = filename[0].toLowerCase(); |         final String lcFileName = filename[0].toLowerCase(); | ||||||
|  |  | ||||||
|         if (docTree == null) { |         if (docTree == null) { | ||||||
|             for (final File file : ioTree.listFiles()) { |             try (Stream<Path> stream = Files.list(ioTree)) { | ||||||
|                 addIfStartWith(matches, lcFilename, file.getName()); |                 matches.addAll(stream.map(path -> path.getFileName().toString().toLowerCase()) | ||||||
|  |                         .filter(fileName -> fileName.startsWith(lcFileName)) | ||||||
|  |                         .collect(Collectors.toList())); | ||||||
|  |             } catch (final IOException e) { | ||||||
|  |                 Log.e(TAG, "Exception while traversing " + ioTree, e); | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             // warning: SAF file listing is very slow |             // warning: SAF file listing is very slow | ||||||
| @@ -82,10 +93,10 @@ public class StoredDirectoryHelper { | |||||||
|             final ContentResolver cr = context.getContentResolver(); |             final ContentResolver cr = context.getContentResolver(); | ||||||
|  |  | ||||||
|             try (Cursor cursor = cr.query(docTreeChildren, projection, selection, |             try (Cursor cursor = cr.query(docTreeChildren, projection, selection, | ||||||
|                     new String[]{lcFilename}, null)) { |                     new String[]{lcFileName}, null)) { | ||||||
|                 if (cursor != null) { |                 if (cursor != null) { | ||||||
|                     while (cursor.moveToNext()) { |                     while (cursor.moveToNext()) { | ||||||
|                         addIfStartWith(matches, lcFilename, cursor.getString(0)); |                         addIfStartWith(matches, lcFileName, cursor.getString(0)); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -112,7 +123,7 @@ public class StoredDirectoryHelper { | |||||||
|         Collections.sort(matches, String::compareTo); |         Collections.sort(matches, String::compareTo); | ||||||
|  |  | ||||||
|         for (int i = 1; i < 1000; i++) { |         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(makeFileName(filename[0], i, filename[1]), mime, true); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -141,11 +152,11 @@ public class StoredDirectoryHelper { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public Uri getUri() { |     public Uri getUri() { | ||||||
|         return docTree == null ? Uri.fromFile(ioTree) : docTree.getUri(); |         return docTree == null ? Uri.fromFile(ioTree.toFile()) : docTree.getUri(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public boolean exists() { |     public boolean exists() { | ||||||
|         return docTree == null ? ioTree.exists() : docTree.exists(); |         return docTree == null ? Files.exists(ioTree) : docTree.exists(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -169,7 +180,9 @@ public class StoredDirectoryHelper { | |||||||
|      */ |      */ | ||||||
|     public boolean mkdirs() { |     public boolean mkdirs() { | ||||||
|         if (docTree == null) { |         if (docTree == null) { | ||||||
|             return ioTree.exists() || ioTree.mkdirs(); |             // TODO: Use Files.createDirectories() when AGP 8.1 is available: | ||||||
|  |             // https://issuetracker.google.com/issues/282544786 | ||||||
|  |             return Files.exists(ioTree) || ioTree.toFile().mkdirs(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (docTree.exists()) { |         if (docTree.exists()) { | ||||||
| @@ -206,8 +219,8 @@ public class StoredDirectoryHelper { | |||||||
|  |  | ||||||
|     public Uri findFile(final String filename) { |     public Uri findFile(final String filename) { | ||||||
|         if (docTree == null) { |         if (docTree == null) { | ||||||
|             final File res = new File(ioTree, filename); |             final Path res = ioTree.resolve(filename); | ||||||
|             return res.exists() ? Uri.fromFile(res) : null; |             return Files.exists(res) ? Uri.fromFile(res.toFile()) : null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final DocumentFile res = findFileSAFHelper(context, docTree, filename); |         final DocumentFile res = findFileSAFHelper(context, docTree, filename); | ||||||
| @@ -215,7 +228,7 @@ public class StoredDirectoryHelper { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public boolean canWrite() { |     public boolean canWrite() { | ||||||
|         return docTree == null ? ioTree.canWrite() : docTree.canWrite(); |         return docTree == null ? Files.isWritable(ioTree) : docTree.canWrite(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -230,14 +243,14 @@ public class StoredDirectoryHelper { | |||||||
|     @NonNull |     @NonNull | ||||||
|     @Override |     @Override | ||||||
|     public String toString() { |     public String toString() { | ||||||
|         return (docTree == null ? Uri.fromFile(ioTree) : docTree.getUri()).toString(); |         return (docTree == null ? Uri.fromFile(ioTree.toFile()) : docTree.getUri()).toString(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     //////////////////// |     //////////////////// | ||||||
|     //      Utils |     //      Utils | ||||||
|     /////////////////// |     /////////////////// | ||||||
|  |  | ||||||
|     private static void addIfStartWith(final ArrayList<String> list, @NonNull final String base, |     private static void addIfStartWith(final List<String> list, @NonNull final String base, | ||||||
|                                        final String str) { |                                        final String str) { | ||||||
|         if (isNullOrEmpty(str)) { |         if (isNullOrEmpty(str)) { | ||||||
|             return; |             return; | ||||||
| @@ -259,7 +272,7 @@ public class StoredDirectoryHelper { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static String makeFileName(final String name, final int idx, final 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); |         return name + "(" + idx + ")" + ext; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|   | |||||||
| @@ -23,6 +23,9 @@ import java.io.File; | |||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.Serializable; | import java.io.Serializable; | ||||||
| import java.net.URI; | import java.net.URI; | ||||||
|  | import java.nio.file.Files; | ||||||
|  | import java.nio.file.Path; | ||||||
|  | import java.nio.file.Paths; | ||||||
|  |  | ||||||
| import us.shandian.giga.io.FileStream; | import us.shandian.giga.io.FileStream; | ||||||
| import us.shandian.giga.io.FileStreamSAF; | import us.shandian.giga.io.FileStreamSAF; | ||||||
| @@ -36,7 +39,7 @@ public class StoredFileHelper implements Serializable { | |||||||
|  |  | ||||||
|     private transient DocumentFile docFile; |     private transient DocumentFile docFile; | ||||||
|     private transient DocumentFile docTree; |     private transient DocumentFile docTree; | ||||||
|     private transient File ioFile; |     private transient Path ioPath; | ||||||
|     private transient Context context; |     private transient Context context; | ||||||
|  |  | ||||||
|     protected String source; |     protected String source; | ||||||
| @@ -49,7 +52,8 @@ public class StoredFileHelper implements Serializable { | |||||||
|  |  | ||||||
|     public StoredFileHelper(final Context context, final Uri uri, final String mime) { |     public StoredFileHelper(final Context context, final Uri uri, final String mime) { | ||||||
|         if (FilePickerActivityHelper.isOwnFileUri(context, uri)) { |         if (FilePickerActivityHelper.isOwnFileUri(context, uri)) { | ||||||
|             ioFile = Utils.getFileForUri(uri); |             final File ioFile = Utils.getFileForUri(uri); | ||||||
|  |             ioPath = ioFile.toPath(); | ||||||
|             source = Uri.fromFile(ioFile).toString(); |             source = Uri.fromFile(ioFile).toString(); | ||||||
|         } else { |         } else { | ||||||
|             docFile = DocumentFile.fromSingleUri(context, uri); |             docFile = DocumentFile.fromSingleUri(context, uri); | ||||||
| @@ -100,26 +104,18 @@ public class StoredFileHelper implements Serializable { | |||||||
|         this.srcType = this.docFile.getType(); |         this.srcType = this.docFile.getType(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     StoredFileHelper(final File location, final String filename, final String mime) |     StoredFileHelper(final Path location, final String filename, final String mime) | ||||||
|             throws IOException { |             throws IOException { | ||||||
|         this.ioFile = new File(location, filename); |         ioPath = location.resolve(filename); | ||||||
|  |  | ||||||
|         if (this.ioFile.exists()) { |         Files.deleteIfExists(ioPath); | ||||||
|             if (!this.ioFile.isFile() && !this.ioFile.delete()) { |         Files.createFile(ioPath); | ||||||
|                 throw new IOException("The filename is already in use by non-file entity " |  | ||||||
|                         + "and cannot overwrite it"); |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             if (!this.ioFile.createNewFile()) { |  | ||||||
|                 throw new IOException("Cannot create the file"); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         this.source = Uri.fromFile(this.ioFile).toString(); |         source = Uri.fromFile(ioPath.toFile()).toString(); | ||||||
|         this.sourceTree = Uri.fromFile(location).toString(); |         sourceTree = Uri.fromFile(location.toFile()).toString(); | ||||||
|  |  | ||||||
|         this.srcName = ioFile.getName(); |         srcName = ioPath.getFileName().toString(); | ||||||
|         this.srcType = mime; |         srcType = mime; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public StoredFileHelper(final Context context, @Nullable final Uri parent, |     public StoredFileHelper(final Context context, @Nullable final Uri parent, | ||||||
| @@ -129,7 +125,7 @@ public class StoredFileHelper implements Serializable { | |||||||
|  |  | ||||||
|         if (path.getScheme() == null |         if (path.getScheme() == null | ||||||
|                 || path.getScheme().equalsIgnoreCase(ContentResolver.SCHEME_FILE)) { |                 || path.getScheme().equalsIgnoreCase(ContentResolver.SCHEME_FILE)) { | ||||||
|             this.ioFile = new File(URI.create(this.source)); |             this.ioPath = Paths.get(URI.create(this.source)); | ||||||
|         } else { |         } else { | ||||||
|             final DocumentFile file = DocumentFile.fromSingleUri(context, path); |             final DocumentFile file = DocumentFile.fromSingleUri(context, path); | ||||||
|  |  | ||||||
| @@ -187,7 +183,7 @@ public class StoredFileHelper implements Serializable { | |||||||
|         assertValid(); |         assertValid(); | ||||||
|  |  | ||||||
|         if (docFile == null) { |         if (docFile == null) { | ||||||
|             return new FileStream(ioFile); |             return new FileStream(ioPath.toFile()); | ||||||
|         } else { |         } else { | ||||||
|             return new FileStreamSAF(context.getContentResolver(), docFile.getUri()); |             return new FileStreamSAF(context.getContentResolver(), docFile.getUri()); | ||||||
|         } |         } | ||||||
| @@ -211,7 +207,7 @@ public class StoredFileHelper implements Serializable { | |||||||
|     public Uri getUri() { |     public Uri getUri() { | ||||||
|         assertValid(); |         assertValid(); | ||||||
|  |  | ||||||
|         return docFile == null ? Uri.fromFile(ioFile) : docFile.getUri(); |         return docFile == null ? Uri.fromFile(ioPath.toFile()) : docFile.getUri(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public Uri getParentUri() { |     public Uri getParentUri() { | ||||||
| @@ -233,7 +229,12 @@ public class StoredFileHelper implements Serializable { | |||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|         if (docFile == null) { |         if (docFile == null) { | ||||||
|             return ioFile.delete(); |             try { | ||||||
|  |                 return Files.deleteIfExists(ioPath); | ||||||
|  |             } catch (final IOException e) { | ||||||
|  |                 Log.e(TAG, "Exception while deleting " + ioPath, e); | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final boolean res = docFile.delete(); |         final boolean res = docFile.delete(); | ||||||
| @@ -252,21 +253,30 @@ public class StoredFileHelper implements Serializable { | |||||||
|     public long length() { |     public long length() { | ||||||
|         assertValid(); |         assertValid(); | ||||||
|  |  | ||||||
|         return docFile == null ? ioFile.length() : docFile.length(); |         if (docFile == null) { | ||||||
|  |             try { | ||||||
|  |                 return Files.size(ioPath); | ||||||
|  |             } catch (final IOException e) { | ||||||
|  |                 Log.e(TAG, "Exception while getting the size of " + ioPath, e); | ||||||
|  |                 return 0; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             return docFile.length(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public boolean canWrite() { |     public boolean canWrite() { | ||||||
|         if (source == null) { |         if (source == null) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|         return docFile == null ? ioFile.canWrite() : docFile.canWrite(); |         return docFile == null ? Files.isWritable(ioPath) : docFile.canWrite(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public String getName() { |     public String getName() { | ||||||
|         if (source == null) { |         if (source == null) { | ||||||
|             return srcName; |             return srcName; | ||||||
|         } else if (docFile == null) { |         } else if (docFile == null) { | ||||||
|             return ioFile.getName(); |             return ioPath.getFileName().toString(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final String name = docFile.getName(); |         final String name = docFile.getName(); | ||||||
| @@ -287,12 +297,11 @@ public class StoredFileHelper implements Serializable { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public boolean existsAsFile() { |     public boolean existsAsFile() { | ||||||
|         if (source == null || (docFile == null && ioFile == null)) { |         if (source == null || (docFile == null && ioPath == null)) { | ||||||
|             if (DEBUG) { |             if (DEBUG) { | ||||||
|                 Log.d(TAG, "existsAsFile called but something is null: source = [" |                 Log.d(TAG, "existsAsFile called but something is null: source = [" | ||||||
|                         + (source == null ? "null => storage is invalid" : source) |                         + (source == null ? "null => storage is invalid" : source) | ||||||
|                         + "], docFile = [" + (docFile == null ? "null" : docFile) |                         + "], docFile = [" + docFile + "], ioPath = [" + ioPath + "]"); | ||||||
|                         + "], ioFile = [" + (ioFile == null ? "null" : ioFile) + "]"); |  | ||||||
|             } |             } | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
| @@ -300,7 +309,7 @@ public class StoredFileHelper implements Serializable { | |||||||
|         // WARNING: DocumentFile.exists() and DocumentFile.isFile() methods are slow |         // WARNING: DocumentFile.exists() and DocumentFile.isFile() methods are slow | ||||||
|         // docFile.isVirtual() means it is non-physical? |         // docFile.isVirtual() means it is non-physical? | ||||||
|         return docFile == null |         return docFile == null | ||||||
|                 ? (ioFile.exists() && ioFile.isFile()) |                 ? Files.isRegularFile(ioPath) | ||||||
|                 : (docFile.exists() && docFile.isFile()); |                 : (docFile.exists() && docFile.isFile()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -310,8 +319,10 @@ public class StoredFileHelper implements Serializable { | |||||||
|  |  | ||||||
|         if (docFile == null) { |         if (docFile == null) { | ||||||
|             try { |             try { | ||||||
|                 result = ioFile.createNewFile(); |                 Files.createFile(ioPath); | ||||||
|  |                 result = true; | ||||||
|             } catch (final IOException e) { |             } catch (final IOException e) { | ||||||
|  |                 Log.e(TAG, "Exception while creating " + ioPath, e); | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|         } else if (docTree == null) { |         } else if (docTree == null) { | ||||||
| @@ -332,7 +343,8 @@ public class StoredFileHelper implements Serializable { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (result) { |         if (result) { | ||||||
|             source = (docFile == null ? Uri.fromFile(ioFile) : docFile.getUri()).toString(); |             source = (docFile == null ? Uri.fromFile(ioPath.toFile()) : docFile.getUri()) | ||||||
|  |                     .toString(); | ||||||
|             srcName = getName(); |             srcName = getName(); | ||||||
|             srcType = getType(); |             srcType = getType(); | ||||||
|         } |         } | ||||||
| @@ -352,7 +364,7 @@ public class StoredFileHelper implements Serializable { | |||||||
|  |  | ||||||
|         docTree = null; |         docTree = null; | ||||||
|         docFile = null; |         docFile = null; | ||||||
|         ioFile = null; |         ioPath = null; | ||||||
|         context = null; |         context = null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -383,7 +395,7 @@ public class StoredFileHelper implements Serializable { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (this.isDirect()) { |         if (this.isDirect()) { | ||||||
|             return this.ioFile.getPath().equalsIgnoreCase(storage.ioFile.getPath()); |             return this.ioPath.equals(storage.ioPath); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return DocumentsContract.getDocumentId(this.docFile.getUri()) |         return DocumentsContract.getDocumentId(this.docFile.getUri()) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user