Skip to content

Commit

Permalink
ACTION_CREATE_DOCUMENT support
Browse files Browse the repository at this point in the history
  • Loading branch information
TranceLove committed Oct 14, 2023
1 parent 957839b commit 8167e89
Show file tree
Hide file tree
Showing 7 changed files with 366 additions and 269 deletions.
7 changes: 7 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.CREATE_DOCUMENT" />
<data android:mimeType="*/*" />
<category android:name="android.intent.category.OPENABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>

<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" />
<data android:mimeType="application/zip" />
Expand Down
272 changes: 135 additions & 137 deletions app/src/main/java/com/amaze/filemanager/filesystem/FileUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,157 +110,155 @@ public static final void writeUriToStorage(
@NonNull final String currentPath) {

MaybeOnSubscribe<List<String>> writeUri =
(MaybeOnSubscribe<List<String>>)
emitter -> {
List<String> retval = new ArrayList<>();

for (Uri uri : uris) {

BufferedInputStream bufferedInputStream = null;
try {
bufferedInputStream =
new BufferedInputStream(contentResolver.openInputStream(uri));
} catch (FileNotFoundException e) {
emitter.onError(e);
return;
}

BufferedOutputStream bufferedOutputStream = null;
emitter -> {
List<String> retval = new ArrayList<>();

for (Uri uri : uris) {

BufferedInputStream bufferedInputStream = null;
try {
bufferedInputStream = new BufferedInputStream(contentResolver.openInputStream(uri));
} catch (FileNotFoundException e) {
emitter.onError(e);
return;
}

BufferedOutputStream bufferedOutputStream = null;

try {
DocumentFile documentFile = DocumentFile.fromSingleUri(mainActivity, uri);
String filename = documentFile.getName();
if (filename == null) {
filename = uri.getLastPathSegment();

// For cleaning up slashes. Back in #1217 there is a case of
// Uri.getLastPathSegment() end up with a full file path
if (filename.contains("/"))
filename = filename.substring(filename.lastIndexOf('/') + 1);
}

try {
DocumentFile documentFile = DocumentFile.fromSingleUri(mainActivity, uri);
String filename = documentFile.getName();
if (filename == null) {
filename = uri.getLastPathSegment();
String finalFilePath = currentPath + "/" + filename;
DataUtils dataUtils = DataUtils.getInstance();

// For cleaning up slashes. Back in #1217 there is a case of
// Uri.getLastPathSegment() end up with a full file path
if (filename.contains("/"))
filename = filename.substring(filename.lastIndexOf('/') + 1);
}
HybridFile hFile = new HybridFile(OpenMode.UNKNOWN, currentPath);
hFile.generateMode(mainActivity);

String finalFilePath = currentPath + "/" + filename;
DataUtils dataUtils = DataUtils.getInstance();

HybridFile hFile = new HybridFile(OpenMode.UNKNOWN, currentPath);
hFile.generateMode(mainActivity);

switch (hFile.getMode()) {
case FILE:
case ROOT:
File targetFile = new File(finalFilePath);
if (!FileProperties.isWritableNormalOrSaf(
targetFile.getParentFile(), mainActivity.getApplicationContext())) {
emitter.onError(new NotAllowedException());
return;
}

DocumentFile targetDocumentFile =
ExternalSdCardOperation.getDocumentFile(
targetFile, false, mainActivity.getApplicationContext());

// Fallback, in case getDocumentFile() didn't properly return a
// DocumentFile
// instance
if (targetDocumentFile == null) {
targetDocumentFile = DocumentFile.fromFile(targetFile);
}

// Lazy check... and in fact, different apps may pass in URI in different
// formats, so we could only check filename matches
// FIXME?: Prompt overwrite instead of simply blocking
if (targetDocumentFile.exists() && targetDocumentFile.length() > 0) {
emitter.onError(new OperationWouldOverwriteException());
return;
}

bufferedOutputStream =
new BufferedOutputStream(
contentResolver.openOutputStream(targetDocumentFile.getUri()));
retval.add(targetFile.getPath());
break;
case SMB:
SmbFile targetSmbFile = SmbUtil.create(finalFilePath);
if (targetSmbFile.exists()) {
emitter.onError(new OperationWouldOverwriteException());
return;
} else {
OutputStream outputStream = targetSmbFile.getOutputStream();
bufferedOutputStream = new BufferedOutputStream(outputStream);
retval.add(HybridFile.parseAndFormatUriForDisplay(targetSmbFile.getPath()));
}
break;
case SFTP:
// FIXME: implement support
AppConfig.toast(mainActivity, mainActivity.getString(R.string.not_allowed));
emitter.onError(new NotImplementedError());
return;
case DROPBOX:
case BOX:
case ONEDRIVE:
case GDRIVE:
OpenMode mode = hFile.getMode();

CloudStorage cloudStorage = dataUtils.getAccount(mode);
String path = CloudUtil.stripPath(mode, finalFilePath);
cloudStorage.upload(path, bufferedInputStream, documentFile.length(), true);
retval.add(path);
break;
case OTG:
DocumentFile documentTargetFile =
OTGUtil.getDocumentFile(finalFilePath, mainActivity, true);

if (documentTargetFile.exists()) {
emitter.onError(new OperationWouldOverwriteException());
return;
}

bufferedOutputStream =
new BufferedOutputStream(
contentResolver.openOutputStream(documentTargetFile.getUri()),
GenericCopyUtil.DEFAULT_BUFFER_SIZE);

retval.add(documentTargetFile.getUri().getPath());
break;
default:
return;
switch (hFile.getMode()) {
case FILE:
case ROOT:
File targetFile = new File(finalFilePath);
if (!FileProperties.isWritableNormalOrSaf(
targetFile.getParentFile(), mainActivity.getApplicationContext())) {
emitter.onError(new NotAllowedException());
return;
}

int count = 0;
byte[] buffer = new byte[GenericCopyUtil.DEFAULT_BUFFER_SIZE];
DocumentFile targetDocumentFile =
ExternalSdCardOperation.getDocumentFile(
targetFile, false, mainActivity.getApplicationContext());

while (count != -1) {
count = bufferedInputStream.read(buffer);
if (count != -1) {
// Fallback, in case getDocumentFile() didn't properly return a
// DocumentFile
// instance
if (targetDocumentFile == null) {
targetDocumentFile = DocumentFile.fromFile(targetFile);
}

bufferedOutputStream.write(buffer, 0, count);
}
// Lazy check... and in fact, different apps may pass in URI in different
// formats, so we could only check filename matches
// FIXME?: Prompt overwrite instead of simply blocking
if (targetDocumentFile.exists() && targetDocumentFile.length() > 0) {
emitter.onError(new OperationWouldOverwriteException());
return;
}
bufferedOutputStream.flush();

} catch (IOException e) {
emitter.onError(e);
bufferedOutputStream =
new BufferedOutputStream(
contentResolver.openOutputStream(targetDocumentFile.getUri()));
retval.add(targetFile.getPath());
break;
case SMB:
SmbFile targetSmbFile = SmbUtil.create(finalFilePath);
if (targetSmbFile.exists()) {
emitter.onError(new OperationWouldOverwriteException());
return;
} else {
OutputStream outputStream = targetSmbFile.getOutputStream();
bufferedOutputStream = new BufferedOutputStream(outputStream);
retval.add(HybridFile.parseAndFormatUriForDisplay(targetSmbFile.getPath()));
}
break;
case SFTP:
// FIXME: implement support
AppConfig.toast(mainActivity, mainActivity.getString(R.string.not_allowed));
emitter.onError(new NotImplementedError());
return;
} finally {
try {
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
if (bufferedOutputStream != null) {
bufferedOutputStream.close();
}
} catch (IOException e) {
emitter.onError(e);
case DROPBOX:
case BOX:
case ONEDRIVE:
case GDRIVE:
OpenMode mode = hFile.getMode();

CloudStorage cloudStorage = dataUtils.getAccount(mode);
String path = CloudUtil.stripPath(mode, finalFilePath);
cloudStorage.upload(path, bufferedInputStream, documentFile.length(), true);
retval.add(path);
break;
case OTG:
DocumentFile documentTargetFile =
OTGUtil.getDocumentFile(finalFilePath, mainActivity, true);

if (documentTargetFile.exists()) {
emitter.onError(new OperationWouldOverwriteException());
return;
}
}

bufferedOutputStream =
new BufferedOutputStream(
contentResolver.openOutputStream(documentTargetFile.getUri()),
GenericCopyUtil.DEFAULT_BUFFER_SIZE);

retval.add(documentTargetFile.getUri().getPath());
break;
default:
return;
}

if (retval.size() > 0) {
emitter.onSuccess(retval);
} else {
emitter.onError(new Exception());
int count = 0;
byte[] buffer = new byte[GenericCopyUtil.DEFAULT_BUFFER_SIZE];

while (count != -1) {
count = bufferedInputStream.read(buffer);
if (count != -1) {

bufferedOutputStream.write(buffer, 0, count);
}
}
bufferedOutputStream.flush();

} catch (IOException e) {
emitter.onError(e);
return;
} finally {
try {
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
if (bufferedOutputStream != null) {
bufferedOutputStream.close();
}
} catch (IOException e) {
emitter.onError(e);
}
};
}
}

if (retval.size() > 0) {
emitter.onSuccess(retval);
} else {
emitter.onError(new Exception());
}
};

Maybe.create(writeUri)
.subscribeOn(Schedulers.io())
Expand Down
Loading

0 comments on commit 8167e89

Please sign in to comment.