Search in sources :

Example 1 with UploadFileOperation

use of com.owncloud.android.operations.UploadFileOperation in project android by owncloud.

the class FileUploader method onStartCommand.

/**
 * Entry point to add one or several files to the queue of uploads.
 * <p>
 * New uploads are added calling to startService(), resulting in a call to
 * this method. This ensures the service will keep on working although the
 * caller activity goes away.
 */
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Timber.d("Starting command with id %s", startId);
    int createdBy = intent.getIntExtra(KEY_CREATED_BY, UploadFileOperation.CREATED_BY_USER);
    boolean isCameraUploadFile = createdBy == CREATED_AS_CAMERA_UPLOAD_PICTURE || createdBy == CREATED_AS_CAMERA_UPLOAD_VIDEO;
    boolean isAvailableOfflineFile = intent.getBooleanExtra(KEY_IS_AVAILABLE_OFFLINE_FILE, false);
    boolean isRequestedFromWifiBackEvent = intent.getBooleanExtra(KEY_REQUESTED_FROM_WIFI_BACK_EVENT, false);
    if ((isCameraUploadFile || isAvailableOfflineFile || isRequestedFromWifiBackEvent) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        Timber.d("Starting FileUploader service in foreground");
        if (isCameraUploadFile) {
            mNotificationBuilder.setContentTitle(getString(R.string.uploader_upload_camera_upload_files));
        } else if (isAvailableOfflineFile) {
            mNotificationBuilder.setContentTitle(getString(R.string.uploader_upload_available_offline_files));
        } else if (isRequestedFromWifiBackEvent) {
            mNotificationBuilder.setContentTitle(getString(R.string.uploader_upload_requested_from_wifi_files));
        }
        /*
             * After calling startForegroundService method from {@link TransferRequester} for camera uploads or
             * available offline, we have to call this within five seconds after the service is created to avoid
             * an error
             */
        startForeground(141, mNotificationBuilder.build());
    }
    boolean retry = intent.getBooleanExtra(KEY_RETRY, false);
    AbstractList<String> requestedUploads = new Vector<>();
    if (!intent.hasExtra(KEY_ACCOUNT)) {
        Timber.e("Not enough information provided in intent");
        return Service.START_NOT_STICKY;
    }
    Account account = intent.getParcelableExtra(KEY_ACCOUNT);
    Timber.d("Account to upload the file to: %s", account);
    if (account == null || !AccountUtils.exists(account.name, getApplicationContext())) {
        return Service.START_NOT_STICKY;
    }
    if (!retry) {
        if (!(intent.hasExtra(KEY_LOCAL_FILE) || intent.hasExtra(KEY_FILE))) {
            Timber.e("Not enough information provided in intent");
            return Service.START_NOT_STICKY;
        }
        String[] localPaths = null, remotePaths = null, mimeTypes = null;
        OCFile[] files = null;
        if (intent.hasExtra(KEY_FILE)) {
            Parcelable[] files_temp = intent.getParcelableArrayExtra(KEY_FILE);
            files = new OCFile[files_temp.length];
            System.arraycopy(files_temp, 0, files, 0, files_temp.length);
        } else {
            localPaths = intent.getStringArrayExtra(KEY_LOCAL_FILE);
            remotePaths = intent.getStringArrayExtra(KEY_REMOTE_FILE);
            mimeTypes = intent.getStringArrayExtra(KEY_MIME_TYPE);
        }
        boolean forceOverwrite = intent.getBooleanExtra(KEY_FORCE_OVERWRITE, false);
        int localAction = intent.getIntExtra(KEY_LOCAL_BEHAVIOUR, LOCAL_BEHAVIOUR_FORGET);
        boolean isCreateRemoteFolder = intent.getBooleanExtra(KEY_CREATE_REMOTE_FOLDER, false);
        if (intent.hasExtra(KEY_FILE) && files == null) {
            Timber.e("Incorrect array for OCFiles provided in upload intent");
            return Service.START_NOT_STICKY;
        } else if (!intent.hasExtra(KEY_FILE)) {
            if (localPaths == null) {
                Timber.e("Incorrect array for local paths provided in upload intent");
                return Service.START_NOT_STICKY;
            }
            if (remotePaths == null) {
                Timber.e("Incorrect array for remote paths provided in upload intent");
                return Service.START_NOT_STICKY;
            }
            if (localPaths.length != remotePaths.length) {
                Timber.e("Different number of remote paths and local paths!");
                return Service.START_NOT_STICKY;
            }
            files = new OCFile[localPaths.length];
            for (int i = 0; i < localPaths.length; i++) {
                files[i] = UploadFileOperation.obtainNewOCFileToUpload(remotePaths[i], localPaths[i], ((mimeTypes != null) ? mimeTypes[i] : null), getApplicationContext());
                if (files[i] == null) {
                    Timber.e("obtainNewOCFileToUpload() returned null for remotePaths[i]:" + remotePaths[i] + " and localPaths[i]:" + localPaths[i]);
                    return Service.START_NOT_STICKY;
                }
            }
        }
        // at this point variable "OCFile[] files" is loaded correctly.
        String uploadKey;
        UploadFileOperation newUploadFileOperation;
        try {
            FileDataStorageManager storageManager = new FileDataStorageManager(getApplicationContext(), account, getContentResolver());
            OCCapability capabilitiesForAccount = storageManager.getCapability(account.name);
            boolean isChunkingAllowed = capabilitiesForAccount != null && capabilitiesForAccount.isChunkingAllowed();
            Timber.d("Chunking is allowed: %s", isChunkingAllowed);
            for (OCFile ocFile : files) {
                OCUpload ocUpload = new OCUpload(ocFile, account);
                ocUpload.setFileSize(ocFile.getFileLength());
                ocUpload.setForceOverwrite(forceOverwrite);
                ocUpload.setCreateRemoteFolder(isCreateRemoteFolder);
                ocUpload.setCreatedBy(createdBy);
                ocUpload.setLocalAction(localAction);
                /*ocUpload.setUseWifiOnly(isUseWifiOnly);
                    ocUpload.setWhileChargingOnly(isWhileChargingOnly);*/
                ocUpload.setUploadStatus(UploadStatus.UPLOAD_IN_PROGRESS);
                if (new File(ocFile.getStoragePath()).length() > ChunkedUploadRemoteFileOperation.CHUNK_SIZE && isChunkingAllowed) {
                    ocUpload.setTransferId(SecurityUtils.stringToMD5Hash(ocFile.getRemotePath()) + System.currentTimeMillis());
                    newUploadFileOperation = new ChunkedUploadFileOperation(account, ocFile, ocUpload, forceOverwrite, localAction, this);
                } else {
                    newUploadFileOperation = new UploadFileOperation(account, ocFile, ocUpload, forceOverwrite, localAction, this);
                }
                newUploadFileOperation.setCreatedBy(createdBy);
                if (isCreateRemoteFolder) {
                    newUploadFileOperation.setRemoteFolderToBeCreated();
                }
                newUploadFileOperation.addDatatransferProgressListener(this);
                newUploadFileOperation.addDatatransferProgressListener((FileUploaderBinder) mBinder);
                newUploadFileOperation.addRenameUploadListener(this);
                Pair<String, String> putResult = mPendingUploads.putIfAbsent(account.name, ocFile.getRemotePath(), newUploadFileOperation);
                if (putResult != null) {
                    uploadKey = putResult.first;
                    requestedUploads.add(uploadKey);
                    // Save upload in database
                    long id = mUploadsStorageManager.storeUpload(ocUpload);
                    newUploadFileOperation.setOCUploadId(id);
                }
            }
        } catch (IllegalArgumentException e) {
            Timber.e(e, "Not enough information provided in intent: %s", e.getMessage());
            return START_NOT_STICKY;
        } catch (IllegalStateException e) {
            Timber.e(e, "Bad information provided in intent: %s", e.getMessage());
            return START_NOT_STICKY;
        } catch (Exception e) {
            Timber.e(e, "Unexpected exception while processing upload intent");
            return START_NOT_STICKY;
        }
    // *** TODO REWRITE: block inserted to request A retry; too many code copied, no control exception ***/
    } else {
        if (!intent.hasExtra(KEY_ACCOUNT) || !intent.hasExtra(KEY_RETRY_UPLOAD)) {
            Timber.e("Not enough information provided in intent: no KEY_RETRY_UPLOAD_KEY");
            return START_NOT_STICKY;
        }
        OCUpload upload = intent.getParcelableExtra(KEY_RETRY_UPLOAD);
        UploadFileOperation newUploadFileOperation;
        if (upload.getFileSize() > ChunkedUploadRemoteFileOperation.CHUNK_SIZE) {
            upload.setTransferId(SecurityUtils.stringToMD5Hash(upload.getRemotePath()) + System.currentTimeMillis());
            newUploadFileOperation = new ChunkedUploadFileOperation(account, null, upload, upload.isForceOverwrite(), upload.getLocalAction(), this);
        } else {
            newUploadFileOperation = new UploadFileOperation(account, null, upload, upload.isForceOverwrite(), upload.getLocalAction(), this);
        }
        newUploadFileOperation.addDatatransferProgressListener(this);
        newUploadFileOperation.addDatatransferProgressListener((FileUploaderBinder) mBinder);
        newUploadFileOperation.addRenameUploadListener(this);
        Pair<String, String> putResult = mPendingUploads.putIfAbsent(account.name, upload.getRemotePath(), newUploadFileOperation);
        if (putResult != null) {
            String uploadKey = putResult.first;
            requestedUploads.add(uploadKey);
            // Update upload in database
            upload.setUploadStatus(UploadStatus.UPLOAD_IN_PROGRESS);
            mUploadsStorageManager.updateUpload(upload);
        }
    }
    if (requestedUploads.size() > 0) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = requestedUploads;
        mServiceHandler.sendMessage(msg);
        sendBroadcastUploadsAdded();
    }
    return Service.START_NOT_STICKY;
}
Also used : Account(android.accounts.Account) OwnCloudAccount(com.owncloud.android.lib.common.OwnCloudAccount) OCCapability(com.owncloud.android.domain.capabilities.model.OCCapability) Message(android.os.Message) Parcelable(android.os.Parcelable) UploadFileOperation(com.owncloud.android.operations.UploadFileOperation) ChunkedUploadFileOperation(com.owncloud.android.operations.ChunkedUploadFileOperation) OCFile(com.owncloud.android.datamodel.OCFile) OCUpload(com.owncloud.android.datamodel.OCUpload) FileDataStorageManager(com.owncloud.android.datamodel.FileDataStorageManager) ChunkedUploadFileOperation(com.owncloud.android.operations.ChunkedUploadFileOperation) Vector(java.util.Vector) OCFile(com.owncloud.android.datamodel.OCFile) File(java.io.File)

