From: David A. Velasco Date: Thu, 11 Oct 2012 14:40:56 +0000 (+0200) Subject: Cancellation in uploads and access to details view pressing the status notification X-Git-Tag: oc-android-1.4.3~154 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/27112bd200e1bf30897ae94507afeeb272e267ec?ds=inline;hp=-c Cancellation in uploads and access to details view pressing the status notification --- 27112bd200e1bf30897ae94507afeeb272e267ec diff --git a/src/com/owncloud/android/files/services/FileUploader.java b/src/com/owncloud/android/files/services/FileUploader.java index 42033beb..da352edd 100644 --- a/src/com/owncloud/android/files/services/FileUploader.java +++ b/src/com/owncloud/android/files/services/FileUploader.java @@ -2,10 +2,7 @@ package com.owncloud.android.files.services; import java.io.File; import java.util.AbstractList; -import java.util.Collections; -import java.util.HashMap; import java.util.Iterator; -import java.util.Map; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -14,9 +11,7 @@ import com.owncloud.android.authenticator.AccountAuthenticator; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.InstantUploadBroadcastReceiver; -import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; import com.owncloud.android.operations.ChunkedUploadFileOperation; -import com.owncloud.android.operations.DownloadFileOperation; import com.owncloud.android.operations.RemoteOperationResult; import com.owncloud.android.operations.UploadFileOperation; import com.owncloud.android.ui.activity.FileDetailActivity; @@ -42,6 +37,7 @@ import android.os.Looper; import android.os.Message; import android.os.Process; import android.util.Log; +import android.webkit.MimeTypeMap; import android.widget.RemoteViews; import com.owncloud.android.R; @@ -76,9 +72,6 @@ public class FileUploader extends Service implements OnDatatransferProgressListe private Account mLastAccount = null, mLastAccountWhereInstantFolderWasCreated = null; private FileDataStorageManager mStorageManager; - //private AbstractList mAccounts = new Vector(); - //private AbstractList mUploads = new Vector(); - //private int mCurrentIndexUpload; private ConcurrentMap mPendingUploads = new ConcurrentHashMap(); private UploadFileOperation mCurrentUpload = null; @@ -86,9 +79,6 @@ public class FileUploader extends Service implements OnDatatransferProgressListe private Notification mNotification; private int mLastPercent; private RemoteViews mDefaultNotificationContentView; - /*private long mTotalDataToSend, mSendData; - private int mTotalFilesToSend, mPreviousPercent; - private int mSuccessCounter;*/ /** @@ -188,13 +178,16 @@ public class FileUploader extends Service implements OnDatatransferProgressListe AbstractList requestedUploads = new Vector(); String uploadKey = null; UploadFileOperation newUpload = null; + OCFile file = null; + FileDataStorageManager storageManager = new FileDataStorageManager(account, getContentResolver()); try { for (int i=0; i < localPaths.length; i++) { uploadKey = buildRemoteName(account, remotePaths[i]); + file = obtainNewOCFileToUpload(remotePaths[i], localPaths[i], ((mimeTypes!=null)?mimeTypes[i]:(String)null), forceOverwrite, storageManager); if (chunked) { - newUpload = new ChunkedUploadFileOperation(account, localPaths[i], remotePaths[i], ((mimeTypes!=null)?mimeTypes[i]:(String)null), isInstant, forceOverwrite); + newUpload = new ChunkedUploadFileOperation(account, file, isInstant, forceOverwrite); } else { - newUpload = new UploadFileOperation(account, localPaths[i], remotePaths[i], (mimeTypes!=null?mimeTypes[i]:(String)null), isInstant, forceOverwrite); + newUpload = new UploadFileOperation(account, file, isInstant, forceOverwrite); } mPendingUploads.putIfAbsent(uploadKey, newUpload); newUpload.addDatatransferProgressListener(this); @@ -246,7 +239,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe upload = mPendingUploads.remove(buildRemoteName(account, file)); } if (upload != null) { - // TODO upload.cancel(); + upload.cancel(); } } @@ -312,16 +305,6 @@ public class FileUploader extends Service implements OnDatatransferProgressListe if (mCurrentUpload != null) { - /// prepare upload statistics - /*mTotalDataToSend = mSendData = mPreviousPercent = 0; - Iterator it = mUploads.iterator(); - while (it.hasNext()) { - mTotalDataToSend += new File(it.next().getLocalPath()).length(); - } - mTotalFilesToSend = mUploads.size(); - Log.d(TAG, "Will upload " + mTotalDataToSend + " bytes, with " + mUploads.size() + " files");*/ - - notifyUploadStart(mCurrentUpload); @@ -340,15 +323,10 @@ public class FileUploader extends Service implements OnDatatransferProgressListe /// perform the upload RemoteOperationResult uploadResult = null; - long parentDirId = -1; try { - File remote = new File(mCurrentUpload.getRemotePath()); - parentDirId = mStorageManager.getFileByPath(remote.getParent().endsWith("/")?remote.getParent():remote.getParent()+"/").getFileId(); - File local = new File(mCurrentUpload.getLocalPath()); - long size = local.length(); uploadResult = mCurrentUpload.execute(mUploadClient); if (uploadResult.isSuccess()) { - saveNewOCFile(mCurrentUpload, mStorageManager, parentDirId, size); + saveUploadedFile(mCurrentUpload.getFile(), mStorageManager); } } finally { @@ -360,7 +338,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe /// notify result notifyUploadResult(uploadResult, mCurrentUpload); - sendFinalBroadcast(mCurrentUpload, uploadResult, parentDirId); + sendFinalBroadcast(mCurrentUpload, uploadResult); } @@ -389,23 +367,52 @@ public class FileUploader extends Service implements OnDatatransferProgressListe /** * Saves a new OC File after a successful upload. * - * @param upload Upload operation completed. + * @param file OCFile describing the uploaded file * @param storageManager Interface to the database where the new OCFile has to be stored. * @param parentDirId Id of the parent OCFile. - * @param size Size of the file. */ - private void saveNewOCFile(UploadFileOperation upload, FileDataStorageManager storageManager, long parentDirId, long size) { - OCFile newFile = new OCFile(upload.getRemotePath()); - newFile.setMimetype(upload.getMimeType()); - newFile.setFileLength(size); - newFile.setModificationTimestamp(System.currentTimeMillis()); + private void saveUploadedFile(OCFile file, FileDataStorageManager storageManager) { + file.setModificationTimestamp(System.currentTimeMillis()); + storageManager.saveFile(file); + } + + + private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType, boolean forceOverwrite, FileDataStorageManager storageManager) { + OCFile newFile = new OCFile(remotePath); + newFile.setStoragePath(localPath); newFile.setLastSyncDate(0); - newFile.setStoragePath(upload.getLocalPath()); + newFile.setKeepInSync(forceOverwrite); + + // size + if (localPath != null && localPath.length() > 0) { + File localFile = new File(localPath); + newFile.setFileLength(localFile.length()); + } // don't worry about not assigning size, the problems with localPath are checked when the UploadFileOperation instance is created + + // MIME type + if (mimeType == null || mimeType.length() <= 0) { + try { + mimeType = MimeTypeMap.getSingleton() + .getMimeTypeFromExtension( + remotePath.substring(remotePath.lastIndexOf('.') + 1)); + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, "Trying to find out MIME type of a file without extension: " + remotePath); + } + } + if (mimeType == null) { + mimeType = "application/octet-stream"; + } + newFile.setMimetype(mimeType); + + // parent dir + String parentPath = new File(remotePath).getParent(); + parentPath = parentPath.endsWith("/")?parentPath:parentPath+"/" ; + long parentDirId = storageManager.getFileByPath(parentPath).getFileId(); newFile.setParentId(parentDirId); - if (upload.getForceOverwrite()) - newFile.setKeepInSync(true); - storageManager.saveFile(newFile); + + return newFile; } + /** * Creates a status notification to show the upload progress @@ -420,17 +427,15 @@ public class FileUploader extends Service implements OnDatatransferProgressListe mDefaultNotificationContentView = mNotification.contentView; mNotification.contentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.progressbar_layout); mNotification.contentView.setProgressBar(R.id.status_progress, 100, 0, false); - mNotification.contentView.setTextViewText(R.id.status_text, String.format(getString(R.string.uploader_upload_in_progress_content), 0, new File(upload.getLocalPath()).getName())); + mNotification.contentView.setTextViewText(R.id.status_text, String.format(getString(R.string.uploader_upload_in_progress_content), 0, new File(upload.getStoragePath()).getName())); mNotification.contentView.setImageViewResource(R.id.status_icon, R.drawable.icon); /// includes a pending intent in the notification showing the details view of the file - /* TODO Intent showDetailsIntent = new Intent(this, FileDetailActivity.class); showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, upload.getFile()); showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, upload.getAccount()); showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, showDetailsIntent, PendingIntent.FLAG_UPDATE_CURRENT); - */ mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotification); } @@ -479,17 +484,15 @@ public class FileUploader extends Service implements OnDatatransferProgressListe mNotification.contentView = mDefaultNotificationContentView; /// includes a pending intent in the notification showing the details view of the file - /* Intent showDetailsIntent = new Intent(this, FileDetailActivity.class); showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, upload.getFile()); showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, upload.getAccount()); showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, showDetailsIntent, PendingIntent.FLAG_UPDATE_CURRENT); - */ mNotification.setLatestEventInfo( getApplicationContext(), getString(R.string.uploader_upload_succeeded_ticker), - String.format(getString(R.string.uploader_upload_succeeded_content_single), (new File(upload.getLocalPath())).getName()), + String.format(getString(R.string.uploader_upload_succeeded_content_single), (new File(upload.getStoragePath())).getName()), mNotification.contentIntent); mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotification); // NOT AN ERROR; uploader_upload_in_progress_ticker is the target, not a new notification @@ -510,7 +513,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT); finalNotification.setLatestEventInfo( getApplicationContext(), getString(R.string.uploader_upload_failed_ticker), - String.format(getString(R.string.uploader_upload_failed_content_single), (new File(upload.getLocalPath())).getName()), + String.format(getString(R.string.uploader_upload_failed_content_single), (new File(upload.getStoragePath())).getName()), finalNotification.contentIntent); mNotificationManager.notify(R.string.uploader_upload_failed_ticker, finalNotification); @@ -532,13 +535,13 @@ public class FileUploader extends Service implements OnDatatransferProgressListe * @param upload Finished upload operation * @param uploadResult Result of the upload operation */ - private void sendFinalBroadcast(UploadFileOperation upload, RemoteOperationResult uploadResult, long parentDirId) { + private void sendFinalBroadcast(UploadFileOperation upload, RemoteOperationResult uploadResult) { Intent end = new Intent(UPLOAD_FINISH_MESSAGE); - end.putExtra(EXTRA_REMOTE_PATH, upload.getRemotePath()); - end.putExtra(EXTRA_FILE_PATH, upload.getLocalPath()); + end.putExtra(EXTRA_REMOTE_PATH, upload.getRemotePath()); // real remote path, after possible automatic renaming + end.putExtra(EXTRA_FILE_PATH, upload.getStoragePath()); end.putExtra(ACCOUNT_NAME, upload.getAccount().name); end.putExtra(EXTRA_UPLOAD_RESULT, uploadResult.isSuccess()); - end.putExtra(EXTRA_PARENT_DIR_ID, parentDirId); + end.putExtra(EXTRA_PARENT_DIR_ID, upload.getFile().getParentId()); sendBroadcast(end); } diff --git a/src/com/owncloud/android/operations/ChunkedUploadFileOperation.java b/src/com/owncloud/android/operations/ChunkedUploadFileOperation.java index 3e7a29d7..6d339e00 100644 --- a/src/com/owncloud/android/operations/ChunkedUploadFileOperation.java +++ b/src/com/owncloud/android/operations/ChunkedUploadFileOperation.java @@ -28,6 +28,8 @@ import java.util.Random; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.methods.PutMethod; +import com.owncloud.android.datamodel.OCFile; + import android.accounts.Account; import android.util.Log; @@ -42,41 +44,38 @@ public class ChunkedUploadFileOperation extends UploadFileOperation { private static final String TAG = ChunkedUploadFileOperation.class.getSimpleName(); public ChunkedUploadFileOperation( Account account, - String localPath, - String remotePath, - String mimeType, + OCFile file, boolean isInstant, boolean forceOverwrite) { - super(account, localPath, remotePath, mimeType, isInstant, forceOverwrite); + super(account, file, isInstant, forceOverwrite); } @Override protected int uploadFile(WebdavClient client) throws HttpException, IOException { int status = -1; - PutMethod put = null; FileChannel channel = null; FileLock lock = null; RandomAccessFile raf = null; try { - File file = new File(getLocalPath()); + File file = new File(getStoragePath()); raf = new RandomAccessFile(file, "rw"); channel = raf.getChannel(); lock = channel.tryLock(); - ChunkFromFileChannelRequestEntity entity = new ChunkFromFileChannelRequestEntity(channel, getMimeType(), CHUNK_SIZE); + ChunkFromFileChannelRequestEntity entity = new ChunkFromFileChannelRequestEntity(channel, getMimeType(), CHUNK_SIZE, file); entity.addOnDatatransferProgressListeners(getDataTransferListeners()); long offset = 0; String uriPrefix = client.getBaseUri() + WebdavUtils.encodePath(getRemotePath()) + "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ; long chunkCount = (long) Math.ceil((double)file.length() / CHUNK_SIZE); for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) { - put = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex); - put.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER); + mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex); + mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER); entity.setOffset(offset); - put.setRequestEntity(entity); - status = client.executeMethod(put); - client.exhaustResponse(put.getResponseBodyAsStream()); - Log.d(TAG, "Upload of " + getLocalPath() + " to " + getRemotePath() + ", chunk index " + chunkIndex + ", count " + chunkCount + ", HTTP result status " + status); + mPutMethod.setRequestEntity(entity); + status = client.executeMethod(mPutMethod); + client.exhaustResponse(mPutMethod.getResponseBodyAsStream()); + Log.d(TAG, "Upload of " + getStoragePath() + " to " + getRemotePath() + ", chunk index " + chunkIndex + ", count " + chunkCount + ", HTTP result status " + status); if (!isSuccess(status)) break; } @@ -88,8 +87,8 @@ public class ChunkedUploadFileOperation extends UploadFileOperation { channel.close(); if (raf != null) raf.close(); - if (put != null) - put.releaseConnection(); // let the connection available for other methods + if (mPutMethod != null) + mPutMethod.releaseConnection(); // let the connection available for other methods } return status; } diff --git a/src/com/owncloud/android/operations/DownloadFileOperation.java b/src/com/owncloud/android/operations/DownloadFileOperation.java index a35a0163..e6120d69 100644 --- a/src/com/owncloud/android/operations/DownloadFileOperation.java +++ b/src/com/owncloud/android/operations/DownloadFileOperation.java @@ -52,7 +52,7 @@ public class DownloadFileOperation extends RemoteOperation { private static final String TAG = DownloadFileOperation.class.getCanonicalName(); - private Account mAccount = null; + private Account mAccount; private OCFile mFile; private Set mDataTransferListeners = new HashSet(); private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); @@ -90,7 +90,7 @@ public class DownloadFileOperation extends RemoteOperation { } public String getMimeType() { - String mimeType = mFile.getMimetype(); + String mimeType = mFile.getMimetype(); // TODO fix the mime types in OCFiles FOREVER if (mimeType == null || mimeType.length() <= 0) { try { mimeType = MimeTypeMap.getSingleton() diff --git a/src/com/owncloud/android/operations/UploadFileOperation.java b/src/com/owncloud/android/operations/UploadFileOperation.java index e005f179..1a7938f3 100644 --- a/src/com/owncloud/android/operations/UploadFileOperation.java +++ b/src/com/owncloud/android/operations/UploadFileOperation.java @@ -22,11 +22,13 @@ import java.io.File; import java.io.IOException; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.methods.PutMethod; import org.apache.http.HttpStatus; +import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.operations.RemoteOperation; import com.owncloud.android.operations.RemoteOperationResult; @@ -36,7 +38,6 @@ import eu.alefzero.webdav.WebdavClient; import eu.alefzero.webdav.WebdavUtils; import android.accounts.Account; import android.util.Log; -import android.webkit.MimeTypeMap; /** * Remote operation performing the upload of a file to an ownCloud server @@ -47,44 +48,31 @@ public class UploadFileOperation extends RemoteOperation { private static final String TAG = UploadFileOperation.class.getCanonicalName(); - private Account mAccount = null; - private String mLocalPath = null; + private Account mAccount; + private OCFile mFile; private String mRemotePath = null; - private String mMimeType = null; private boolean mIsInstant = false; private boolean mForceOverwrite = false; + PutMethod mPutMethod = null; private Set mDataTransferListeners = new HashSet(); + private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); public UploadFileOperation( Account account, - String localPath, - String remotePath, - String mimeType, + OCFile file, boolean isInstant, boolean forceOverwrite) { if (account == null) - throw new IllegalArgumentException("Illegal null account in UploadFileOperation creation"); - if (localPath == null || localPath.length() <= 0) - throw new IllegalArgumentException("Illegal null or empty localPath in UploadFileOperation creation"); - if (remotePath == null || remotePath.length() <= 0) - throw new IllegalArgumentException("Illegal null or empty remotePath in UploadFileOperation creation"); - - mAccount = account; - mLocalPath = localPath; - mRemotePath = remotePath; - mMimeType = mimeType; - if (mMimeType == null || mMimeType.length() <= 0) { - try { - mMimeType = MimeTypeMap.getSingleton() - .getMimeTypeFromExtension( - localPath.substring(localPath.lastIndexOf('.') + 1)); - } catch (IndexOutOfBoundsException e) { - Log.e(TAG, "Trying to find out MIME type of a file without extension: " + localPath); - } - } - if (mMimeType == null) { - mMimeType = "application/octet-stream"; + throw new IllegalArgumentException("Illegal NULL account in UploadFileOperation creation"); + if (file == null) + throw new IllegalArgumentException("Illegal NULL file in UploadFileOperation creation"); + if (file.getStoragePath() == null || file.getStoragePath().length() <= 0 || !(new File(file.getStoragePath()).exists())) { + throw new IllegalArgumentException("Illegal file in UploadFileOperation; storage path invalid or file not found: " + file.getStoragePath()); } + + mAccount = account; + mFile = file; + mRemotePath = file.getRemotePath(); mIsInstant = isInstant; mForceOverwrite = forceOverwrite; } @@ -94,16 +82,21 @@ public class UploadFileOperation extends RemoteOperation { return mAccount; } - public String getLocalPath() { - return mLocalPath; + public OCFile getFile() { + return mFile; + } + + public String getStoragePath() { + return mFile.getStoragePath(); } public String getRemotePath() { + //return mFile.getRemotePath(); // DON'T MAKE THIS ; the remotePath used can be different to mFile.getRemotePath() if mForceOverwrite is 'false'; see run(...) return mRemotePath; } public String getMimeType() { - return mMimeType; + return mFile.getMimetype(); } public boolean isInstant() { @@ -136,14 +129,25 @@ public class UploadFileOperation extends RemoteOperation { /// perform the upload nameCheckPassed = true; + synchronized(mCancellationRequested) { + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } else { + mPutMethod = new PutMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath)); + } + } int status = uploadFile(client); result = new RemoteOperationResult(isSuccess(status), status); - Log.i(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " + result.getLogMessage()); - + Log.i(TAG, "Upload of " + mFile.getStoragePath() + " to " + mRemotePath + ": " + result.getLogMessage()); + } catch (Exception e) { - result = new RemoteOperationResult(e); - Log.e(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " + result.getLogMessage() + (nameCheckPassed?"":" (while checking file existence in server)"), e); - + // TODO something cleaner + if (mCancellationRequested.get()) { + result = new RemoteOperationResult(new OperationCancelledException()); + } else { + result = new RemoteOperationResult(e); + } + Log.e(TAG, "Upload of " + mFile.getStoragePath() + " to " + mRemotePath + ": " + result.getLogMessage() + (nameCheckPassed?"":" (while checking file existence in server)"), result.getException()); } return result; @@ -155,20 +159,18 @@ public class UploadFileOperation extends RemoteOperation { } - protected int uploadFile(WebdavClient client) throws HttpException, IOException { + protected int uploadFile(WebdavClient client) throws HttpException, IOException, OperationCancelledException { int status = -1; - PutMethod put = new PutMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath)); - try { - File f = new File(mLocalPath); - FileRequestEntity entity = new FileRequestEntity(f, mMimeType); + File f = new File(mFile.getStoragePath()); + FileRequestEntity entity = new FileRequestEntity(f, getMimeType()); entity.addOnDatatransferProgressListeners(mDataTransferListeners); - put.setRequestEntity(entity); - status = client.executeMethod(put); - client.exhaustResponse(put.getResponseBodyAsStream()); + mPutMethod.setRequestEntity(entity); + status = client.executeMethod(mPutMethod); + client.exhaustResponse(mPutMethod.getResponseBodyAsStream()); } finally { - put.releaseConnection(); // let the connection available for other methods + mPutMethod.releaseConnection(); // let the connection available for other methods } return status; } @@ -211,4 +213,12 @@ public class UploadFileOperation extends RemoteOperation { } + public void cancel() { + synchronized(mCancellationRequested) { + mCancellationRequested.set(true); + if (mPutMethod != null) + mPutMethod.abort(); + } + } + } diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index b6393a51..77612e3a 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -222,7 +222,9 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements mCurrentDir = mStorageManager.getFileByPath(mCurrentDir.getRemotePath()); // mCurrentDir == null if it is not in the current account } if (mCurrentFile != null) { - mCurrentFile = mStorageManager.getFileByPath(mCurrentFile.getRemotePath()); // mCurrentFile == null if it is not in the current account + if (mCurrentFile.fileExists()) { + mCurrentFile = mStorageManager.getFileByPath(mCurrentFile.getRemotePath()); // mCurrentFile == null if it is not in the current account + } // else : keep mCurrentFile with the received value; this is currently the case of an upload in progress, when the user presses the status notification in a landscape tablet } /// Default to root if mCurrentDir was not found @@ -442,9 +444,11 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements outState.putParcelable(FileDetailFragment.EXTRA_FILE, mCurrentDir); if (mDualPane) { FileDetailFragment fragment = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG); - OCFile file = fragment.getDisplayedFile(); - if (file != null) { - outState.putParcelable(FileDetailFragment.EXTRA_FILE, file); + if (fragment != null) { + OCFile file = fragment.getDisplayedFile(); + if (file != null) { + outState.putParcelable(FileDetailFragment.EXTRA_FILE, file); + } } } Log.d(getClass().toString(), "onSaveInstanceState() end"); diff --git a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java index 10b44add..007c294f 100644 --- a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java +++ b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java @@ -247,6 +247,7 @@ public class FileDetailFragment extends SherlockFragment implements case R.id.fdDownloadBtn: { //if (FileDownloader.isDownloading(mAccount, mFile.getRemotePath())) { FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder(); + FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder(); if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) { downloaderBinder.cancel(mAccount, mFile); if (mFile.isDown()) { @@ -254,6 +255,26 @@ public class FileDetailFragment extends SherlockFragment implements } else { setButtonsForRemote(); } + + } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile)) { + uploaderBinder.cancel(mAccount, mFile); + if (!mFile.fileExists()) { + // TODO make something better + if (getActivity() instanceof FileDisplayActivity) { + // double pane + FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction(); + transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FTAG); // empty FileDetailFragment + transaction.commit(); + mContainerActivity.onFileStateChanged(); + } else { + getActivity().finish(); + } + + } else if (mFile.isDown()) { + setButtonsForDown(); + } else { + setButtonsForRemote(); + } } else { Intent i = new Intent(getActivity(), FileDownloader.class); @@ -534,6 +555,7 @@ public class FileDetailFragment extends SherlockFragment implements ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(false); ((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(false); ((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(false); + getView().findViewById(R.id.fdKeepInSync).setEnabled(false); } } @@ -549,6 +571,7 @@ public class FileDetailFragment extends SherlockFragment implements ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(true); ((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true); ((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true); + getView().findViewById(R.id.fdKeepInSync).setEnabled(true); } } @@ -563,6 +586,7 @@ public class FileDetailFragment extends SherlockFragment implements ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(false); ((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true); ((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true); + getView().findViewById(R.id.fdKeepInSync).setEnabled(true); } } diff --git a/src/eu/alefzero/webdav/ChunkFromFileChannelRequestEntity.java b/src/eu/alefzero/webdav/ChunkFromFileChannelRequestEntity.java index b7ab2613..1316315d 100644 --- a/src/eu/alefzero/webdav/ChunkFromFileChannelRequestEntity.java +++ b/src/eu/alefzero/webdav/ChunkFromFileChannelRequestEntity.java @@ -18,6 +18,7 @@ package eu.alefzero.webdav; +import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; @@ -46,23 +47,27 @@ public class ChunkFromFileChannelRequestEntity implements RequestEntity { //private final File mFile; private final FileChannel mChannel; private final String mContentType; - private final long mSize; + private final long mChunkSize; + private final File mFile; private long mOffset; - Set mListeners = new HashSet(); + private long mTransferred; + Set mDataTransferListeners = new HashSet(); private ByteBuffer mBuffer = ByteBuffer.allocate(4096); - public ChunkFromFileChannelRequestEntity(final FileChannel channel, final String contentType, long size) { + public ChunkFromFileChannelRequestEntity(final FileChannel channel, final String contentType, long chunkSize, final File file) { super(); if (channel == null) { throw new IllegalArgumentException("File may not be null"); } - if (size <= 0) { - throw new IllegalArgumentException("Size must be greater than zero"); + if (chunkSize <= 0) { + throw new IllegalArgumentException("Chunk size must be greater than zero"); } mChannel = channel; mContentType = contentType; - mSize = size; + mChunkSize = chunkSize; + mFile = file; mOffset = 0; + mTransferred = 0; } public void setOffset(long offset) { @@ -71,9 +76,9 @@ public class ChunkFromFileChannelRequestEntity implements RequestEntity { public long getContentLength() { try { - return Math.min(mSize, mChannel.size() - mChannel.position()); + return Math.min(mChunkSize, mChannel.size() - mChannel.position()); } catch (IOException e) { - return mSize; + return mChunkSize; } } @@ -86,15 +91,15 @@ public class ChunkFromFileChannelRequestEntity implements RequestEntity { } public void addOnDatatransferProgressListener(OnDatatransferProgressListener listener) { - mListeners.add(listener); + mDataTransferListeners.add(listener); } public void addOnDatatransferProgressListeners(Collection listeners) { - mListeners.addAll(listeners); + mDataTransferListeners.addAll(listeners); } public void removeOnDatatransferProgressListener(OnDatatransferProgressListener listener) { - mListeners.remove(listener); + mDataTransferListeners.remove(listener); } @@ -104,13 +109,16 @@ public class ChunkFromFileChannelRequestEntity implements RequestEntity { try { mChannel.position(mOffset); - while (mChannel.position() < mOffset + mSize && mChannel.position() < mChannel.size()) { + long size = mFile.length(); + if (size == 0) size = -1; + while (mChannel.position() < mOffset + mChunkSize && mChannel.position() < mChannel.size()) { readCount = mChannel.read(mBuffer); out.write(mBuffer.array(), 0, readCount); mBuffer.clear(); - it = mListeners.iterator(); + mTransferred += readCount; + it = mDataTransferListeners.iterator(); while (it.hasNext()) { - it.next().onTransferProgress(readCount); + it.next().onTransferProgress(readCount, mTransferred, size, mFile.getName()); } } diff --git a/src/eu/alefzero/webdav/FileRequestEntity.java b/src/eu/alefzero/webdav/FileRequestEntity.java index 0f774f77..2924f452 100644 --- a/src/eu/alefzero/webdav/FileRequestEntity.java +++ b/src/eu/alefzero/webdav/FileRequestEntity.java @@ -27,7 +27,7 @@ public class FileRequestEntity implements RequestEntity { final File mFile; final String mContentType; - Set mListeners = new HashSet(); + Set mDataTransferListeners = new HashSet(); public FileRequestEntity(final File file, final String contentType) { super(); @@ -54,15 +54,15 @@ public class FileRequestEntity implements RequestEntity { } public void addOnDatatransferProgressListener(OnDatatransferProgressListener listener) { - mListeners.add(listener); + mDataTransferListeners.add(listener); } public void addOnDatatransferProgressListeners(Collection listeners) { - mListeners.addAll(listeners); + mDataTransferListeners.addAll(listeners); } public void removeOnDatatransferProgressListener(OnDatatransferProgressListener listener) { - mListeners.remove(listener); + mDataTransferListeners.remove(listener); } @@ -70,7 +70,7 @@ public class FileRequestEntity implements RequestEntity { public void writeRequest(final OutputStream out) throws IOException { //byte[] tmp = new byte[4096]; ByteBuffer tmp = ByteBuffer.allocate(4096); - int i = 0; + int readResult = 0; // TODO(bprzybylski): each mem allocation can throw OutOfMemoryError we need to handle it // globally in some fashionable manner @@ -78,13 +78,17 @@ public class FileRequestEntity implements RequestEntity { FileChannel channel = raf.getChannel(); FileLock lock = channel.tryLock(); Iterator it = null; + long transferred = 0; + long size = mFile.length(); + if (size == 0) size = -1; try { - while ((i = channel.read(tmp)) >= 0) { - out.write(tmp.array(), 0, i); + while ((readResult = channel.read(tmp)) >= 0) { + out.write(tmp.array(), 0, readResult); tmp.clear(); - it = mListeners.iterator(); + transferred += readResult; + it = mDataTransferListeners.iterator(); while (it.hasNext()) { - it.next().onTransferProgress(i); + it.next().onTransferProgress(readResult, transferred, size, mFile.getName()); } }