Merge pull request #1399 from owncloud/uploadShowsFiles_Master

Upload shows files
This commit is contained in:
Thomas Müller 2016-03-09 13:10:53 +01:00
commit ea2fe8cb4e
5 changed files with 342 additions and 84 deletions

View file

@ -29,7 +29,7 @@
android:layout_width="@dimen/file_icon_size"
android:layout_height="@dimen/file_icon_size"
android:layout_gravity="center_vertical|center"
android:src="@drawable/ic_menu_archive"
android:src="@drawable/ic_menu_archive"
android:id="@+id/thumbnail"
android:layout_marginRight="@dimen/standard_padding"/>
@ -37,9 +37,8 @@
android:text="TextView"
android:layout_width="fill_parent"
android:id="@+id/filename"
android:layout_height="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:layout_gravity="center_vertical"
android:textSize="20dip"/>
android:textSize="16sp" />
</LinearLayout>

View file

@ -436,6 +436,14 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
return mParentId;
}
/**
* get remote path of parent file
* @return remote path
*/
public String getParentRemotePath() {
return new File(getRemotePath()).getParent();
}
/**
* Check, if this file needs updating
*

View file

@ -967,7 +967,7 @@ public class FileDisplayActivity extends HookActivity
String synchFolderRemotePath =
intent.getStringExtra(FileSyncAdapter.EXTRA_FOLDER_PATH);
RemoteOperationResult synchResult =
(RemoteOperationResult)intent.getSerializableExtra(
(RemoteOperationResult) intent.getSerializableExtra(
FileSyncAdapter.EXTRA_RESULT);
boolean sameAccount = (getAccount() != null &&
accountName.equals(getAccount().name) && getStorageManager() != null);
@ -1037,9 +1037,6 @@ public class FileDisplayActivity extends HookActivity
removeStickyBroadcast(intent);
Log_OC.d(TAG, "Setting progress visibility to " + mSyncInProgress);
mProgressBar.setIndeterminate(mSyncInProgress);
//mProgressBar.setVisibility((mSyncInProgress) ? View.VISIBLE : View.INVISIBLE);
//setSupportProgressBarIndeterminateVisibility(mSyncInProgress
/*|| mRefreshSharesInProgress*/ //);
setBackgroundText();

View file

