Support SAF properly
This commit is contained in:
parent
1e09a1768e
commit
0f75024e03
23 changed files with 451 additions and 311 deletions
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package us.shandian.giga.io;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.schabi.newpipe.streams.io.SharpStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Wrapper for the classic {@link java.io.InputStream}
|
||||
*
|
||||
* @author kapodamy
|
||||
*/
|
||||
public class SharpInputStream extends InputStream {
|
||||
|
||||
private final SharpStream base;
|
||||
|
||||
public SharpInputStream(SharpStream base) throws IOException {
|
||||
if (!base.canRead()) {
|
||||
throw new IOException("The provided stream is not readable");
|
||||
}
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return base.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(@NonNull byte[] bytes) throws IOException {
|
||||
return base.read(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(@NonNull byte[] bytes, int i, int i1) throws IOException {
|
||||
return base.read(bytes, i, i1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long l) throws IOException {
|
||||
return base.skip(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() {
|
||||
long res = base.available();
|
||||
return res > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
base.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,9 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.Nullable;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
|
||||
import org.schabi.newpipe.settings.NewPipeSettings;
|
||||
import org.schabi.newpipe.util.FilePickerActivityHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
|
@ -287,4 +290,18 @@ public class StoredDirectoryHelper {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static Intent getPicker(final Context ctx) {
|
||||
if (NewPipeSettings.useStorageAccessFramework(ctx)) {
|
||||
return new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||
.putExtra("android.content.extra.SHOW_ADVANCED", true)
|
||||
.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
||||
| StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||
} else {
|
||||
return new Intent(ctx, FilePickerActivityHelper.class)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, true)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_MODE,
|
||||
FilePickerActivityHelper.MODE_DIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,14 +6,18 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.provider.DocumentsContract;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
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;
|
||||
import java.io.IOException;
|
||||
|
|
@ -37,6 +41,19 @@ public class StoredFileHelper implements Serializable {
|
|||
private String srcName;
|
||||
private String srcType;
|
||||
|
||||
public StoredFileHelper(final Context context, final Uri uri, final String mime) {
|
||||
if (FilePickerActivityHelper.isOwnFileUri(context, uri)) {
|
||||
ioFile = Utils.getFileForUri(uri);
|
||||
source = Uri.fromFile(ioFile).toString();
|
||||
} else {
|
||||
docFile = DocumentFile.fromSingleUri(context, uri);
|
||||
source = uri.toString();
|
||||
}
|
||||
|
||||
this.context = context;
|
||||
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
|
||||
|
||||
|
|
@ -139,22 +156,6 @@ public class StoredFileHelper implements Serializable {
|
|||
return instance;
|
||||
}
|
||||
|
||||
public static void requestSafWithFileCreation(@NonNull Fragment who, int requestCode, String filename, String mime) {
|
||||
// SAF notes:
|
||||
// ACTION_OPEN_DOCUMENT Do not let you create the file, useful for overwrite files
|
||||
// ACTION_CREATE_DOCUMENT No overwrite support, useless the file provider resolve the conflict
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT)
|
||||
.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
.setType(mime)
|
||||
.putExtra(Intent.EXTRA_TITLE, filename)
|
||||
.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION | StoredDirectoryHelper.PERMISSION_FLAGS)
|
||||
.putExtra("android.content.extra.SHOW_ADVANCED", true);// hack, show all storage disks
|
||||
|
||||
who.startActivityForResult(intent, requestCode);
|
||||
}
|
||||
|
||||
|
||||
public SharpStream getStream() throws IOException {
|
||||
invalid();
|
||||
|
||||
|
|
@ -383,4 +384,64 @@ public class StoredFileHelper implements Serializable {
|
|||
|
||||
return !str1.equals(str2);
|
||||
}
|
||||
|
||||
public static Intent getPicker(final Context ctx) {
|
||||
if (NewPipeSettings.useStorageAccessFramework(ctx)) {
|
||||
return new Intent(Intent.ACTION_OPEN_DOCUMENT)
|
||||
.putExtra("android.content.extra.SHOW_ADVANCED", true)
|
||||
.setType("*/*")
|
||||
.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
||||
| StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||
} else {
|
||||
return new Intent(ctx, FilePickerActivityHelper.class)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, true)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_SINGLE_CLICK, true)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_MODE,
|
||||
FilePickerActivityHelper.MODE_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
public static Intent getNewPicker(@NonNull final Context ctx, @Nullable final String startPath,
|
||||
@Nullable final String filename) {
|
||||
final Intent i;
|
||||
if (NewPipeSettings.useStorageAccessFramework(ctx)) {
|
||||
i = new Intent(Intent.ACTION_CREATE_DOCUMENT)
|
||||
.putExtra("android.content.extra.SHOW_ADVANCED", true)
|
||||
.setType("*/*")
|
||||
.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
||||
| StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||
|
||||
if (startPath != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
i.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Uri.parse(startPath));
|
||||
}
|
||||
if (filename != null) {
|
||||
i.putExtra(Intent.EXTRA_TITLE, filename);
|
||||
}
|
||||
} else {
|
||||
i = new Intent(ctx, FilePickerActivityHelper.class)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, true)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_EXISTING_FILE, true)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_MODE,
|
||||
FilePickerActivityHelper.MODE_NEW_FILE);
|
||||
|
||||
if (startPath != null || filename != null) {
|
||||
File fullStartPath;
|
||||
if (startPath == null) {
|
||||
fullStartPath = Environment.getExternalStorageDirectory();
|
||||
} else {
|
||||
fullStartPath = new File(startPath);
|
||||
}
|
||||
if (filename != null) {
|
||||
fullStartPath = new File(fullStartPath, filename);
|
||||
}
|
||||
i.putExtra(FilePickerActivityHelper.EXTRA_START_PATH,
|
||||
fullStartPath.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -242,27 +242,21 @@ public class MissionsFragment extends Fragment {
|
|||
private void recoverMission(@NonNull DownloadMission mission) {
|
||||
unsafeMissionTarget = mission;
|
||||
|
||||
final String startPath;
|
||||
if (NewPipeSettings.useStorageAccessFramework(mContext)) {
|
||||
StoredFileHelper.requestSafWithFileCreation(
|
||||
MissionsFragment.this,
|
||||
REQUEST_DOWNLOAD_SAVE_AS,
|
||||
mission.storage.getName(),
|
||||
mission.storage.getType()
|
||||
);
|
||||
|
||||
startPath = null;
|
||||
} else {
|
||||
File initialSavePath;
|
||||
if (DownloadManager.TAG_VIDEO.equals(mission.storage.getType()))
|
||||
initialSavePath = NewPipeSettings.getDir(Environment.DIRECTORY_MOVIES);
|
||||
else
|
||||
final File initialSavePath;
|
||||
if (DownloadManager.TAG_AUDIO.equals(mission.storage.getType())) {
|
||||
initialSavePath = NewPipeSettings.getDir(Environment.DIRECTORY_MUSIC);
|
||||
|
||||
initialSavePath = new File(initialSavePath, mission.storage.getName());
|
||||
startActivityForResult(
|
||||
FilePickerActivityHelper.chooseFileToSave(mContext, initialSavePath.getAbsolutePath()),
|
||||
REQUEST_DOWNLOAD_SAVE_AS
|
||||
);
|
||||
} else {
|
||||
initialSavePath = NewPipeSettings.getDir(Environment.DIRECTORY_MOVIES);
|
||||
}
|
||||
startPath = initialSavePath.getAbsolutePath();
|
||||
}
|
||||
|
||||
startActivityForResult(StoredFileHelper.getNewPicker(mContext, startPath,
|
||||
mission.storage.getName()), REQUEST_DOWNLOAD_SAVE_AS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue