|
@@ -2,6 +2,7 @@
|
|
|
* ownCloud Android client application
|
|
|
*
|
|
|
* @author Bartek Przybylski
|
|
|
+ * @author masensio
|
|
|
* Copyright (C) 2012 Bartek Przybylski
|
|
|
* Copyright (C) 2015 ownCloud Inc.
|
|
|
*
|
|
@@ -29,6 +30,7 @@ import java.util.List;
|
|
|
import java.util.Stack;
|
|
|
import java.util.Vector;
|
|
|
|
|
|
+
|
|
|
import android.accounts.Account;
|
|
|
import android.accounts.AccountManager;
|
|
|
import android.app.AlertDialog;
|
|
@@ -47,9 +49,13 @@ import android.net.Uri;
|
|
|
import android.os.Bundle;
|
|
|
import android.os.Parcelable;
|
|
|
import android.preference.PreferenceManager;
|
|
|
+import android.provider.MediaStore;
|
|
|
import android.provider.MediaStore.Audio;
|
|
|
import android.provider.MediaStore.Images;
|
|
|
import android.provider.MediaStore.Video;
|
|
|
+import android.support.v4.app.Fragment;
|
|
|
+import android.support.v4.app.FragmentManager;
|
|
|
+import android.support.v4.app.FragmentTransaction;
|
|
|
import android.view.View;
|
|
|
import android.widget.AdapterView;
|
|
|
import android.widget.AdapterView.OnItemClickListener;
|
|
@@ -71,6 +77,8 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
|
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
|
|
import com.owncloud.android.operations.CreateFolderOperation;
|
|
|
import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
|
|
|
+import com.owncloud.android.ui.dialog.LoadingDialog;
|
|
|
+import com.owncloud.android.utils.CopyTmpFileAsyncTask;
|
|
|
import com.owncloud.android.utils.DisplayUtils;
|
|
|
import com.owncloud.android.utils.ErrorMessageAdapter;
|
|
|
|
|
@@ -79,7 +87,8 @@ import com.owncloud.android.utils.ErrorMessageAdapter;
|
|
|
* This can be used to upload things to an ownCloud instance.
|
|
|
*/
|
|
|
public class Uploader extends FileActivity
|
|
|
- implements OnItemClickListener, android.view.View.OnClickListener {
|
|
|
+ implements OnItemClickListener, android.view.View.OnClickListener,
|
|
|
+ CopyTmpFileAsyncTask.OnCopyTmpFileTaskListener {
|
|
|
|
|
|
private static final String TAG = Uploader.class.getSimpleName();
|
|
|
|
|
@@ -90,6 +99,10 @@ public class Uploader extends FileActivity
|
|
|
private String mUploadPath;
|
|
|
private OCFile mFile;
|
|
|
private boolean mAccountSelected;
|
|
|
+ private boolean mAccountSelectionShowing;
|
|
|
+
|
|
|
+ private ArrayList<String> mRemoteCacheData;
|
|
|
+ private int mNumCacheFile;
|
|
|
|
|
|
private final static int DIALOG_NO_ACCOUNT = 0;
|
|
|
private final static int DIALOG_WAITING = 1;
|
|
@@ -101,6 +114,11 @@ public class Uploader extends FileActivity
|
|
|
private final static String KEY_PARENTS = "PARENTS";
|
|
|
private final static String KEY_FILE = "FILE";
|
|
|
private final static String KEY_ACCOUNT_SELECTED = "ACCOUNT_SELECTED";
|
|
|
+ private final static String KEY_ACCOUNT_SELECTION_SHOWING = "ACCOUNT_SELECTION_SHOWING";
|
|
|
+ private final static String KEY_NUM_CACHE_FILE = "NUM_CACHE_FILE";
|
|
|
+ private final static String KEY_REMOTE_CACHE_DATA = "REMOTE_CACHE_DATA";
|
|
|
+
|
|
|
+ private static final String DIALOG_WAIT_COPY_FILE = "DIALOG_WAIT_COPY_FILE";
|
|
|
|
|
|
@Override
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
@@ -109,13 +127,27 @@ public class Uploader extends FileActivity
|
|
|
if (savedInstanceState == null) {
|
|
|
mParents = new Stack<String>();
|
|
|
mAccountSelected = false;
|
|
|
+ mAccountSelectionShowing = false;
|
|
|
+ mNumCacheFile = 0;
|
|
|
+
|
|
|
+ // ArrayList for files with path in private storage
|
|
|
+ mRemoteCacheData = new ArrayList<String>();
|
|
|
} else {
|
|
|
mParents = (Stack<String>) savedInstanceState.getSerializable(KEY_PARENTS);
|
|
|
mFile = savedInstanceState.getParcelable(KEY_FILE);
|
|
|
mAccountSelected = savedInstanceState.getBoolean(KEY_ACCOUNT_SELECTED);
|
|
|
+ mAccountSelectionShowing = savedInstanceState.getBoolean(KEY_ACCOUNT_SELECTION_SHOWING);
|
|
|
+ mNumCacheFile = savedInstanceState.getInt(KEY_NUM_CACHE_FILE);
|
|
|
+ mRemoteCacheData = savedInstanceState.getStringArrayList(KEY_REMOTE_CACHE_DATA);
|
|
|
}
|
|
|
+
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
|
+ if (mAccountSelected) {
|
|
|
+ setAccount((Account) savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
ActionBar actionBar = getSupportActionBar();
|
|
|
actionBar.setIcon(DisplayUtils.getSeasonalIconId());
|
|
|
|
|
@@ -129,9 +161,10 @@ public class Uploader extends FileActivity
|
|
|
if (accounts.length == 0) {
|
|
|
Log_OC.i(TAG, "No ownCloud account is available");
|
|
|
showDialog(DIALOG_NO_ACCOUNT);
|
|
|
- } else if (accounts.length > 1 && !mAccountSelected) {
|
|
|
+ } else if (accounts.length > 1 && !mAccountSelected && !mAccountSelectionShowing) {
|
|
|
Log_OC.i(TAG, "More than one ownCloud is available");
|
|
|
showDialog(DIALOG_MULTIPLE_ACCOUNT);
|
|
|
+ mAccountSelectionShowing = true;
|
|
|
} else {
|
|
|
if (!savedAccount) {
|
|
|
setAccount(accounts[0]);
|
|
@@ -160,6 +193,10 @@ public class Uploader extends FileActivity
|
|
|
//outState.putParcelable(KEY_ACCOUNT, mAccount);
|
|
|
outState.putParcelable(KEY_FILE, mFile);
|
|
|
outState.putBoolean(KEY_ACCOUNT_SELECTED, mAccountSelected);
|
|
|
+ outState.putBoolean(KEY_ACCOUNT_SELECTION_SHOWING, mAccountSelectionShowing);
|
|
|
+ outState.putInt(KEY_NUM_CACHE_FILE, mNumCacheFile);
|
|
|
+ outState.putStringArrayList(KEY_REMOTE_CACHE_DATA, mRemoteCacheData);
|
|
|
+ outState.putParcelable(FileActivity.EXTRA_ACCOUNT, getAccount());
|
|
|
|
|
|
Log_OC.d(TAG, "onSaveInstanceState() end");
|
|
|
}
|
|
@@ -225,12 +262,14 @@ public class Uploader extends FileActivity
|
|
|
onAccountSet(mAccountWasRestored);
|
|
|
dialog.dismiss();
|
|
|
mAccountSelected = true;
|
|
|
+ mAccountSelectionShowing = false;
|
|
|
}
|
|
|
});
|
|
|
builder.setCancelable(true);
|
|
|
builder.setOnCancelListener(new OnCancelListener() {
|
|
|
@Override
|
|
|
public void onCancel(DialogInterface dialog) {
|
|
|
+ mAccountSelectionShowing = false;
|
|
|
dialog.cancel();
|
|
|
finish();
|
|
|
}
|
|
@@ -366,7 +405,7 @@ public class Uploader extends FileActivity
|
|
|
actionBar.setHomeButtonEnabled(notRoot);
|
|
|
|
|
|
String full_path = generatePath(mParents);
|
|
|
-
|
|
|
+
|
|
|
Log_OC.d(TAG, "Populating view with content of : " + full_path);
|
|
|
|
|
|
mFile = getStorageManager().getFileByPath(full_path);
|
|
@@ -421,6 +460,7 @@ public class Uploader extends FileActivity
|
|
|
public void uploadFiles() {
|
|
|
try {
|
|
|
|
|
|
+ // ArrayList for files with path in external storage
|
|
|
ArrayList<String> local = new ArrayList<String>();
|
|
|
ArrayList<String> remote = new ArrayList<String>();
|
|
|
|
|
@@ -428,101 +468,106 @@ public class Uploader extends FileActivity
|
|
|
for (Parcelable mStream : mStreamsToUpload) {
|
|
|
|
|
|
Uri uri = (Uri) mStream;
|
|
|
- if (uri !=null) {
|
|
|
+ String data = null;
|
|
|
+ String filePath = "";
|
|
|
+
|
|
|
+ if (uri != null) {
|
|
|
if (uri.getScheme().equals("content")) {
|
|
|
-
|
|
|
- String mimeType = getContentResolver().getType(uri);
|
|
|
-
|
|
|
- if (mimeType.contains("image")) {
|
|
|
- String[] CONTENT_PROJECTION = { Images.Media.DATA,
|
|
|
- Images.Media.DISPLAY_NAME, Images.Media.MIME_TYPE,
|
|
|
- Images.Media.SIZE};
|
|
|
- Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null,
|
|
|
- null, null);
|
|
|
- c.moveToFirst();
|
|
|
- int index = c.getColumnIndex(Images.Media.DATA);
|
|
|
- String data = c.getString(index);
|
|
|
- local.add(data);
|
|
|
- remote.add(mUploadPath +
|
|
|
- c.getString(c.getColumnIndex(Images.Media.DISPLAY_NAME)));
|
|
|
-
|
|
|
- }
|
|
|
- else if (mimeType.contains("video")) {
|
|
|
- String[] CONTENT_PROJECTION = { Video.Media.DATA,
|
|
|
+ String mimeType = getContentResolver().getType(uri);
|
|
|
+
|
|
|
+ if (mimeType.contains("image")) {
|
|
|
+ String[] CONTENT_PROJECTION = { Images.Media.DATA,
|
|
|
+ Images.Media.DISPLAY_NAME, Images.Media.MIME_TYPE,
|
|
|
+ Images.Media.SIZE };
|
|
|
+ Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null,
|
|
|
+ null, null);
|
|
|
+ c.moveToFirst();
|
|
|
+ int index = c.getColumnIndex(Images.Media.DATA);
|
|
|
+ data = c.getString(index);
|
|
|
+ filePath = mUploadPath +
|
|
|
+ c.getString(c.getColumnIndex(Images.Media.DISPLAY_NAME));
|
|
|
+
|
|
|
+ } else if (mimeType.contains("video")) {
|
|
|
+ String[] CONTENT_PROJECTION = { Video.Media.DATA,
|
|
|
Video.Media.DISPLAY_NAME, Video.Media.MIME_TYPE,
|
|
|
Video.Media.SIZE, Video.Media.DATE_MODIFIED };
|
|
|
- Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null,
|
|
|
+ Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null,
|
|
|
null, null);
|
|
|
- c.moveToFirst();
|
|
|
- int index = c.getColumnIndex(Video.Media.DATA);
|
|
|
- String data = c.getString(index);
|
|
|
- local.add(data);
|
|
|
- remote.add(mUploadPath +
|
|
|
- c.getString(c.getColumnIndex(Video.Media.DISPLAY_NAME)));
|
|
|
+ c.moveToFirst();
|
|
|
+ int index = c.getColumnIndex(Video.Media.DATA);
|
|
|
+ data = c.getString(index);
|
|
|
+ filePath = mUploadPath +
|
|
|
+ c.getString(c.getColumnIndex(Video.Media.DISPLAY_NAME));
|
|
|
|
|
|
- }
|
|
|
- else if (mimeType.contains("audio")) {
|
|
|
- String[] CONTENT_PROJECTION = { Audio.Media.DATA,
|
|
|
+ } else if (mimeType.contains("audio")) {
|
|
|
+ String[] CONTENT_PROJECTION = { Audio.Media.DATA,
|
|
|
Audio.Media.DISPLAY_NAME, Audio.Media.MIME_TYPE,
|
|
|
Audio.Media.SIZE };
|
|
|
- Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null,
|
|
|
+ Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null,
|
|
|
null, null);
|
|
|
- c.moveToFirst();
|
|
|
- int index = c.getColumnIndex(Audio.Media.DATA);
|
|
|
- String data = c.getString(index);
|
|
|
- local.add(data);
|
|
|
- remote.add(mUploadPath +
|
|
|
- c.getString(c.getColumnIndex(Audio.Media.DISPLAY_NAME)));
|
|
|
-
|
|
|
- }
|
|
|
- else {
|
|
|
- String filePath = Uri.decode(uri.toString()).replace(uri.getScheme() +
|
|
|
- "://", "");
|
|
|
- // cut everything whats before mnt. It occurred to me that sometimes
|
|
|
- // apps send their name into the URI
|
|
|
- if (filePath.contains("mnt")) {
|
|
|
- String splitedFilePath[] = filePath.split("/mnt");
|
|
|
- filePath = splitedFilePath[1];
|
|
|
- }
|
|
|
- final File file = new File(filePath);
|
|
|
- local.add(file.getAbsolutePath());
|
|
|
- remote.add(mUploadPath + file.getName());
|
|
|
- }
|
|
|
-
|
|
|
+ c.moveToFirst();
|
|
|
+ int index = c.getColumnIndex(Audio.Media.DATA);
|
|
|
+ data = c.getString(index);
|
|
|
+ filePath = mUploadPath +
|
|
|
+ c.getString(c.getColumnIndex(Audio.Media.DISPLAY_NAME));
|
|
|
+
|
|
|
+ } else {
|
|
|
+ Cursor cursor = getContentResolver().query(uri,
|
|
|
+ new String[]{MediaStore.MediaColumns.DISPLAY_NAME},
|
|
|
+ null, null, null);
|
|
|
+ cursor.moveToFirst();
|
|
|
+ int nameIndex = cursor.getColumnIndex(cursor.getColumnNames()[0]);
|
|
|
+ if (nameIndex >= 0) {
|
|
|
+ filePath = mUploadPath + cursor.getString(nameIndex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
} else if (uri.getScheme().equals("file")) {
|
|
|
- String filePath = Uri.decode(uri.toString()).replace(uri.getScheme() +
|
|
|
+ filePath = Uri.decode(uri.toString()).replace(uri.getScheme() +
|
|
|
"://", "");
|
|
|
if (filePath.contains("mnt")) {
|
|
|
String splitedFilePath[] = filePath.split("/mnt");
|
|
|
filePath = splitedFilePath[1];
|
|
|
}
|
|
|
final File file = new File(filePath);
|
|
|
- local.add(file.getAbsolutePath());
|
|
|
- remote.add(mUploadPath + file.getName());
|
|
|
+ data = file.getAbsolutePath();
|
|
|
+ filePath = mUploadPath + file.getName();
|
|
|
}
|
|
|
else {
|
|
|
throw new SecurityException();
|
|
|
}
|
|
|
+ if (data == null) {
|
|
|
+ mRemoteCacheData.add(filePath);
|
|
|
+ CopyTmpFileAsyncTask copyTask = new CopyTmpFileAsyncTask(this);
|
|
|
+ Object[] params = { uri, filePath, mRemoteCacheData.size()-1,
|
|
|
+ getAccount().name, getContentResolver()};
|
|
|
+ mNumCacheFile++;
|
|
|
+ showWaitingCopyDialog();
|
|
|
+ copyTask.execute(params);
|
|
|
+ } else {
|
|
|
+ remote.add(filePath);
|
|
|
+ local.add(data);
|
|
|
+ }
|
|
|
}
|
|
|
else {
|
|
|
throw new SecurityException();
|
|
|
}
|
|
|
-
|
|
|
- Intent intent = new Intent(getApplicationContext(), FileUploader.class);
|
|
|
- intent.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_MULTIPLE_FILES);
|
|
|
- intent.putExtra(FileUploader.KEY_LOCAL_FILE, local.toArray(new String[local.size()]));
|
|
|
- intent.putExtra(FileUploader.KEY_REMOTE_FILE,
|
|
|
- remote.toArray(new String[remote.size()]));
|
|
|
- intent.putExtra(FileUploader.KEY_ACCOUNT, getAccount());
|
|
|
- startService(intent);
|
|
|
|
|
|
- //Save the path to shared preferences
|
|
|
- SharedPreferences.Editor appPrefs = PreferenceManager
|
|
|
- .getDefaultSharedPreferences(getApplicationContext()).edit();
|
|
|
- appPrefs.putString("last_upload_path", mUploadPath);
|
|
|
- appPrefs.apply();
|
|
|
+ Intent intent = new Intent(getApplicationContext(), FileUploader.class);
|
|
|
+ intent.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_MULTIPLE_FILES);
|
|
|
+ intent.putExtra(FileUploader.KEY_LOCAL_FILE, local.toArray(new String[local.size()]));
|
|
|
+ intent.putExtra(FileUploader.KEY_REMOTE_FILE,
|
|
|
+ remote.toArray(new String[remote.size()]));
|
|
|
+ intent.putExtra(FileUploader.KEY_ACCOUNT, getAccount());
|
|
|
+ startService(intent);
|
|
|
|
|
|
- finish();
|
|
|
+ //Save the path to shared preferences
|
|
|
+ SharedPreferences.Editor appPrefs = PreferenceManager
|
|
|
+ .getDefaultSharedPreferences(getApplicationContext()).edit();
|
|
|
+ appPrefs.putString("last_upload_path", mUploadPath);
|
|
|
+ appPrefs.apply();
|
|
|
+
|
|
|
+ finish();
|
|
|
}
|
|
|
|
|
|
} catch (SecurityException e) {
|
|
@@ -588,16 +633,15 @@ public class Uploader extends FileActivity
|
|
|
// "/" equals root-directory
|
|
|
if(last_path.equals("/")) {
|
|
|
mParents.add("");
|
|
|
- }
|
|
|
- else{
|
|
|
+ } else{
|
|
|
String[] dir_names = last_path.split("/");
|
|
|
for (String dir : dir_names)
|
|
|
mParents.add(dir);
|
|
|
}
|
|
|
//Make sure that path still exists, if it doesn't pop the stack and try the previous path
|
|
|
- while(!getStorageManager().fileExists(generatePath(mParents)) && mParents.size() > 1){
|
|
|
- mParents.pop();
|
|
|
- }
|
|
|
+ while(!getStorageManager().fileExists(generatePath(mParents)) && mParents.size() > 1){
|
|
|
+ mParents.pop();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
@@ -605,17 +649,67 @@ public class Uploader extends FileActivity
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
boolean retval = true;
|
|
|
switch (item.getItemId()) {
|
|
|
- case android.R.id.home: {
|
|
|
- if((mParents.size() > 1)) {
|
|
|
- onBackPressed();
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- default:
|
|
|
- retval = super.onOptionsItemSelected(item);
|
|
|
+ case android.R.id.home:
|
|
|
+ if((mParents.size() > 1)) {
|
|
|
+ onBackPressed();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ retval = super.onOptionsItemSelected(item);
|
|
|
}
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Process the result of CopyTmpFileAsyncTask
|
|
|
+ * @param result
|
|
|
+ * @param index
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void onTmpFileCopied(String result, int index) {
|
|
|
+ if (mNumCacheFile -- == 0) {
|
|
|
+ dismissWaitingCopyDialog();
|
|
|
+ }
|
|
|
+ if (result != null) {
|
|
|
+ Intent intent = new Intent(getApplicationContext(), FileUploader.class);
|
|
|
+ intent.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
|
|
|
+ intent.putExtra(FileUploader.KEY_LOCAL_FILE, result);
|
|
|
+ intent.putExtra(FileUploader.KEY_REMOTE_FILE, mRemoteCacheData.get(index));
|
|
|
+ intent.putExtra(FileUploader.KEY_ACCOUNT, getAccount());
|
|
|
+ startService(intent);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ String message = String.format(getString(R.string.uploader_error_forbidden_content),
|
|
|
+ getString(R.string.app_name));
|
|
|
+ Toast.makeText(this, message, Toast.LENGTH_LONG).show();
|
|
|
+ Log_OC.d(TAG, message);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+/**
|
|
|
+ * Show waiting for copy dialog
|
|
|
+ */
|
|
|
+ public void showWaitingCopyDialog() {
|
|
|
+ // Construct dialog
|
|
|
+ LoadingDialog loading = new LoadingDialog(
|
|
|
+ getResources().getString(R.string.wait_for_tmp_copy_from_private_storage));
|
|
|
+ FragmentManager fm = getSupportFragmentManager();
|
|
|
+ FragmentTransaction ft = fm.beginTransaction();
|
|
|
+ loading.show(ft, DIALOG_WAIT_COPY_FILE);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Dismiss waiting for copy dialog
|
|
|
+ */
|
|
|
+ public void dismissWaitingCopyDialog(){
|
|
|
+ Fragment frag = getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_COPY_FILE);
|
|
|
+ if (frag != null) {
|
|
|
+ LoadingDialog loading = (LoadingDialog) frag;
|
|
|
+ loading.dismiss();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|