Merge pull request #923 from owncloud/create_folder_during_upload_pr_701_with_develop

Create folder during upload  (PR#701) and bug fixes
This commit is contained in:
David A. Velasco 2015-03-25 09:29:13 +01:00
commit 30b72638a6
4 changed files with 211 additions and 68 deletions

View file

@ -31,10 +31,29 @@
android:layout_height="fill_parent" android:divider="@drawable/uploader_list_separator"
android:dividerHeight="1dip"></ListView>
</FrameLayout>
<LinearLayout android:id="@+id/linearLayout1"
android:layout_width="fill_parent" android:layout_alignParentBottom="true" android:layout_height="wrap_content" android:orientation="vertical">
<Button android:layout_gravity="bottom" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:id="@+id/uploader_choose_folder"
android:text="@string/uploader_btn_upload_text"/>
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal" >
<Button
android:id="@+id/uploader_new_folder"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_weight="1"
android:text="@string/uploader_btn_new_folder_text" />
<Button
android:id="@+id/uploader_choose_folder"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_weight="1"
android:text="@string/uploader_btn_upload_text" />
</LinearLayout>
</RelativeLayout>

View file

@ -53,6 +53,7 @@
<string name="sync_string_files">Files</string>
<string name="setup_btn_connect">Connect</string>
<string name="uploader_btn_upload_text">Upload</string>
<string name="uploader_btn_new_folder_text">New folder</string>
<string name="uploader_top_message">Choose upload folder:</string>
<string name="uploader_wrn_no_account_title">No account found</string>
<string name="uploader_wrn_no_account_text">There are no %1$s accounts on your device. Please setup an account first.</string>

View file

@ -98,10 +98,10 @@ public class FileActivity extends SherlockFragmentActivity
private boolean mRedirectingToSetupAccount = false;
/** Flag to signal when the value of mAccount was set */
private boolean mAccountWasSet;
protected boolean mAccountWasSet;
/** Flag to signal when the value of mAccount was restored from a saved state */
private boolean mAccountWasRestored;
protected boolean mAccountWasRestored;
/** Flag to signal if the activity is launched by a notification */
private boolean mFromNotification;
@ -243,7 +243,7 @@ public class FileActivity extends SherlockFragmentActivity
* @param account New {@link Account} to set.
* @param savedAccount When 'true', account was retrieved from a saved instance state.
*/
private void setAccount(Account account, boolean savedAccount) {
protected void setAccount(Account account, boolean savedAccount) {
Account oldAccount = mAccount;
boolean validAccount = (account != null && AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), account.name));
if (validAccount) {
@ -341,6 +341,10 @@ public class FileActivity extends SherlockFragmentActivity
return mAccount;
}
protected void setAccount(Account account) {
mAccount = account;
}
/**
* @return Value of mFromNotification: True if the Activity is launched by a notification
*/

View file

@ -29,14 +29,6 @@ import java.util.List;
import java.util.Stack;
import java.util.Vector;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.lib.common.utils.Log_OC;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.AlertDialog;
@ -49,6 +41,7 @@ import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources.NotFoundException;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
@ -62,29 +55,42 @@ import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockListActivity;
import com.actionbarsherlock.view.MenuItem;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.lib.common.operations.RemoteOperation;
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.utils.DisplayUtils;
import com.owncloud.android.utils.ErrorMessageAdapter;
/**
* This can be used to upload things to an ownCloud instance.
*/
public class Uploader extends SherlockListActivity implements OnItemClickListener, android.view.View.OnClickListener {
private static final String TAG = "ownCloudUploader";
public class Uploader extends FileActivity
implements OnItemClickListener, android.view.View.OnClickListener {
private static final String TAG = Uploader.class.getSimpleName();
private Account mAccount;
private AccountManager mAccountManager;
private Stack<String> mParents;
private ArrayList<Parcelable> mStreamsToUpload;
private boolean mCreateDir;
private String mUploadPath;
private FileDataStorageManager mStorageManager;
private OCFile mFile;
private boolean mAccountSelected;
private final static int DIALOG_NO_ACCOUNT = 0;
private final static int DIALOG_WAITING = 1;
private final static int DIALOG_NO_STREAM = 2;
@ -92,36 +98,72 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
private final static int REQUEST_CODE_SETUP_ACCOUNT = 0;
private final static String KEY_PARENTS = "PARENTS";
private final static String KEY_FILE = "FILE";
private final static String KEY_ACCOUNT_SELECTED = "ACCOUNT_SELECTED";
@Override
protected void onCreate(Bundle savedInstanceState) {
prepareStreamsToUpload();
if (savedInstanceState == null) {
mParents = new Stack<String>();
mAccountSelected = false;
} else {
mParents = (Stack<String>) savedInstanceState.getSerializable(KEY_PARENTS);
mFile = savedInstanceState.getParcelable(KEY_FILE);
mAccountSelected = savedInstanceState.getBoolean(KEY_ACCOUNT_SELECTED);
}
super.onCreate(savedInstanceState);
mParents = new Stack<String>();
ActionBar actionBar = getSupportActionBar();
actionBar.setIcon(DisplayUtils.getSeasonalIconId());
if (prepareStreamsToUpload()) {
}
@Override
protected void setAccount(Account account, boolean savedAccount) {
if (somethingToUpload()) {
mAccountManager = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE);
Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAccountType());
if (accounts.length == 0) {
Log_OC.i(TAG, "No ownCloud account is available");
showDialog(DIALOG_NO_ACCOUNT);
} else if (accounts.length > 1) {
Log_OC.i(TAG, "More then one ownCloud is available");
} else if (accounts.length > 1 && !mAccountSelected) {
Log_OC.i(TAG, "More than one ownCloud is available");
showDialog(DIALOG_MULTIPLE_ACCOUNT);
} else {
mAccount = accounts[0];
mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
initTargetFolder();
populateDirectoryList();
if (!savedAccount) {
setAccount(accounts[0]);
}
}
} else {
showDialog(DIALOG_NO_STREAM);
}
super.setAccount(account, savedAccount);
}
@Override
protected void onAccountSet(boolean stateWasRecovered) {
super.onAccountSet(mAccountWasRestored);
initTargetFolder();
populateDirectoryList();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
Log_OC.d(TAG, "onSaveInstanceState() start");
super.onSaveInstanceState(outState);
outState.putSerializable(KEY_PARENTS, mParents);
//outState.putParcelable(KEY_ACCOUNT, mAccount);
outState.putParcelable(KEY_FILE, mFile);
outState.putBoolean(KEY_ACCOUNT_SELECTED, mAccountSelected);
Log_OC.d(TAG, "onSaveInstanceState() end");
}
@Override
protected Dialog onCreateDialog(final int id) {
final AlertDialog.Builder builder = new Builder(this);
@ -135,7 +177,8 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
case DIALOG_NO_ACCOUNT:
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setTitle(R.string.uploader_wrn_no_account_title);
builder.setMessage(String.format(getString(R.string.uploader_wrn_no_account_text), getString(R.string.app_name)));
builder.setMessage(String.format(
getString(R.string.uploader_wrn_no_account_text), getString(R.string.app_name)));
builder.setCancelable(false);
builder.setPositiveButton(R.string.uploader_wrn_no_account_setup_btn_text, new OnClickListener() {
@Override
@ -168,18 +211,20 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
});
return builder.create();
case DIALOG_MULTIPLE_ACCOUNT:
CharSequence ac[] = new CharSequence[mAccountManager.getAccountsByType(MainApp.getAccountType()).length];
CharSequence ac[] = new CharSequence[
mAccountManager.getAccountsByType(MainApp.getAccountType()).length];
for (int i = 0; i < ac.length; ++i) {
ac[i] = DisplayUtils.convertIdn(mAccountManager.getAccountsByType(MainApp.getAccountType())[i].name, false);
ac[i] = DisplayUtils.convertIdn(
mAccountManager.getAccountsByType(MainApp.getAccountType())[i].name, false);
}
builder.setTitle(R.string.common_choose_account);
builder.setItems(ac, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mAccount = mAccountManager.getAccountsByType(MainApp.getAccountType())[which];
mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
initTargetFolder();
populateDirectoryList();
setAccount(mAccountManager.getAccountsByType(MainApp.getAccountType())[which]);
onAccountSet(mAccountWasRestored);
dialog.dismiss();
mAccountSelected = true;
}
});
builder.setCancelable(true);
@ -241,7 +286,7 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// click on folder in the list
Log_OC.d(TAG, "on item click");
Vector<OCFile> tmpfiles = mStorageManager.getFolderContent(mFile);
Vector<OCFile> tmpfiles = getStorageManager().getFolderContent(mFile);
if (tmpfiles.size() <= 0) return;
// filter on dirtype
Vector<OCFile> files = new Vector<OCFile>();
@ -260,7 +305,8 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
// click on button
switch (v.getId()) {
case R.id.uploader_choose_folder:
mUploadPath = ""; // first element in mParents is root dir, represented by ""; init mUploadPath with "/" results in a "//" prefix
mUploadPath = ""; // first element in mParents is root dir, represented by "";
// init mUploadPath with "/" results in a "//" prefix
for (String p : mParents)
mUploadPath += p + OCFile.PATH_SEPARATOR;
Log_OC.d(TAG, "Uploading file to dir " + mUploadPath);
@ -268,6 +314,13 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
uploadFiles();
break;
case R.id.uploader_new_folder:
CreateFolderDialogFragment dialog = CreateFolderDialogFragment.newInstance(mFile);
dialog.show(getSupportFragmentManager(), "createdirdialog");
break;
default:
throw new IllegalArgumentException("Wrong element clicked");
}
@ -289,7 +342,7 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
// there is no need for checking for is there more then one
// account at this point
// since account setup can set only one account at time
mAccount = accounts[0];
setAccount(accounts[0]);
populateDirectoryList();
}
}
@ -297,6 +350,8 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
private void populateDirectoryList() {
setContentView(R.layout.uploader_layout);
ListView mListView = (ListView) findViewById(android.R.id.list);
String current_dir = mParents.peek();
if(current_dir.equals("")){
@ -314,9 +369,9 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
Log_OC.d(TAG, "Populating view with content of : " + full_path);
mFile = mStorageManager.getFileByPath(full_path);
mFile = getStorageManager().getFileByPath(full_path);
if (mFile != null) {
Vector<OCFile> files = mStorageManager.getFolderContent(mFile);
Vector<OCFile> files = getStorageManager().getFolderContent(mFile);
List<HashMap<String, Object>> data = new LinkedList<HashMap<String,Object>>();
for (OCFile f : files) {
HashMap<String, Object> h = new HashMap<String, Object>();
@ -330,10 +385,15 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
R.layout.uploader_list_item_layout,
new String[] {"dirname"},
new int[] {R.id.textView1});
setListAdapter(sa);
Button btn = (Button) findViewById(R.id.uploader_choose_folder);
btn.setOnClickListener(this);
getListView().setOnItemClickListener(this);
mListView.setAdapter(sa);
Button btnChooseFolder = (Button) findViewById(R.id.uploader_choose_folder);
btnChooseFolder.setOnClickListener(this);
Button btnNewFolder = (Button) findViewById(R.id.uploader_new_folder);
btnNewFolder.setOnClickListener(this);
mListView.setOnItemClickListener(this);
}
}
@ -345,13 +405,16 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
return full_path;
}
private boolean prepareStreamsToUpload() {
private void prepareStreamsToUpload() {
if (getIntent().getAction().equals(Intent.ACTION_SEND)) {
mStreamsToUpload = new ArrayList<Parcelable>();
mStreamsToUpload.add(getIntent().getParcelableExtra(Intent.EXTRA_STREAM));
} else if (getIntent().getAction().equals(Intent.ACTION_SEND_MULTIPLE)) {
mStreamsToUpload = getIntent().getParcelableArrayListExtra(Intent.EXTRA_STREAM);
}
}
private boolean somethingToUpload() {
return (mStreamsToUpload != null && mStreamsToUpload.get(0) != null);
}
@ -371,38 +434,52 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
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);
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)));
remote.add(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, null, null);
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,
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)));
remote.add(mUploadPath +
c.getString(c.getColumnIndex(Video.Media.DISPLAY_NAME)));
}
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, null, null);
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,
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)));
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 occured to me that sometimes apps send their name into the URI
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];
@ -413,7 +490,8 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
}
} else if (uri.getScheme().equals("file")) {
String filePath = Uri.decode(uri.toString()).replace(uri.getScheme() + "://", "");
String filePath = Uri.decode(uri.toString()).replace(uri.getScheme() +
"://", "");
if (filePath.contains("mnt")) {
String splitedFilePath[] = filePath.split("/mnt");
filePath = splitedFilePath[1];
@ -433,8 +511,9 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
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, mAccount);
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
@ -447,19 +526,59 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
}
} catch (SecurityException e) {
String message = String.format(getString(R.string.uploader_error_forbidden_content), getString(R.string.app_name));
String message = String.format(getString(R.string.uploader_error_forbidden_content),
getString(R.string.app_name));
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
}
@Override
public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
super.onRemoteOperationFinish(operation, result);
if (operation instanceof CreateFolderOperation) {
onCreateFolderOperationFinish((CreateFolderOperation)operation, result);
}
}
/**
* Updates the view associated to the activity after the finish of an operation
* trying create a new folder
*
* @param operation Creation operation performed.
* @param result Result of the creation.
*/
private void onCreateFolderOperationFinish(CreateFolderOperation operation,
RemoteOperationResult result) {
if (result.isSuccess()) {
dismissLoadingDialog();
populateDirectoryList();
} else {
dismissLoadingDialog();
try {
Toast msg = Toast.makeText(this,
ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
Toast.LENGTH_LONG);
msg.show();
} catch (NotFoundException e) {
Log_OC.e(TAG, "Error while trying to show fail message " , e);
}
}
}
/**
* Loads the target folder initialize shown to the user.
*
* The target account has to be chosen before this method is called.
*/
private void initTargetFolder() {
if (mStorageManager == null) {
throw new IllegalStateException("Do not call this method before initializing mStorageManager");
if (getStorageManager() == null) {
throw new IllegalStateException("Do not call this method before " +
"initializing mStorageManager");
}
SharedPreferences appPreferences = PreferenceManager
@ -476,7 +595,7 @@ public class Uploader extends SherlockListActivity implements OnItemClickListene
mParents.add(dir);
}
//Make sure that path still exists, if it doesn't pop the stack and try the previous path
while(!mStorageManager.fileExists(generatePath(mParents)) && mParents.size() > 1){
while(!getStorageManager().fileExists(generatePath(mParents)) && mParents.size() > 1){
mParents.pop();
}
}