@ -30,15 +30,28 @@ 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.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.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.operations.RefreshFolderOperation;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AlertDialog.Builder;
import android.accounts.AuthenticatorException;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.IntentFilter;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
@ -49,7 +62,6 @@ 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;
@ -67,18 +79,11 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SimpleAdapter;
import android.widget.Toast;
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.utils.Log_OC;
import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.operations.CreateFolderOperation;
import com.owncloud.android.syncadapter.FileSyncAdapter;
import com.owncloud.android.ui.adapter.UploaderAdapter;
import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
import com.owncloud.android.ui.dialog.LoadingDialog;
import com.owncloud.android.utils.CopyTmpFileAsyncTask;
@ -101,6 +106,9 @@ public class Uploader extends FileActivity
private boolean mCreateDir;
private String mUploadPath;
private OCFile mFile;
private SyncBroadcastReceiver mSyncBroadcastReceiver;
private boolean mSyncInProgress = false;
private boolean mAccountSelected;
private boolean mAccountSelectionShowing;
@ -149,6 +157,13 @@ public class Uploader extends FileActivity
if (mAccountSelected) {
setAccount((Account) savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT));
}
// Listen for sync messages
IntentFilter syncIntentFilter = new IntentFilter(RefreshFolderOperation.
EVENT_SINGLE_FOLDER_CONTENTS_SYNCED);
syncIntentFilter.addAction(RefreshFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED);
mSyncBroadcastReceiver = new SyncBroadcastReceiver();
registerReceiver(mSyncBroadcastReceiver, syncIntentFilter);
}
@Override
@ -199,6 +214,14 @@ public class Uploader extends FileActivity
Log_OC.d(TAG, "onSaveInstanceState() end");
}
@Override
protected void onDestroy(){
if (mSyncBroadcastReceiver != null) {
unregisterReceiver(mSyncBroadcastReceiver);
}
super.onDestroy();
}
@Override
protected Dialog onCreateDialog(final int id) {
final AlertDialog.Builder builder = new Builder(this);
@ -230,8 +253,8 @@ public class Uploader extends FileActivity
if (android.os.Build.VERSION.SDK_INT >
android.os.Build.VERSION_CODES.ECLAIR_MR1) {
// using string value since in API7 this
// constatn is not defined
// in API7 < this constatant is defined in
// constant is not defined
// in API7 < this constant is defined in
// Settings.ADD_ACCOUNT_SETTINGS
// and Settings.EXTRA_AUTHORITIES
Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT);
@ -319,12 +342,13 @@ public class Uploader extends FileActivity
@Override
public void onBackPressed() {
if (mParents.size() <= 1) {
super.onBackPressed();
return;
} else {
mParents.pop();
String full_path = generatePath(mParents);
startSyncFolderOperation(getStorageManager().getFileByPath(full_path));
populateDirectoryList();
}
}
@ -339,13 +363,16 @@ public class Uploader extends FileActivity
// filter on dirtype
Vector<OCFile> files = new Vector<OCFile>();
for (OCFile f : tmpfiles)
if (f.isFolder())
files.add(f);
if (files.size() < position) {
throw new IndexOutOfBoundsException("Incorrect item selected");
}
mParents.push(files.get(position).getFileName());
populateDirectoryList();
if (files.get(position).isFolder()){
OCFile folderToEnter = files.get(position);
startSyncFolderOperation(folderToEnter);
mParents.push(folderToEnter.getFileName());
populateDirectoryList();
}
}
@Override
@ -420,19 +447,19 @@ public class Uploader extends FileActivity
if (mFile != null) {
// TODO Enable when "On Device" is recovered ?
Vector<OCFile> files = getStorageManager().getFolderContent(mFile/*, false*/);
List<HashMap<String, Object>> data = new LinkedList<HashMap<String,Object>>();
List<HashMap<String, OCFile>> data = new LinkedList<HashMap<String,OCFile>>();
for (OCFile f : files) {
HashMap<String, Object> h = new HashMap<String, Object>();
if (f.isFolder()) {
h.put("dirname", f.getFileName());
HashMap<String, OCFile> h = new HashMap<String, OCFile>();
h.put("dirname", f);
data.add(h);
}
}
SimpleAdapter sa = new SimpleAdapter(this,
UploaderAdapter sa = new UploaderAdapter(this,
data,
R.layout.uploader_list_item_layout,
new String[] {"dirname"},
new int[] {R.id.filename});
new int[] {R.id.filename},
getStorageManager(), getAccount());
mListView.setAdapter(sa);
Button btnChooseFolder = (Button) findViewById(R.id.uploader_choose_folder);
@ -444,6 +471,25 @@ public class Uploader extends FileActivity
mListView.setOnItemClickListener(this);
}
}
private void startSyncFolderOperation(OCFile folder) {
long currentSyncTime = System.currentTimeMillis();
mSyncInProgress = true;
// perform folder synchronization
RemoteOperation synchFolderOp = new RefreshFolderOperation( folder,
currentSyncTime,
false,
false,
false,
getStorageManager(),
getAccount(),
getApplicationContext()
);
synchFolderOp.execute(getAccount(), this, null, null);
}
private String generatePath(Stack<String> dirs) {
String full_path = "";
@ -482,55 +528,54 @@ public class Uploader extends FileActivity
if (uri != null) {
if (uri.getScheme().equals("content")) {
String mimeType = getContentResolver().getType(uri);
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));
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);
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,
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);
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,
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);
data = c.getString(index);
filePath = mUploadPath +
c.getString(c.getColumnIndex(Audio.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);
c.moveToFirst();
int index = c.getColumnIndex(Video.Media.DATA);
data = c.getString(index);
local.add(data);
remote.add(mUploadPath + c.getString(c.getColumnIndex(Video.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 (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);
c.moveToFirst();
int index = c.getColumnIndex(Audio.Media.DATA);
data = c.getString(index);
local.add(data);
remote.add(mUploadPath + c.getString(c.getColumnIndex(Audio.Media.DISPLAY_NAME)));
}
else {
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
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());
}
} else if (uri.getScheme().equals("file")) {
filePath = Uri.decode(uri.toString()).replace(uri.getScheme() +
"://", "");
@ -548,14 +593,11 @@ public class Uploader extends FileActivity
if (data == null) {
mRemoteCacheData.add(filePath);
CopyTmpFileAsyncTask copyTask = new CopyTmpFileAsyncTask(this);
Object[] params = { uri, filePath, mRemoteCacheData.size()-1,
Object[] params = {uri, filePath, mRemoteCacheData.size() - 1,
getAccount().name, getContentResolver()};
mNumCacheFile++;
showWaitingCopyDialog();
copyTask.execute(params);
} else {
remote.add(filePath);
local.add(data);
}
}
else {
@ -682,8 +724,104 @@ public class Uploader extends FileActivity
}
return retval;
}
private OCFile getCurrentFolder(){
OCFile file = mFile;
if (file != null) {
if (file.isFolder()) {
return file;
} else if (getStorageManager() != null) {
return getStorageManager().getFileByPath(file.getParentRemotePath());
}
}
return null;
}
private void browseToRoot() {
OCFile root = getStorageManager().getFileByPath(OCFile.ROOT_PATH);
mFile = root;
startSyncFolderOperation(root);
}
private class SyncBroadcastReceiver extends BroadcastReceiver {
/**
* {@link BroadcastReceiver} to enable syncing feedback in UI
*/
@Override
public void onReceive(Context context, Intent intent) {
try {
String event = intent.getAction();
Log_OC.d(TAG, "Received broadcast " + event);
String accountName = intent.getStringExtra(FileSyncAdapter.EXTRA_ACCOUNT_NAME);
String synchFolderRemotePath =
intent.getStringExtra(FileSyncAdapter.EXTRA_FOLDER_PATH);
RemoteOperationResult synchResult =
(RemoteOperationResult) intent.getSerializableExtra(
FileSyncAdapter.EXTRA_RESULT);
boolean sameAccount = (getAccount() != null &&
accountName.equals(getAccount().name) && getStorageManager() != null);
if (sameAccount) {
if (FileSyncAdapter.EVENT_FULL_SYNC_START.equals(event)) {
mSyncInProgress = true;
} else {
OCFile currentFile = (mFile == null) ? null :
getStorageManager().getFileByPath(mFile.getRemotePath());
OCFile currentDir = (getCurrentFolder() == null) ? null :
getStorageManager().getFileByPath(getCurrentFolder().getRemotePath());
if (currentDir == null) {
// current folder was removed from the server
Toast.makeText(context,
String.format(
getString(R.string.sync_current_folder_was_removed),
getCurrentFolder().getFileName()),
Toast.LENGTH_LONG)
.show();
browseToRoot();
} else {
if (currentFile == null && !mFile.isFolder()) {
// currently selected file was removed in the server, and now we know it
currentFile = currentDir;
}
if (synchFolderRemotePath != null &&
currentDir.getRemotePath().equals(synchFolderRemotePath)) {
populateDirectoryList();
}
mFile = currentFile;
}
mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) &&
!RefreshFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event));
if (RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED.
equals(event) &&
/// TODO refactor and make common
synchResult != null && !synchResult.isSuccess() &&
(synchResult.getCode() == ResultCode.UNAUTHORIZED ||
synchResult.isIdPRedirection() ||
(synchResult.isException() && synchResult.getException()
instanceof AuthenticatorException))) {
requestCredentialsUpdate(context);
}
}
removeStickyBroadcast(intent);
Log_OC.d(TAG, "Setting progress visibility to " + mSyncInProgress);
}
} catch (RuntimeException e) {
// avoid app crashes after changing the serial id of RemoteOperationResult
// in owncloud library with broadcast notifications pending to process
removeStickyBroadcast(intent);
}
}
}
/**
* Process the result of CopyTmpFileAsyncTask
* @param result
@ -708,9 +846,9 @@ public class Uploader extends FileActivity
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
Log_OC.d(TAG, message);
}
}
/**
/**
* Show waiting for copy dialog
*/
public void showWaitingCopyDialog() {

View file

@ -0,0 +1,116 @@
/**
* ownCloud Android client application
*
* @author Tobias Kaminsky
* 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 <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.ui.adapter;
import android.accounts.Account;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncDrawable;
import com.owncloud.android.utils.MimetypeIconUtil;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class UploaderAdapter extends SimpleAdapter {
private Context mContext;
private Account mAccount;
private FileDataStorageManager mStorageManager;
private LayoutInflater inflater;
public UploaderAdapter(Context context,
List<? extends Map<String, ?>> data, int resource, String[] from,
int[] to, FileDataStorageManager storageManager, Account account) {
super(context, data, resource, from, to);
mAccount = account;
mStorageManager = storageManager;
mContext = context;
inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.uploader_list_item_layout, null);
HashMap<String, OCFile> data = (HashMap<String, OCFile>) getItem(position);
OCFile file = data.get("dirname");
TextView filename = (TextView) vi.findViewById(R.id.filename);
filename.setText(file.getFileName());
ImageView fileIcon = (ImageView) vi.findViewById(R.id.thumbnail);
fileIcon.setTag(file.getFileId());
// TODO enable after #1277 is merged
// TextView lastModV = (TextView) vi.findViewById(R.id.last_mod);
// lastModV.setText(DisplayUtils.getRelativeTimestamp(mContext, file));
// get Thumbnail if file is image
if (file.isImage() && file.getRemoteId() != null){
// Thumbnail in Cache?
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
String.valueOf(file.getRemoteId())
);
if (thumbnail != null && !file.needsUpdateThumbnail()){
fileIcon.setImageBitmap(thumbnail);
} else {
// generate new Thumbnail
if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {
final ThumbnailsCacheManager.ThumbnailGenerationTask task =
new ThumbnailsCacheManager.ThumbnailGenerationTask(fileIcon, mStorageManager,
mAccount);
if (thumbnail == null) {
thumbnail = ThumbnailsCacheManager.mDefaultImg;
}
final AsyncDrawable asyncDrawable = new AsyncDrawable(
mContext.getResources(),
thumbnail,
task
);
fileIcon.setImageDrawable(asyncDrawable);
task.execute(file);
}
}
} else {
fileIcon.setImageResource(
MimetypeIconUtil.getFileTypeIconId(file.getMimetype(), file.getFileName())
);
}
return vi;
}
}