Example 2 with UploadFileOperation

use of com.owncloud.android.operations.UploadFileOperation in project android by owncloud.

the class FileUploader method uploadFile.

/**
 * Core upload method: sends the file(s) to upload
 *
 * @param uploadKey Key to access the upload to perform, contained in mPendingUploads
 */
public void uploadFile(String uploadKey) {
    mCurrentUpload = mPendingUploads.get(uploadKey);
    if (mCurrentUpload != null) {
        // / Check account existence
        if (!AccountUtils.exists(mCurrentUpload.getAccount().name, this)) {
            Timber.w("Account " + mCurrentUpload.getAccount().name + " does not exist anymore -> cancelling all " + "its uploads");
            cancelUploadsForAccount(mCurrentUpload.getAccount());
            return;
        }
        // / OK, let's upload
        mUploadsStorageManager.updateDatabaseUploadStart(mCurrentUpload);
        notifyUploadStart(mCurrentUpload);
        sendBroadcastUploadStarted(mCurrentUpload);
        RemoteOperationResult uploadResult = null;
        try {
            // / prepare client object to send the request to the ownCloud server
            if (mCurrentAccount == null || !mCurrentAccount.equals(mCurrentUpload.getAccount())) {
                mCurrentAccount = mCurrentUpload.getAccount();
                mStorageManager = new FileDataStorageManager(getApplicationContext(), mCurrentAccount, getContentResolver());
            }
            // else, reuse storage manager from previous operation
            // always get client from client manager to get fresh credentials in case of update
            OwnCloudAccount ocAccount = new OwnCloudAccount(mCurrentAccount, this);
            mUploadClient = SingleSessionManager.getDefaultSingleton().getClientFor(ocAccount, this);
            // / perform the upload
            uploadResult = mCurrentUpload.execute(mUploadClient, mStorageManager);
        } catch (Exception e) {
            Timber.e(e, "Error uploading");
            uploadResult = new RemoteOperationResult(e);
        } finally {
            Pair<UploadFileOperation, String> removeResult;
            if (mCurrentUpload.wasRenamed()) {
                removeResult = mPendingUploads.removePayload(mCurrentAccount.name, mCurrentUpload.getOldFile().getRemotePath());
            /* TODO: grant that name is also updated for mCurrentUpload.getOCUploadId */
            } else {
                removeResult = mPendingUploads.removePayload(mCurrentAccount.name, mCurrentUpload.getRemotePath());
            }
            if (uploadResult != null && !uploadResult.isSuccess()) {
                TransferRequester requester = new TransferRequester();
                int jobId = mPendingUploads.buildKey(mCurrentAccount.name, mCurrentUpload.getRemotePath()).hashCode();
                if (uploadResult.getException() != null) {
                    // if failed due to lack of connectivity, schedule an automatic retry
                    if (requester.shouldScheduleRetry(this, uploadResult.getException())) {
                        requester.scheduleUpload(this, jobId, mCurrentAccount.name, mCurrentUpload.getRemotePath());
                        uploadResult = new RemoteOperationResult(ResultCode.NO_NETWORK_CONNECTION);
                    } else {
                        String stringToLog = String.format("Exception in upload, network is OK, no retry scheduled for %1s in %2s", mCurrentUpload.getRemotePath(), mCurrentAccount.name);
                        Timber.v("%s", stringToLog);
                    }
                } else if (uploadResult.getCode() == ResultCode.DELAYED_FOR_WIFI) {
                    // if failed due to the upload is delayed for wifi, schedule automatic retry as well
                    requester.scheduleUpload(this, jobId, mCurrentAccount.name, mCurrentUpload.getRemotePath());
                }
            } else {
                String stringToLog = String.format("Success OR fail without exception for %1s in %2s", mCurrentUpload.getRemotePath(), mCurrentAccount.name);
                Timber.v("%s", stringToLog);
            }
            if (uploadResult != null) {
                mUploadsStorageManager.updateDatabaseUploadResult(uploadResult, mCurrentUpload);
                // / notify result
                notifyUploadResult(mCurrentUpload, uploadResult);
            }
            sendBroadcastUploadFinished(mCurrentUpload, uploadResult, removeResult.second);
        }
    }
}
Also used : RemoteOperationResult(com.owncloud.android.lib.common.operations.RemoteOperationResult) FileDataStorageManager(com.owncloud.android.datamodel.FileDataStorageManager) OwnCloudAccount(com.owncloud.android.lib.common.OwnCloudAccount) UploadFileOperation(com.owncloud.android.operations.UploadFileOperation) ChunkedUploadFileOperation(com.owncloud.android.operations.ChunkedUploadFileOperation)

