mirror of
https://github.com/nextcloud/android.git
synced 2024-11-27 09:39:25 +03:00
add missing upload error messages
better handle temp file Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
This commit is contained in:
parent
9927a649dc
commit
cb7134817e
5 changed files with 87 additions and 60 deletions
|
@ -210,9 +210,9 @@ dependencies {
|
|||
// dependencies for app building
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
// implementation project('nextcloud-android-library')
|
||||
genericImplementation 'com.github.nextcloud:android-library:master-SNAPSHOT'
|
||||
gplayImplementation 'com.github.nextcloud:android-library:master-SNAPSHOT'
|
||||
versionDevImplementation 'com.github.nextcloud:android-library:master-SNAPSHOT'
|
||||
genericImplementation 'com.github.nextcloud:android-library:newResultCode-SNAPSHOT'
|
||||
gplayImplementation 'com.github.nextcloud:android-library:newResultCode-SNAPSHOT'
|
||||
versionDevImplementation 'com.github.nextcloud:android-library:newResultCode-SNAPSHOT'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/*
|
||||
* ownCloud Android client application
|
||||
*
|
||||
* @author masensio
|
||||
|
@ -29,7 +29,7 @@ public enum UploadResult {
|
|||
FOLDER_ERROR(3),
|
||||
CONFLICT_ERROR(4),
|
||||
FILE_ERROR(5),
|
||||
PRIVILEDGES_ERROR(6),
|
||||
PRIVILEGES_ERROR(6),
|
||||
CANCELLED(7),
|
||||
FILE_NOT_FOUND(8),
|
||||
DELAYED_FOR_WIFI(9),
|
||||
|
@ -39,7 +39,12 @@ public enum UploadResult {
|
|||
LOCK_FAILED(13),
|
||||
DELAYED_IN_POWER_SAVE_MODE(14),
|
||||
SSL_RECOVERABLE_PEER_UNVERIFIED(15),
|
||||
VIRUS_DETECTED(16);
|
||||
VIRUS_DETECTED(16),
|
||||
LOCAL_STORAGE_FULL(17),
|
||||
OLD_ANDROID_API(18),
|
||||
SYNC_CONFLICT(19),
|
||||
CANNOT_CREATE_FILE(20),
|
||||
LOCAL_STORAGE_NOT_COPIED(21);
|
||||
|
||||
private final int value;
|
||||
|
||||
|
@ -68,7 +73,7 @@ public enum UploadResult {
|
|||
case 5:
|
||||
return FILE_ERROR;
|
||||
case 6:
|
||||
return PRIVILEDGES_ERROR;
|
||||
return PRIVILEGES_ERROR;
|
||||
case 7:
|
||||
return CANCELLED;
|
||||
case 8:
|
||||
|
@ -89,8 +94,18 @@ public enum UploadResult {
|
|||
return SSL_RECOVERABLE_PEER_UNVERIFIED;
|
||||
case 16:
|
||||
return VIRUS_DETECTED;
|
||||
case 17:
|
||||
return LOCAL_STORAGE_FULL;
|
||||
case 18:
|
||||
return OLD_ANDROID_API;
|
||||
case 19:
|
||||
return SYNC_CONFLICT;
|
||||
case 20:
|
||||
return CANNOT_CREATE_FILE;
|
||||
case 21:
|
||||
return LOCAL_STORAGE_NOT_COPIED;
|
||||
}
|
||||
return null;
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public static UploadResult fromOperationResult(RemoteOperationResult result) {
|
||||
|
@ -115,9 +130,15 @@ public enum UploadResult {
|
|||
case CONFLICT:
|
||||
return CONFLICT_ERROR;
|
||||
case LOCAL_STORAGE_NOT_COPIED:
|
||||
return FILE_ERROR;
|
||||
return LOCAL_STORAGE_NOT_COPIED;
|
||||
case LOCAL_STORAGE_FULL:
|
||||
return LOCAL_STORAGE_FULL;
|
||||
case OLD_ANDROID_API:
|
||||
return OLD_ANDROID_API;
|
||||
case SYNC_CONFLICT:
|
||||
return SYNC_CONFLICT;
|
||||
case FORBIDDEN:
|
||||
return PRIVILEDGES_ERROR;
|
||||
return PRIVILEGES_ERROR;
|
||||
case CANCELLED:
|
||||
return CANCELLED;
|
||||
case DELAYED_FOR_WIFI:
|
||||
|
@ -139,6 +160,8 @@ public enum UploadResult {
|
|||
return LOCK_FAILED;
|
||||
case VIRUS_DETECTED:
|
||||
return VIRUS_DETECTED;
|
||||
case CANNOT_CREATE_FILE:
|
||||
return CANNOT_CREATE_FILE;
|
||||
default:
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
|
|
@ -83,7 +83,6 @@ import java.nio.channels.FileLock;
|
|||
import java.nio.channels.OverlappingFileLockException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
@ -502,7 +501,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||
expectedFile = new File(expectedPath);
|
||||
|
||||
result = copyFile(originalFile, expectedPath);
|
||||
if (result != null) {
|
||||
if (!result.isSuccess()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -551,7 +550,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||
Files.deleteIfExists(Paths.get(temporalPath));
|
||||
result = copy(originalFile, temporalFile);
|
||||
|
||||
if (result == null) {
|
||||
if (result.isSuccess()) {
|
||||
if (temporalFile.length() == originalFile.length()) {
|
||||
channel = new RandomAccessFile(temporalFile.getAbsolutePath(), "rw").getChannel();
|
||||
fileLock = channel.tryLock();
|
||||
|
@ -586,9 +585,8 @@ public class UploadFileOperation extends SyncOperation {
|
|||
mFile.getEtagInConflict(), timeStamp);
|
||||
}
|
||||
|
||||
Iterator<OnDatatransferProgressListener> listener = mDataTransferListeners.iterator();
|
||||
while (listener.hasNext()) {
|
||||
mUploadOperation.addDatatransferProgressListener(listener.next());
|
||||
for (OnDatatransferProgressListener mDataTransferListener : mDataTransferListeners) {
|
||||
mUploadOperation.addDatatransferProgressListener(mDataTransferListener);
|
||||
}
|
||||
|
||||
if (mCancellationRequested.get()) {
|
||||
|
@ -755,7 +753,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||
File originalFile = new File(mOriginalStoragePath);
|
||||
File expectedFile = null;
|
||||
FileLock fileLock = null;
|
||||
long size = 0;
|
||||
long size;
|
||||
|
||||
try {
|
||||
// check conditions
|
||||
|
@ -772,7 +770,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||
expectedFile = new File(expectedPath);
|
||||
|
||||
result = copyFile(originalFile, expectedPath);
|
||||
if (result != null) {
|
||||
if (!result.isSuccess()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -795,7 +793,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||
Files.deleteIfExists(Paths.get(temporalPath));
|
||||
result = copy(originalFile, temporalFile);
|
||||
|
||||
if (result == null) {
|
||||
if (result.isSuccess()) {
|
||||
if (temporalFile.length() == originalFile.length()) {
|
||||
channel = new RandomAccessFile(temporalFile.getAbsolutePath(), "rw").getChannel();
|
||||
fileLock = channel.tryLock();
|
||||
|
@ -807,7 +805,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||
|
||||
try {
|
||||
size = channel.size();
|
||||
} catch (IOException e1) {
|
||||
} catch (Exception e1) {
|
||||
size = new File(mFile.getStoragePath()).length();
|
||||
}
|
||||
|
||||
|
@ -828,16 +826,15 @@ public class UploadFileOperation extends SyncOperation {
|
|||
mFile.getRemotePath(), mFile.getMimeType(), mFile.getEtagInConflict(), timeStamp);
|
||||
}
|
||||
|
||||
Iterator<OnDatatransferProgressListener> listener = mDataTransferListeners.iterator();
|
||||
while (listener.hasNext()) {
|
||||
mUploadOperation.addDatatransferProgressListener(listener.next());
|
||||
for (OnDatatransferProgressListener mDataTransferListener : mDataTransferListeners) {
|
||||
mUploadOperation.addDatatransferProgressListener(mDataTransferListener);
|
||||
}
|
||||
|
||||
if (mCancellationRequested.get()) {
|
||||
throw new OperationCancelledException();
|
||||
}
|
||||
|
||||
if (result == null || result.isSuccess() && mUploadOperation != null) {
|
||||
if (result.isSuccess() && mUploadOperation != null) {
|
||||
result = mUploadOperation.execute(client, mFile.isEncrypted());
|
||||
|
||||
/// move local temporal file or original file to its corresponding
|
||||
|
@ -908,22 +905,20 @@ public class UploadFileOperation extends SyncOperation {
|
|||
|
||||
private RemoteOperationResult copyFile(File originalFile, String expectedPath) throws OperationCancelledException,
|
||||
IOException {
|
||||
RemoteOperationResult result = null;
|
||||
|
||||
if (mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_COPY && !mOriginalStoragePath.equals(expectedPath)) {
|
||||
String temporalPath = FileStorageUtils.getInternalTemporalPath(mAccount.name, mContext) +
|
||||
mFile.getRemotePath();
|
||||
mFile.setStoragePath(temporalPath);
|
||||
File temporalFile = new File(temporalPath);
|
||||
|
||||
result = copy(originalFile, temporalFile);
|
||||
return copy(originalFile, temporalFile);
|
||||
}
|
||||
|
||||
if (mCancellationRequested.get()) {
|
||||
throw new OperationCancelledException();
|
||||
}
|
||||
|
||||
return result;
|
||||
return new RemoteOperationResult(ResultCode.OK);
|
||||
}
|
||||
|
||||
private void checkNameCollision(OwnCloudClient client, DecryptedFolderMetadata metadata, boolean encrypted)
|
||||
|
@ -1017,7 +1012,7 @@ public class UploadFileOperation extends SyncOperation {
|
|||
if (parentDir != null) {
|
||||
result = new RemoteOperationResult(ResultCode.OK);
|
||||
} else {
|
||||
result = new RemoteOperationResult(ResultCode.UNKNOWN_ERROR);
|
||||
result = new RemoteOperationResult(ResultCode.CANNOT_CREATE_FILE);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -1168,25 +1163,19 @@ public class UploadFileOperation extends SyncOperation {
|
|||
private RemoteOperationResult copy(File sourceFile, File targetFile) throws IOException {
|
||||
Log_OC.d(TAG, "Copying local file");
|
||||
|
||||
RemoteOperationResult result = null;
|
||||
|
||||
if (FileStorageUtils.getUsableSpace() < sourceFile.length()) {
|
||||
result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_FULL);
|
||||
return result; // error condition when the file should be copied
|
||||
|
||||
return new RemoteOperationResult(ResultCode.LOCAL_STORAGE_FULL); // error when the file should be copied
|
||||
} else {
|
||||
Log_OC.d(TAG, "Creating temporal folder");
|
||||
File temporalParent = targetFile.getParentFile();
|
||||
temporalParent.mkdirs();
|
||||
if (!temporalParent.isDirectory()) {
|
||||
throw new IOException(
|
||||
"Unexpected error: parent directory could not be created");
|
||||
|
||||
if (!temporalParent.mkdirs() && !temporalParent.isDirectory()) {
|
||||
return new RemoteOperationResult(ResultCode.CANNOT_CREATE_FILE);
|
||||
}
|
||||
|
||||
Log_OC.d(TAG, "Creating temporal file");
|
||||
targetFile.createNewFile();
|
||||
if (!targetFile.isFile()) {
|
||||
throw new IOException(
|
||||
"Unexpected error: target file could not be created");
|
||||
if (!targetFile.createNewFile() && !targetFile.isFile()) {
|
||||
return new RemoteOperationResult(ResultCode.CANNOT_CREATE_FILE);
|
||||
}
|
||||
|
||||
Log_OC.d(TAG, "Copying file contents");
|
||||
|
@ -1214,14 +1203,10 @@ public class UploadFileOperation extends SyncOperation {
|
|||
} // else: weird but possible situation, nothing to copy
|
||||
|
||||
if (mCancellationRequested.get()) {
|
||||
result = new RemoteOperationResult(new OperationCancelledException());
|
||||
return result;
|
||||
return new RemoteOperationResult(new OperationCancelledException());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_COPIED);
|
||||
return result;
|
||||
|
||||
return new RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_COPIED);
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
|
@ -1241,19 +1226,17 @@ public class UploadFileOperation extends SyncOperation {
|
|||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return new RemoteOperationResult(ResultCode.OK);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TODO rewrite with homogeneous fail handling, remove dependency on {@link RemoteOperationResult},
|
||||
* TODO use Exceptions instead
|
||||
* <p>
|
||||
* TODO refactor both this and 'copy' in a single method
|
||||
*
|
||||
* @param sourceFile Source file to move.
|
||||
* @param targetFile Target location to move the file.
|
||||
* @return {@link RemoteOperationResult} result from remote operation
|
||||
* @throws IOException exception if file cannot be read/wrote
|
||||
*/
|
||||
private void move(File sourceFile, File targetFile) throws IOException {
|
||||
|
|
|
@ -58,7 +58,6 @@ import java.util.Arrays;
|
|||
import java.util.Comparator;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
|
||||
/**
|
||||
* This Adapter populates a ListView with following types of uploads: pending,active, completed. Filtering possible.
|
||||
|
@ -436,7 +435,7 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
|
|||
case FILE_ERROR:
|
||||
status = mParentActivity.getString(R.string.uploads_view_upload_status_failed_file_error);
|
||||
break;
|
||||
case PRIVILEDGES_ERROR:
|
||||
case PRIVILEGES_ERROR:
|
||||
status = mParentActivity.getString(R.string.uploads_view_upload_status_failed_permission_error);
|
||||
break;
|
||||
case NETWORK_CONNECTION:
|
||||
|
@ -466,14 +465,16 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
|
|||
status = mParentActivity.getString(R.string.maintenance_mode);
|
||||
break;
|
||||
case SSL_RECOVERABLE_PEER_UNVERIFIED:
|
||||
status =
|
||||
mParentActivity.getString(
|
||||
status = mParentActivity.getString(
|
||||
R.string.uploads_view_upload_status_failed_ssl_certificate_not_trusted
|
||||
);
|
||||
break;
|
||||
case UNKNOWN:
|
||||
status = mParentActivity.getString(R.string.uploads_view_upload_status_unknown_fail);
|
||||
break;
|
||||
case LOCK_FAILED:
|
||||
status = mParentActivity.getString(R.string.upload_lock_failed);
|
||||
break;
|
||||
case DELAYED_IN_POWER_SAVE_MODE:
|
||||
status = mParentActivity.getString(
|
||||
R.string.uploads_view_upload_status_waiting_exit_power_save_mode);
|
||||
|
@ -481,8 +482,23 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
|
|||
case VIRUS_DETECTED:
|
||||
status = mParentActivity.getString(R.string.uploads_view_upload_status_virus_detected);
|
||||
break;
|
||||
case LOCAL_STORAGE_FULL:
|
||||
status = mParentActivity.getString(R.string.upload_local_storage_full);
|
||||
break;
|
||||
case OLD_ANDROID_API:
|
||||
status = mParentActivity.getString(R.string.upload_old_android);
|
||||
break;
|
||||
case SYNC_CONFLICT:
|
||||
status = mParentActivity.getString(R.string.upload_sync_conflict);
|
||||
break;
|
||||
case CANNOT_CREATE_FILE:
|
||||
status = mParentActivity.getString(R.string.upload_cannot_create_file);
|
||||
break;
|
||||
case LOCAL_STORAGE_NOT_COPIED:
|
||||
status = mParentActivity.getString(R.string.upload_local_storage_not_copied);
|
||||
break;
|
||||
default:
|
||||
status = "New fail result but no description for the user";
|
||||
status = mParentActivity.getString(R.string.upload_unknown_error);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -656,14 +672,12 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("Bx")
|
||||
private int compareUploadId(OCUpload upload1, OCUpload upload2) {
|
||||
return Long.valueOf(upload1.getFixedUploadId()).compareTo(upload2.getFixedUploadId());
|
||||
return Long.compare(upload1.getFixedUploadId(), upload2.getFixedUploadId());
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("Bx")
|
||||
private int compareUpdateTime(OCUpload upload1, OCUpload upload2) {
|
||||
return Long.valueOf(upload2.getFixedUploadEndTimeStamp()).compareTo(upload1.getFixedUploadEndTimeStamp());
|
||||
return Long.compare(upload2.getFixedUploadEndTimeStamp(), upload1.getFixedUploadEndTimeStamp());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -850,4 +850,11 @@
|
|||
<string name="uploader_upload_files_behaviour_not_writable">source folder is read-only; file will only be uploaded</string>
|
||||
<string name="auto_upload_file_behaviour_kept_in_folder">kept in original folder, as it is readonly</string>
|
||||
<string name="scanQR_description">Login via QR code</string>
|
||||
<string name="upload_unknown_error">Unknown error</string>
|
||||
<string name="upload_lock_failed">Locking folder failed</string>
|
||||
<string name="upload_local_storage_full">Local storage full</string>
|
||||
<string name="upload_old_android"><![CDATA[Encryption is only possible with >= Android 5.0]]></string>
|
||||
<string name="upload_sync_conflict">Sync conflict, please resolve manually</string>
|
||||
<string name="upload_cannot_create_file">Cannot create local file</string>
|
||||
<string name="upload_local_storage_not_copied">File could not be copied to local storage</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue