/**
* ownCloud Android client application
*
* Copyright (C) 2016 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
package com.owncloud.android.ui.helpers;
import android.accounts.Account;
import android.content.ContentResolver;
import android.net.Uri;
import android.os.Parcelable;
import com.owncloud.android.R;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.operations.UploadFileOperation;
import com.owncloud.android.ui.activity.FileActivity;
import com.owncloud.android.ui.asynctasks.CopyAndUploadContentUrisTask;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.UriUtils;
import java.util.ArrayList;
import java.util.List;
/**
* This class handle both file:// and content:// URIs pointing to files to upload.
*/
public class UriUploader {
private final String TAG = UriUploader.class.getSimpleName();
private FileActivity mActivity;
private ArrayList mUrisToUpload;
private CopyAndUploadContentUrisTask.OnCopyTmpFilesTaskListener mCopyTmpTaskListener;
private int mBehaviour;
private String mUploadPath;
private Account mAccount;
private boolean mShowWaitingDialog;
private UriUploaderResultCode mCode = UriUploaderResultCode.OK;
public enum UriUploaderResultCode {
OK,
ERROR_UNKNOWN,
ERROR_NO_FILE_TO_UPLOAD,
ERROR_READ_PERMISSION_NOT_GRANTED
}
public UriUploader(
FileActivity activity,
ArrayList uris,
String uploadPath,
Account account,
int behaviour,
boolean showWaitingDialog,
CopyAndUploadContentUrisTask.OnCopyTmpFilesTaskListener copyTmpTaskListener
) {
mActivity = activity;
mUrisToUpload = uris;
mUploadPath = uploadPath;
mAccount = account;
mBehaviour = behaviour;
mShowWaitingDialog = showWaitingDialog;
mCopyTmpTaskListener = copyTmpTaskListener;
}
public UriUploaderResultCode uploadUris() {
try {
List contentUris = new ArrayList<>();
List contentRemotePaths = new ArrayList<>();
int schemeFileCounter = 0;
for (Parcelable sourceStream : mUrisToUpload) {
Uri sourceUri = (Uri) sourceStream;
if (sourceUri != null) {
String displayName = UriUtils.getDisplayNameForUri(sourceUri, mActivity);
if (displayName == null) {
displayName = generateDiplayName();
}
String remotePath = mUploadPath + displayName;
if (ContentResolver.SCHEME_CONTENT.equals(sourceUri.getScheme())) {
contentUris.add(sourceUri);
contentRemotePaths.add(remotePath);
} else if (ContentResolver.SCHEME_FILE.equals(sourceUri.getScheme())) {
/// file: uris should point to a local file, should be safe let FileUploader handle them
requestUpload(sourceUri.getPath(), remotePath);
schemeFileCounter++;
}
}
}
if (!contentUris.isEmpty()) {
/// content: uris will be copied to temporary files before calling {@link FileUploader}
copyThenUpload(contentUris.toArray(new Uri[contentUris.size()]),
contentRemotePaths.toArray(new String[contentRemotePaths.size()]));
} else if (schemeFileCounter == 0) {
mCode = UriUploaderResultCode.ERROR_NO_FILE_TO_UPLOAD;
}
} catch (SecurityException e) {
mCode = UriUploaderResultCode.ERROR_READ_PERMISSION_NOT_GRANTED;
Log_OC.e(TAG, "Permissions fail", e);
} catch (Exception e) {
mCode = UriUploaderResultCode.ERROR_UNKNOWN;
Log_OC.e(TAG, "Unexpected error", e);
}
return mCode;
}
private String generateDiplayName() {
return mActivity.getString(R.string.common_unknown) +
"-" + DisplayUtils.unixTimeToHumanReadable(System.currentTimeMillis());
}
/**
* Requests the upload of a file in the local file system to {@link FileUploader} service.
*
* The original file will be left in its original location, and will not be duplicated.
* As a side effect, the user will see the file as not uploaded when accesses to the OC app.
* This is considered as acceptable, since when a file is shared from another app to OC,
* the usual workflow will go back to the original app.
*
* @param localPath Absolute path in the local file system to the file to upload.
* @param remotePath Absolute path in the current OC account to set to the uploaded file.
*/
private void requestUpload(String localPath, String remotePath) {
FileUploader.UploadRequester requester = new FileUploader.UploadRequester();
requester.uploadNewFile(
mActivity,
mAccount,
localPath,
remotePath,
mBehaviour,
null, // MIME type will be detected from file name
false, // do not create parent folder if not existent
UploadFileOperation.CREATED_BY_USER
);
}
/**
*
* @param sourceUris Array of content:// URIs to the files to upload
* @param remotePaths Array of absolute paths to set to the uploaded files
*/
private void copyThenUpload(Uri[] sourceUris, String[] remotePaths) {
if (mShowWaitingDialog) {
mActivity.showLoadingDialog(mActivity.getResources().
getString(R.string.wait_for_tmp_copy_from_private_storage));
}
CopyAndUploadContentUrisTask copyTask = new CopyAndUploadContentUrisTask
(mCopyTmpTaskListener, mActivity);
copyTask.execute(
CopyAndUploadContentUrisTask.makeParamsToExecute(
mAccount,
sourceUris,
remotePaths,
mActivity.getContentResolver()
)
);
}
}