Example 3 with UploadFileOperation

use of com.owncloud.android.operations.UploadFileOperation in project android by nextcloud.

the class AbstractIT method uploadOCUpload.

public void uploadOCUpload(OCUpload ocUpload) {
    ConnectivityService connectivityServiceMock = new ConnectivityService() {

        @Override
        public boolean isInternetWalled() {
            return false;
        }

        @Override
        public Connectivity getConnectivity() {
            return Connectivity.CONNECTED_WIFI;
        }
    };
    PowerManagementService powerManagementServiceMock = new PowerManagementService() {

        @NonNull
        @Override
        public BatteryStatus getBattery() {
            return new BatteryStatus();
        }

        @Override
        public boolean isPowerSavingEnabled() {
            return false;
        }

        @Override
        public boolean isPowerSavingExclusionAvailable() {
            return false;
        }
    };
    UserAccountManager accountManager = UserAccountManagerImpl.fromContext(targetContext);
    UploadsStorageManager uploadsStorageManager = new UploadsStorageManager(accountManager, targetContext.getContentResolver());
    UploadFileOperation newUpload = new UploadFileOperation(uploadsStorageManager, connectivityServiceMock, powerManagementServiceMock, user, null, ocUpload, NameCollisionPolicy.DEFAULT, FileUploader.LOCAL_BEHAVIOUR_COPY, targetContext, false, false, getStorageManager());
    newUpload.addRenameUploadListener(() -> {
    // dummy
    });
    newUpload.setRemoteFolderToBeCreated();
    RemoteOperationResult result = newUpload.execute(client);
    assertTrue(result.getLogMessage(), result.isSuccess());
}
Also used : UserAccountManager(com.nextcloud.client.account.UserAccountManager) ConnectivityService(com.nextcloud.client.network.ConnectivityService) PowerManagementService(com.nextcloud.client.device.PowerManagementService) BatteryStatus(com.nextcloud.client.device.BatteryStatus) RemoteOperationResult(com.owncloud.android.lib.common.operations.RemoteOperationResult) UploadsStorageManager(com.owncloud.android.datamodel.UploadsStorageManager) UploadFileOperation(com.owncloud.android.operations.UploadFileOperation)

