You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="@color/owncloud_white" >
-
- <ScrollView
- android:id="@+id/fdScrollView"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content" >
-
- <RelativeLayout
- android:id="@+id/fdFileHeaderContainer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="16dp"
- android:layout_marginTop="4dp" >
-
- <ImageView
- android:id="@+id/fdIcon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/file" />
-
- <TextView
- android:id="@+id/fdFilename"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_toRightOf="@+id/fdIcon"
- android:text="file.name"
- android:textAppearance="?android:attr/textAppearanceLarge" />
- </RelativeLayout>
-
- <RelativeLayout
- android:id="@+id/fdDetailsContainer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/fdFileHeaderContainer" >
-
- <RelativeLayout
- android:id="@+id/fdLabelContainer"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_marginLeft="16dp" >
-
- <TextView
- android:id="@+id/fdTypeLabel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="24dp"
- android:text="@string/filedetails_type"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/fdSizeLabel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdTypeLabel"
- android:layout_marginTop="12dp"
- android:text="@string/filedetails_size"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/fdCreatedLabel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdSizeLabel"
- android:layout_marginTop="12dp"
- android:text="@string/filedetails_created"
- android:visibility="gone"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/fdModifiedLabel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdCreatedLabel"
- android:layout_marginTop="12dp"
- android:text="@string/filedetails_modified"
- android:textAppearance="?android:attr/textAppearanceMedium" />
- </RelativeLayout>
-
- <RelativeLayout
- android:id="@+id/fdValueContainer"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_marginLeft="12dp"
- android:layout_toRightOf="@+id/fdLabelContainer" >
-
- <TextView
- android:id="@+id/fdType"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="24dp"
- android:text="JPG Image"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/fdSize"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdType"
- android:layout_marginTop="12dp"
- android:text="389 KB"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/fdCreated"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdSize"
- android:layout_marginTop="12dp"
- android:visibility="gone"
- android:text="2012/05/18 12:23 PM"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/fdModified"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdCreated"
- android:layout_marginTop="12dp"
- android:text="2012/05/19 02:56 PM"
- android:textAppearance="?android:attr/textAppearanceMedium" />
- </RelativeLayout>
-
- </RelativeLayout>
-
- <RelativeLayout
- android:id="@+id/fdPreviewAndDL"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdDetailsContainer"
- android:gravity="center_horizontal" >
-
- <CheckBox
- android:id="@+id/fdKeepInSync"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:text="@string/fd_keep_in_sync" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/fdKeepInSync"
- android:orientation="vertical" >
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal" >
-
- <Button
- android:id="@+id/fdRemoveBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:text="@string/common_remove" />
-
- <Button
- android:id="@+id/fdOpenBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:text="@string/filedetails_open" />
-
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal">
-
- <Button
- android:id="@+id/fdDownloadBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:text="@string/filedetails_download" />
-
- <Button
- android:id="@+id/fdRenameBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:text="@string/common_rename" />
-
- </LinearLayout>
-<!--
- <Button
- android:id="@+id/fdShareBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:text="@string/common_share" />
- -->
-
- </LinearLayout>
- </RelativeLayout>
-
- </RelativeLayout>
- </ScrollView>
-
-</RelativeLayout>
\ No newline at end of file
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/fdScrollView"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" >
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <RelativeLayout
+ android:id="@+id/fdFileHeaderContainer"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="16dp"
+ android:layout_marginTop="4dp" >
+
+ <ImageView
+ android:id="@+id/fdIcon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/file" />
+
+ <TextView
+ android:id="@+id/fdFilename"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_toRightOf="@+id/fdIcon"
+ android:text="@string/placeholder_filename"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:id="@+id/fdDetailsContainer"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/fdFileHeaderContainer" >
+
+ <RelativeLayout
+ android:id="@+id/fdLabelContainer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginLeft="16dp" >
+
+ <TextView
+ android:id="@+id/fdTypeLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="24dp"
+ android:text="@string/filedetails_type"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/fdSizeLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdTypeLabel"
+ android:layout_marginTop="12dp"
+ android:text="@string/filedetails_size"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/fdCreatedLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdSizeLabel"
+ android:layout_marginTop="12dp"
+ android:text="@string/filedetails_created"
+ android:visibility="gone"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/fdModifiedLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdCreatedLabel"
+ android:layout_marginTop="12dp"
+ android:text="@string/filedetails_modified"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:id="@+id/fdValueContainer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_marginLeft="12dp"
+ android:layout_toRightOf="@+id/fdLabelContainer" >
+
+ <TextView
+ android:id="@+id/fdType"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="24dp"
+ android:text="@string/placeholder_filetype"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/fdSize"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdType"
+ android:layout_marginTop="12dp"
+ android:text="@string/placeholder_filesize"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/fdCreated"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdSize"
+ android:layout_marginTop="12dp"
+ android:visibility="gone"
+ android:text="@string/placeholder_timestamp"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/fdModified"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdCreated"
+ android:layout_marginTop="12dp"
+ android:text="@string/placeholder_timestamp"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ </RelativeLayout>
+
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:id="@+id/fdProgressAndControl"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdDetailsContainer"
+ android:gravity="center_horizontal"
+ android:layout_margin="16dp"
+ >
+
+ <CheckBox
+ android:id="@+id/fdKeepInSync"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:text="@string/fd_keep_in_sync" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/fdKeepInSync"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/fdProgressText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/downloader_download_in_progress_ticker"
+ />
+
+ <ProgressBar android:id="@+id/fdProgressBar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:progressDrawable="@android:drawable/progress_horizontal"
+ android:indeterminate="false"
+ android:indeterminateOnly="false"
+ />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:layout_marginTop="12dp"
+ >
+
+ <Button
+ android:id="@+id/fdDownloadBtn"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/filedetails_download" />
+
+ <Button
+ android:id="@+id/fdOpenBtn"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/filedetails_open" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:layout_marginTop="12dp"
+ >
+
+ <Button
+ android:id="@+id/fdRenameBtn"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/common_rename" />
+
+ <Button
+ android:id="@+id/fdRemoveBtn"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/common_remove" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </RelativeLayout>
+
+ </RelativeLayout>
+
+</ScrollView>
<string name="ssl_validator_label_signature">Signature:</string>
<string name="ssl_validator_label_signature_algorithm">Algorithm:</string>
- <string name="text_placeholder">This is a placeholder</string>
+ <string name="placeholder_sentence">This is a placeholder</string>
+ <string name="placeholder_filename">placeholder.txt</string>
+ <string name="placeholder_filetype">PNG Image</string>
+ <string name="placeholder_filesize">389 KB</string>
+ <string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
<string name="instant_upload_on_wifi">Upload pictures via WiFi only</string>
<string name="instant_upload_path">/InstantUpload</string>
import android.os.Message;\r
import android.os.Process;\r
import android.util.Log;\r
+import android.widget.ProgressBar;\r
import android.widget.RemoteViews;\r
\r
import com.owncloud.android.R;\r
}\r
}\r
}\r
+\r
+ \r
+ /**\r
+ * Adds a listener interested in the progress of the download for a concrete file.\r
+ * \r
+ * @param listener Object to notify about progress of transfer. \r
+ * @param account ownCloud account holding the file of interest.\r
+ * @param file {@link OCfile} of interest for listener. \r
+ */\r
+ public void addDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {\r
+ if (account == null || file == null) return;\r
+ String targetKey = buildRemoteName(account, file);\r
+ DownloadFileOperation target = null;\r
+ synchronized (mPendingDownloads) {\r
+ if (!file.isDirectory()) {\r
+ target = mPendingDownloads.get(targetKey);\r
+ } else {\r
+ // nothing to do for directories, right now\r
+ }\r
+ }\r
+ if (target != null) {\r
+ target.addDatatransferProgressListener(listener);\r
+ }\r
+ }\r
+ \r
+ \r
+ /**\r
+ * Removes a listener interested in the progress of the download for a concrete file.\r
+ * \r
+ * @param listener Object to notify about progress of transfer. \r
+ * @param account ownCloud account holding the file of interest.\r
+ * @param file {@link OCfile} of interest for listener. \r
+ */\r
+ public void removeDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {\r
+ if (account == null || file == null) return;\r
+ String targetKey = buildRemoteName(account, file);\r
+ DownloadFileOperation target = null;\r
+ synchronized (mPendingDownloads) {\r
+ if (!file.isDirectory()) {\r
+ target = mPendingDownloads.get(targetKey);\r
+ } else {\r
+ // nothing to do for directories, right now\r
+ }\r
+ }\r
+ if (target != null) {\r
+ target.removeDatatransferProgressListener(listener);\r
+ }\r
+ }\r
+ \r
}\r
\r
\r
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.InstantUploadBroadcastReceiver;
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.operations.RemoteOperationResult.ResultCode;
}
}
}
+
+
+ /**
+ * Adds a listener interested in the progress of the download for a concrete file.
+ *
+ * @param listener Object to notify about progress of transfer.
+ * @param account ownCloud account holding the file of interest.
+ * @param file {@link OCfile} of interest for listener.
+ */
+ public void addDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {
+ if (account == null || file == null) return;
+ String targetKey = buildRemoteName(account, file);
+ UploadFileOperation target = null;
+ synchronized (mPendingUploads) {
+ if (!file.isDirectory()) {
+ target = mPendingUploads.get(targetKey);
+ } else {
+ // nothing to do for directories, right now
+ }
+ }
+ if (target != null) {
+ target.addDatatransferProgressListener(listener);
+ }
+ }
+
+
}
--- /dev/null
+/* ownCloud Android client application
+ * Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.network;
+
+import java.util.Collection;
+
+import eu.alefzero.webdav.OnDatatransferProgressListener;
+
+public interface ProgressiveDataTransferer {
+
+ public void addDatatransferProgressListener (OnDatatransferProgressListener listener);
+
+ public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners);
+
+ public void removeDatatransferProgressListener(OnDatatransferProgressListener listener);
+
+}
import org.apache.commons.httpclient.methods.PutMethod;
import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.network.ProgressiveDataTransferer;
import android.accounts.Account;
import android.util.Log;
File file = new File(getStoragePath());
raf = new RandomAccessFile(file, "r");
channel = raf.getChannel();
- ChunkFromFileChannelRequestEntity entity = new ChunkFromFileChannelRequestEntity(channel, getMimeType(), CHUNK_SIZE, file);
- entity.addOnDatatransferProgressListeners(getDataTransferListeners());
+ mEntity = new ChunkFromFileChannelRequestEntity(channel, getMimeType(), CHUNK_SIZE, file);
+ ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(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) {
mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex);
mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER);
- entity.setOffset(offset);
- mPutMethod.setRequestEntity(entity);
+ ((ChunkFromFileChannelRequestEntity)mEntity).setOffset(offset);
+ mPutMethod.setRequestEntity(mEntity);
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);
public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
- mDataTransferListeners.add(listener);
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.add(listener);
+ }
}
+ public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.remove(listener);
+ }
+ }
+
@Override
protected RemoteOperationResult run(WebdavClient client) {
RemoteOperationResult result = null;
}
fos.write(bytes, 0, readResult);
transferred += readResult;
- it = mDataTransferListeners.iterator();
- while (it.hasNext()) {
- it.next().onTransferProgress(readResult, transferred, mFile.getFileLength(), targetFile.getName());
+ synchronized (mDataTransferListeners) {
+ it = mDataTransferListeners.iterator();
+ while (it.hasNext()) {
+ it.next().onTransferProgress(readResult, transferred, mFile.getFileLength(), targetFile.getName());
+ }
}
}
savedFile = true;
mCancellationRequested.set(true); // atomic set; there is no need of synchronizing it
}
+
}
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.http.HttpStatus;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.network.ProgressiveDataTransferer;
import com.owncloud.android.operations.RemoteOperation;
import com.owncloud.android.operations.RemoteOperationResult;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
+ protected RequestEntity mEntity = null;
+
public UploadFileOperation( Account account,
OCFile file,
}
public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
- mDataTransferListeners.add(listener);
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.add(listener);
+ }
+ if (mEntity != null) {
+ ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListener(listener);
+ }
+ }
+
+ public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.remove(listener);
+ }
+ if (mEntity != null) {
+ ((ProgressiveDataTransferer)mEntity).removeDatatransferProgressListener(listener);
+ }
}
@Override
int status = -1;
try {
File f = new File(mFile.getStoragePath());
- FileRequestEntity entity = new FileRequestEntity(f, getMimeType());
- entity.addOnDatatransferProgressListeners(mDataTransferListeners);
- mPutMethod.setRequestEntity(entity);
+ mEntity = new FileRequestEntity(f, getMimeType());
+ synchronized (mDataTransferListeners) {
+ ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners);
+ }
+ mPutMethod.setRequestEntity(mEntity);
status = client.executeMethod(mPutMethod);
client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
*/\r
package com.owncloud.android.ui.activity;\r
\r
+import java.lang.ref.WeakReference;\r
+\r
import android.accounts.Account;\r
import android.app.Dialog;\r
import android.app.ProgressDialog;\r
import android.support.v4.app.Fragment;\r
import android.support.v4.app.FragmentTransaction;\r
import android.util.Log;\r
+import android.widget.ProgressBar;\r
\r
import com.actionbarsherlock.app.ActionBar;\r
import com.actionbarsherlock.app.SherlockFragmentActivity;\r
import com.owncloud.android.files.services.FileUploader;\r
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;\r
import com.owncloud.android.ui.fragment.FileDetailFragment;\r
-import com.owncloud.android.ui.fragment.FileFragment;\r
import com.owncloud.android.ui.fragment.FilePreviewFragment;\r
\r
-import com.owncloud.android.AccountUtils;\r
import com.owncloud.android.R;\r
\r
+import eu.alefzero.webdav.OnDatatransferProgressListener;\r
+\r
/**\r
* This activity displays the details of a file like its name, its size and so\r
* on.\r
* \r
* @author Bartek Przybylski\r
- * \r
+ * @author David A. Velasco\r
*/\r
public class FileDetailActivity extends SherlockFragmentActivity implements FileDetailFragment.ContainerActivity {\r
\r
public static final String EXTRA_MODE = "MODE";\r
public static final int MODE_DETAILS = 0;\r
public static final int MODE_PREVIEW = 1;\r
+\r
+ private static final String KEY_WAITING_TO_PREVIEW = "WAITING_TO_PREVIEW";\r
\r
private boolean mConfigurationChangedToLandscape = false;\r
private FileDownloaderBinder mDownloaderBinder = null;\r
private ServiceConnection mDownloadConnection, mUploadConnection = null;\r
private FileUploaderBinder mUploaderBinder = null;\r
+ private boolean mWaitingToPreview;\r
+\r
+ public ProgressListener mProgressListener;\r
\r
\r
@Override\r
actionBar.setDisplayHomeAsUpEnabled(true);\r
\r
if (savedInstanceState == null) {\r
+ mWaitingToPreview = false;\r
createChildFragment();\r
+ } else {\r
+ mWaitingToPreview = savedInstanceState.getBoolean(KEY_WAITING_TO_PREVIEW);\r
}\r
\r
} else {\r
\r
\r
}\r
- \r
- \r
+\r
+ /**\r
+ * Creates the proper fragment depending upon the state of the handled {@link OCFile} and\r
+ * the requested {@link Intent}.\r
+ */\r
private void createChildFragment() {\r
OCFile file = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE);\r
Account account = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT);\r
\r
Fragment newFragment = null;\r
if (FilePreviewFragment.canBePreviewed(file) && mode == MODE_PREVIEW) {\r
- newFragment = new FilePreviewFragment(file, account);\r
+ if (file.isDown()) {\r
+ newFragment = new FilePreviewFragment(file, account);\r
+ \r
+ } else {\r
+ newFragment = new FileDetailFragment(file, account);\r
+ mWaitingToPreview = true;\r
+ }\r
\r
} else {\r
newFragment = new FileDetailFragment(file, account);\r
}\r
\r
\r
+ @Override\r
+ protected void onSaveInstanceState(Bundle outState) {\r
+ outState.putBoolean(KEY_WAITING_TO_PREVIEW, mWaitingToPreview);\r
+ }\r
+\r
\r
/** Defines callbacks for service binding, passed to bindService() */\r
private class DetailsServiceConnection implements ServiceConnection {\r
\r
@Override\r
public void onServiceConnected(ComponentName component, IBinder service) {\r
+ Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);\r
+ FileDetailFragment detailsFragment = (FileDetailFragment) fragment;\r
+ \r
if (component.equals(new ComponentName(FileDetailActivity.this, FileDownloader.class))) {\r
Log.d(TAG, "Download service connected");\r
mDownloaderBinder = (FileDownloaderBinder) service;\r
+ if (detailsFragment != null) {\r
+ mProgressListener = new ProgressListener(detailsFragment.getProgressBar());\r
+ mDownloaderBinder.addDatatransferProgressListener(\r
+ mProgressListener, \r
+ (Account) getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT), \r
+ (OCFile) getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE)\r
+ );\r
+ }\r
} else if (component.equals(new ComponentName(FileDetailActivity.this, FileUploader.class))) {\r
Log.d(TAG, "Upload service connected");\r
mUploaderBinder = (FileUploaderBinder) service;\r
+ if (detailsFragment != null) {\r
+ mProgressListener = new ProgressListener(detailsFragment.getProgressBar());\r
+ mUploaderBinder.addDatatransferProgressListener(\r
+ mProgressListener, \r
+ (Account) getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT), \r
+ (OCFile) getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE)\r
+ );\r
+ }\r
} else {\r
return;\r
}\r
- Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);\r
- if (fragment != null && fragment instanceof FileDetailFragment) {\r
- ((FileDetailFragment) fragment).updateFileDetails(false); // let the fragment gets the mDownloadBinder through getDownloadBinder() (see FileDetailFragment#updateFileDetais())\r
+ \r
+ if (detailsFragment != null) {\r
+ detailsFragment.updateFileDetails(false); // let the fragment gets the mDownloadBinder through getDownloadBinder() (see FileDetailFragment#updateFileDetais())\r
}\r
}\r
\r
}\r
}; \r
\r
+ \r
+ /**\r
+ * Helper class responsible for updating the progress bar shown for file uploading or downloading \r
+ * \r
+ * @author David A. Velasco\r
+ */\r
+ private class ProgressListener implements OnDatatransferProgressListener {\r
+ int mLastPercent = 0;\r
+ WeakReference<ProgressBar> mProgressBar = null;\r
+ \r
+ ProgressListener(ProgressBar progressBar) {\r
+ mProgressBar = new WeakReference<ProgressBar>(progressBar);\r
+ }\r
+ \r
+ @Override\r
+ public void onTransferProgress(long progressRate) {\r
+ // old method, nothing here\r
+ };\r
+\r
+ @Override\r
+ public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) {\r
+ int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));\r
+ if (percent != mLastPercent) {\r
+ ProgressBar pb = mProgressBar.get();\r
+ if (pb != null) {\r
+ pb.setProgress(percent);\r
+ }\r
+ }\r
+ mLastPercent = percent;\r
+ }\r
+\r
+ };\r
+ \r
\r
@Override\r
public void onDestroy() {\r
if (mDualPane && getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG) == null) {\r
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\r
if (mCurrentFile != null) {\r
- if (FilePreviewFragment.canBePreviewed(mCurrentFile)) {\r
+ if (mCurrentFile.isDown() && FilePreviewFragment.canBePreviewed(mCurrentFile)) {\r
transaction.replace(R.id.file_details_container, new FilePreviewFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);\r
} else {\r
transaction.replace(R.id.file_details_container, new FileDetailFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);\r
if (mDualPane) {\r
// buttons in the details view are problematic when trying to reuse an existing fragment; create always a new one solves some of them, BUT no all; downloads are 'dangerous'\r
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\r
- if (FilePreviewFragment.canBePreviewed(file)) {\r
+ if (file != null && file.isDown() && FilePreviewFragment.canBePreviewed(file)) {\r
transaction.replace(R.id.file_details_container, new FilePreviewFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);\r
} else {\r
transaction.replace(R.id.file_details_container, new FileDetailFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);\r
dialog.setIndeterminate(true);
/// set message
- int messageId = getArguments().getInt(ARG_MESSAGE_ID, R.string.text_placeholder);
+ int messageId = getArguments().getInt(ARG_MESSAGE_ID, R.string.placeholder_sentence);
dialog.setMessage(getString(messageId));
/// set cancellation behavior
package com.owncloud.android.ui.fragment;\r
\r
import java.io.File;\r
+import java.lang.ref.WeakReference;\r
import java.util.ArrayList;\r
import java.util.List;\r
\r
import android.view.View.OnTouchListener;\r
import android.view.ViewGroup;\r
import android.webkit.MimeTypeMap;\r
+import android.webkit.WebView.FindListener;\r
import android.widget.Button;\r
import android.widget.CheckBox;\r
import android.widget.ImageView;\r
import android.widget.MediaController;\r
+import android.widget.ProgressBar;\r
import android.widget.TextView;\r
import android.widget.Toast;\r
import android.widget.VideoView;\r
import com.owncloud.android.utils.OwnCloudVersion;\r
\r
import com.owncloud.android.R;\r
+\r
+import eu.alefzero.webdav.OnDatatransferProgressListener;\r
import eu.alefzero.webdav.WebdavClient;\r
import eu.alefzero.webdav.WebdavUtils;\r
\r
((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(false);\r
((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(false);\r
getView().findViewById(R.id.fdKeepInSync).setEnabled(false);\r
+ \r
+ // show the progress bar for the transfer\r
+ ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);\r
+ progressBar.setVisibility(View.VISIBLE);\r
+ TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);\r
+ progressText.setVisibility(View.VISIBLE);\r
+ FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();\r
+ FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();\r
+ if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {\r
+ progressText.setText(R.string.downloader_download_in_progress_ticker);\r
+ } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile)) {\r
+ progressText.setText(R.string.uploader_upload_in_progress_ticker);\r
+ }\r
}\r
}\r
\r
+\r
/**\r
* Enables or disables buttons for a file locally available \r
*/\r
((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);\r
((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);\r
getView().findViewById(R.id.fdKeepInSync).setEnabled(true);\r
+ \r
+ // hides the progress bar\r
+ ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);\r
+ progressBar.setVisibility(View.GONE);\r
}\r
}\r
\r
((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);\r
((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);\r
getView().findViewById(R.id.fdKeepInSync).setEnabled(true);\r
+ \r
+ // hides the progress bar\r
+ ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);\r
+ progressBar.setVisibility(View.GONE);\r
}\r
}\r
\r
}\r
\r
\r
+ public ProgressBar getProgressBar() {\r
+ View v = getView();\r
+ if (v != null) {\r
+ return (ProgressBar) v.findViewById(R.id.fdProgressBar);\r
+ } else {\r
+ return null;\r
+ }\r
+ }\r
+\r
+\r
}\r
* @return 'True' if the file can be handled by the fragment.
*/
public static boolean canBePreviewed(OCFile file) {
- return (file != null && file.isDown() &&
- (file.isAudio() || file.isVideo() || file.isImage()));
+ return (file != null && (file.isAudio() || file.isVideo() || file.isImage()));
}
/**
import org.apache.commons.httpclient.methods.RequestEntity;
+import com.owncloud.android.network.ProgressiveDataTransferer;
+
import eu.alefzero.webdav.OnDatatransferProgressListener;
import android.util.Log;
*
* @author David A. Velasco
*/
-public class ChunkFromFileChannelRequestEntity implements RequestEntity {
+public class ChunkFromFileChannelRequestEntity implements RequestEntity, ProgressiveDataTransferer {
private static final String TAG = ChunkFromFileChannelRequestEntity.class.getSimpleName();
return true;
}
- public void addOnDatatransferProgressListener(OnDatatransferProgressListener listener) {
- mDataTransferListeners.add(listener);
+ @Override
+ public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.add(listener);
+ }
}
- public void addOnDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
- mDataTransferListeners.addAll(listeners);
+ @Override
+ public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.addAll(listeners);
+ }
}
- public void removeOnDatatransferProgressListener(OnDatatransferProgressListener listener) {
- mDataTransferListeners.remove(listener);
+ @Override
+ public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.remove(listener);
+ }
}
out.write(mBuffer.array(), 0, readCount);
mBuffer.clear();
mTransferred += readCount;
- it = mDataTransferListeners.iterator();
- while (it.hasNext()) {
- it.next().onTransferProgress(readCount, mTransferred, size, mFile.getName());
+ synchronized (mDataTransferListeners) {
+ it = mDataTransferListeners.iterator();
+ while (it.hasNext()) {
+ it.next().onTransferProgress(readCount, mTransferred, size, mFile.getName());
+ }
}
}
import org.apache.commons.httpclient.methods.RequestEntity;
+import com.owncloud.android.network.ProgressiveDataTransferer;
+
import eu.alefzero.webdav.OnDatatransferProgressListener;
import android.util.Log;
* A RequestEntity that represents a File.
*
*/
-public class FileRequestEntity implements RequestEntity {
+public class FileRequestEntity implements RequestEntity, ProgressiveDataTransferer {
final File mFile;
final String mContentType;
public boolean isRepeatable() {
return true;
}
-
- public void addOnDatatransferProgressListener(OnDatatransferProgressListener listener) {
- mDataTransferListeners.add(listener);
+
+ @Override
+ public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.add(listener);
+ }
}
- public void addOnDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
- mDataTransferListeners.addAll(listeners);
+ @Override
+ public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.addAll(listeners);
+ }
}
- public void removeOnDatatransferProgressListener(OnDatatransferProgressListener listener) {
- mDataTransferListeners.remove(listener);
+ @Override
+ public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.remove(listener);
+ }
}
out.write(tmp.array(), 0, readResult);
tmp.clear();
transferred += readResult;
- it = mDataTransferListeners.iterator();
- while (it.hasNext()) {
- it.next().onTransferProgress(readResult, transferred, size, mFile.getName());
+ synchronized (mDataTransferListeners) {
+ it = mDataTransferListeners.iterator();
+ while (it.hasNext()) {
+ it.next().onTransferProgress(readResult, transferred, size, mFile.getName());
+ }
}
}
try {\r
File f = new File(localFile);\r
FileRequestEntity entity = new FileRequestEntity(f, contentType);\r
- entity.addOnDatatransferProgressListener(mDataTransferListener);\r
+ entity.addDatatransferProgressListener(mDataTransferListener);\r
put.setRequestEntity(entity);\r
status = executeMethod(put);\r
\r