Example 4 with UploadFileOperation

use of com.owncloud.android.operations.UploadFileOperation in project android by nextcloud.

the class AbstractOnServerIT method uploadOCUpload.

public void uploadOCUpload(OCUpload ocUpload, int localBehaviour) {
    ConnectivityService connectivityServiceMock = new ConnectivityService() {

        @Override
        public boolean isInternetWalled() {
            return false;
        }

        @Override
        public Connectivity getConnectivity() {
            return Connectivity.CONNECTED_WIFI;
        }
    };
    PowerManagementService powerManagementServiceMock = new PowerManagementService() {

        @NonNull
        @Override
        public BatteryStatus getBattery() {
            return new BatteryStatus();
        }

        @Override
        public boolean isPowerSavingEnabled() {
            return false;
        }

        @Override
        public boolean isPowerSavingExclusionAvailable() {
            return false;
        }
    };
    UserAccountManager accountManager = UserAccountManagerImpl.fromContext(targetContext);
    UploadsStorageManager uploadsStorageManager = new UploadsStorageManager(accountManager, targetContext.getContentResolver());
    UploadFileOperation newUpload = new UploadFileOperation(uploadsStorageManager, connectivityServiceMock, powerManagementServiceMock, user, null, ocUpload, NameCollisionPolicy.DEFAULT, localBehaviour, targetContext, false, false, getStorageManager());
    newUpload.addRenameUploadListener(() -> {
    // dummy
    });
    newUpload.setRemoteFolderToBeCreated();
    RemoteOperationResult result = newUpload.execute(client);
    assertTrue(result.getLogMessage(), result.isSuccess());
    OCFile parentFolder = getStorageManager().getFileByEncryptedRemotePath(new File(ocUpload.getRemotePath()).getParent() + "/");
    String uploadedFileName = new File(ocUpload.getRemotePath()).getName();
    OCFile uploadedFile = getStorageManager().getFileByDecryptedRemotePath(parentFolder.getDecryptedRemotePath() + uploadedFileName);
    assertNotNull(uploadedFile.getRemoteId());
    if (localBehaviour == FileUploader.LOCAL_BEHAVIOUR_COPY || localBehaviour == FileUploader.LOCAL_BEHAVIOUR_MOVE) {
        assertTrue(new File(uploadedFile.getStoragePath()).exists());
    }
}
Also used : UserAccountManager(com.nextcloud.client.account.UserAccountManager) OCFile(com.owncloud.android.datamodel.OCFile) ConnectivityService(com.nextcloud.client.network.ConnectivityService) PowerManagementService(com.nextcloud.client.device.PowerManagementService) BatteryStatus(com.nextcloud.client.device.BatteryStatus) RemoteOperationResult(com.owncloud.android.lib.common.operations.RemoteOperationResult) UploadsStorageManager(com.owncloud.android.datamodel.UploadsStorageManager) UploadFileOperation(com.owncloud.android.operations.UploadFileOperation) RemoteFile(com.owncloud.android.lib.resources.files.model.RemoteFile) OCFile(com.owncloud.android.datamodel.OCFile) File(java.io.File)

Example 5 with UploadFileOperation

use of com.owncloud.android.operations.UploadFileOperation in project android by nextcloud.

the class UploadIT method testUploadOnWifiOnlyButNoWifi.

@Test
public void testUploadOnWifiOnlyButNoWifi() {
    ConnectivityService connectivityServiceMock = new ConnectivityService() {

        @Override
        public boolean isInternetWalled() {
            return false;
        }

        @Override
        public Connectivity getConnectivity() {
            return new Connectivity(true, false, false, true);
        }
    };
    OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt", FOLDER + "noWifi.txt", account.name);
    ocUpload.setUseWifiOnly(true);
    UploadFileOperation newUpload = new UploadFileOperation(uploadsStorageManager, connectivityServiceMock, powerManagementServiceMock, user, null, ocUpload, NameCollisionPolicy.DEFAULT, FileUploader.LOCAL_BEHAVIOUR_COPY, targetContext, true, false, getStorageManager());
    newUpload.setRemoteFolderToBeCreated();
    newUpload.addRenameUploadListener(() -> {
    // dummy
    });
    RemoteOperationResult result = newUpload.execute(client);
    assertFalse(result.toString(), result.isSuccess());
    assertEquals(RemoteOperationResult.ResultCode.DELAYED_FOR_WIFI, result.getCode());
}
Also used : OCUpload(com.owncloud.android.db.OCUpload) ConnectivityService(com.nextcloud.client.network.ConnectivityService) RemoteOperationResult(com.owncloud.android.lib.common.operations.RemoteOperationResult) Connectivity(com.nextcloud.client.network.Connectivity) UploadFileOperation(com.owncloud.android.operations.UploadFileOperation) Test(org.junit.Test)

Aggregations

UploadFileOperation (com.owncloud.android.operations.UploadFileOperation)13 RemoteOperationResult (com.owncloud.android.lib.common.operations.RemoteOperationResult)9 OCUpload (com.owncloud.android.db.OCUpload)8 Test (org.junit.Test)6 FileDataStorageManager (com.owncloud.android.datamodel.FileDataStorageManager)5 ConnectivityService (com.nextcloud.client.network.ConnectivityService)4 OCFile (com.owncloud.android.datamodel.OCFile)4 File (java.io.File)4 BatteryStatus (com.nextcloud.client.device.BatteryStatus)3 PowerManagementService (com.nextcloud.client.device.PowerManagementService)3 OwnCloudAccount (com.owncloud.android.lib.common.OwnCloudAccount)3 UserAccountManager (com.nextcloud.client.account.UserAccountManager)2 Connectivity (com.nextcloud.client.network.Connectivity)2 UploadsStorageManager (com.owncloud.android.datamodel.UploadsStorageManager)2 ChunkedUploadFileOperation (com.owncloud.android.operations.ChunkedUploadFileOperation)2 Account (android.accounts.Account)1 SuppressLint (android.annotation.SuppressLint)1 Message (android.os.Message)1 Parcelable (android.os.Parcelable)1 User (com.nextcloud.client.account.User)1