Added progress bar for file transfers in details view (untested)

This commit is contained in:
David A. Velasco 2013-02-19 13:28:01 +01:00
parent f2474ae28d
commit 24dd513682
16 changed files with 552 additions and 257 deletions

View file

@ -16,215 +16,225 @@
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 xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fdScrollView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<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: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" />
<RelativeLayout
android:id="@+id/fdFileHeaderContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginTop="4dp" >
<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>
<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>
</RelativeLayout>
</ScrollView>

View file

@ -259,7 +259,11 @@
<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>

View file

@ -49,6 +49,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.util.Log;
import android.widget.ProgressBar;
import android.widget.RemoteViews;
import com.owncloud.android.R;
@ -214,6 +215,55 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
}
}
}
/**
* 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);
DownloadFileOperation target = null;
synchronized (mPendingDownloads) {
if (!file.isDirectory()) {
target = mPendingDownloads.get(targetKey);
} else {
// nothing to do for directories, right now
}
}
if (target != null) {
target.addDatatransferProgressListener(listener);
}
}
/**
* Removes 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 removeDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {
if (account == null || file == null) return;
String targetKey = buildRemoteName(account, file);
DownloadFileOperation target = null;
synchronized (mPendingDownloads) {
if (!file.isDirectory()) {
target = mPendingDownloads.get(targetKey);
} else {
// nothing to do for directories, right now
}
}
if (target != null) {
target.removeDatatransferProgressListener(listener);
}
}
}

View file

@ -34,6 +34,7 @@ import com.owncloud.android.datamodel.FileDataStorageManager;
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;
@ -340,6 +341,32 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
}
}
}
/**
* 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);
}
}
}

View file

@ -0,0 +1,33 @@
/* 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);
}

View file

@ -28,6 +28,7 @@ import org.apache.commons.httpclient.HttpException;
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;
@ -61,16 +62,16 @@ public class ChunkedUploadFileOperation extends UploadFileOperation {
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);

View file

@ -123,9 +123,17 @@ public class DownloadFileOperation extends RemoteOperation {
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;
@ -190,9 +198,11 @@ public class DownloadFileOperation extends RemoteOperation {
}
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;
@ -221,4 +231,5 @@ public class DownloadFileOperation extends RemoteOperation {
mCancellationRequested.set(true); // atomic set; there is no need of synchronizing it
}
}

View file

@ -30,10 +30,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
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;
@ -70,6 +72,8 @@ public class UploadFileOperation extends RemoteOperation {
private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
protected RequestEntity mEntity = null;
public UploadFileOperation( Account account,
OCFile file,
@ -152,7 +156,21 @@ public class UploadFileOperation extends RemoteOperation {
}
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
@ -331,9 +349,11 @@ public class UploadFileOperation extends RemoteOperation {
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());

View file

@ -17,6 +17,8 @@
*/
package com.owncloud.android.ui.activity;
import java.lang.ref.WeakReference;
import android.accounts.Account;
import android.app.Dialog;
import android.app.ProgressDialog;
@ -30,6 +32,7 @@ import android.os.IBinder;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.widget.ProgressBar;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
@ -40,18 +43,18 @@ import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
import com.owncloud.android.ui.fragment.FileDetailFragment;
import com.owncloud.android.ui.fragment.FileFragment;
import com.owncloud.android.ui.fragment.FilePreviewFragment;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.R;
import eu.alefzero.webdav.OnDatatransferProgressListener;
/**
* This activity displays the details of a file like its name, its size and so
* on.
*
* @author Bartek Przybylski
*
* @author David A. Velasco
*/
public class FileDetailActivity extends SherlockFragmentActivity implements FileDetailFragment.ContainerActivity {
@ -62,11 +65,16 @@ public class FileDetailActivity extends SherlockFragmentActivity implements File
public static final String EXTRA_MODE = "MODE";
public static final int MODE_DETAILS = 0;
public static final int MODE_PREVIEW = 1;
private static final String KEY_WAITING_TO_PREVIEW = "WAITING_TO_PREVIEW";
private boolean mConfigurationChangedToLandscape = false;
private FileDownloaderBinder mDownloaderBinder = null;
private ServiceConnection mDownloadConnection, mUploadConnection = null;
private FileUploaderBinder mUploaderBinder = null;
private boolean mWaitingToPreview;
public ProgressListener mProgressListener;
@Override
@ -91,7 +99,10 @@ public class FileDetailActivity extends SherlockFragmentActivity implements File
actionBar.setDisplayHomeAsUpEnabled(true);
if (savedInstanceState == null) {
mWaitingToPreview = false;
createChildFragment();
} else {
mWaitingToPreview = savedInstanceState.getBoolean(KEY_WAITING_TO_PREVIEW);
}
} else {
@ -100,8 +111,11 @@ public class FileDetailActivity extends SherlockFragmentActivity implements File
}
/**
* Creates the proper fragment depending upon the state of the handled {@link OCFile} and
* the requested {@link Intent}.
*/
private void createChildFragment() {
OCFile file = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE);
Account account = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT);
@ -109,7 +123,13 @@ public class FileDetailActivity extends SherlockFragmentActivity implements File
Fragment newFragment = null;
if (FilePreviewFragment.canBePreviewed(file) && mode == MODE_PREVIEW) {
newFragment = new FilePreviewFragment(file, account);
if (file.isDown()) {
newFragment = new FilePreviewFragment(file, account);
} else {
newFragment = new FileDetailFragment(file, account);
mWaitingToPreview = true;
}
} else {
newFragment = new FileDetailFragment(file, account);
@ -120,24 +140,48 @@ public class FileDetailActivity extends SherlockFragmentActivity implements File
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean(KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
}
/** Defines callbacks for service binding, passed to bindService() */
private class DetailsServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName component, IBinder service) {
Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
FileDetailFragment detailsFragment = (FileDetailFragment) fragment;
if (component.equals(new ComponentName(FileDetailActivity.this, FileDownloader.class))) {
Log.d(TAG, "Download service connected");
mDownloaderBinder = (FileDownloaderBinder) service;
if (detailsFragment != null) {
mProgressListener = new ProgressListener(detailsFragment.getProgressBar());
mDownloaderBinder.addDatatransferProgressListener(
mProgressListener,
(Account) getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT),
(OCFile) getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE)
);
}
} else if (component.equals(new ComponentName(FileDetailActivity.this, FileUploader.class))) {
Log.d(TAG, "Upload service connected");
mUploaderBinder = (FileUploaderBinder) service;
if (detailsFragment != null) {
mProgressListener = new ProgressListener(detailsFragment.getProgressBar());
mUploaderBinder.addDatatransferProgressListener(
mProgressListener,
(Account) getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT),
(OCFile) getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE)
);
}
} else {
return;
}
Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
if (fragment != null && fragment instanceof FileDetailFragment) {
((FileDetailFragment) fragment).updateFileDetails(false); // let the fragment gets the mDownloadBinder through getDownloadBinder() (see FileDetailFragment#updateFileDetais())
if (detailsFragment != null) {
detailsFragment.updateFileDetails(false); // let the fragment gets the mDownloadBinder through getDownloadBinder() (see FileDetailFragment#updateFileDetais())
}
}
@ -153,6 +197,39 @@ public class FileDetailActivity extends SherlockFragmentActivity implements File
}
};
/**
* Helper class responsible for updating the progress bar shown for file uploading or downloading
*
* @author David A. Velasco
*/
private class ProgressListener implements OnDatatransferProgressListener {
int mLastPercent = 0;
WeakReference<ProgressBar> mProgressBar = null;
ProgressListener(ProgressBar progressBar) {
mProgressBar = new WeakReference<ProgressBar>(progressBar);
}
@Override
public void onTransferProgress(long progressRate) {
// old method, nothing here
};
@Override
public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) {
int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));
if (percent != mLastPercent) {
ProgressBar pb = mProgressBar.get();
if (pb != null) {
pb.setProgress(percent);
}
}
mLastPercent = percent;
}
};
@Override
public void onDestroy() {

View file

@ -293,7 +293,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
if (mDualPane && getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG) == null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (mCurrentFile != null) {
if (FilePreviewFragment.canBePreviewed(mCurrentFile)) {
if (mCurrentFile.isDown() && FilePreviewFragment.canBePreviewed(mCurrentFile)) {
transaction.replace(R.id.file_details_container, new FilePreviewFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
} else {
transaction.replace(R.id.file_details_container, new FileDetailFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
@ -1027,7 +1027,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
if (mDualPane) {
// 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'
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (FilePreviewFragment.canBePreviewed(file)) {
if (file != null && file.isDown() && FilePreviewFragment.canBePreviewed(file)) {
transaction.replace(R.id.file_details_container, new FilePreviewFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
} else {
transaction.replace(R.id.file_details_container, new FileDetailFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);

View file

@ -43,7 +43,7 @@ public class IndeterminateProgressDialog extends SherlockDialogFragment {
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

View file

@ -18,6 +18,7 @@
package com.owncloud.android.ui.fragment;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@ -65,10 +66,12 @@ import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.webkit.MimeTypeMap;
import android.webkit.WebView.FindListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.MediaController;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;
@ -105,6 +108,8 @@ import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
import com.owncloud.android.utils.OwnCloudVersion;
import com.owncloud.android.R;
import eu.alefzero.webdav.OnDatatransferProgressListener;
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavUtils;
@ -731,9 +736,23 @@ public class FileDetailFragment extends SherlockFragment implements
((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(false);
((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(false);
getView().findViewById(R.id.fdKeepInSync).setEnabled(false);
// show the progress bar for the transfer
ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);
progressBar.setVisibility(View.VISIBLE);
TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);
progressText.setVisibility(View.VISIBLE);
FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {
progressText.setText(R.string.downloader_download_in_progress_ticker);
} else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile)) {
progressText.setText(R.string.uploader_upload_in_progress_ticker);
}
}
}
/**
* Enables or disables buttons for a file locally available
*/
@ -746,6 +765,10 @@ public class FileDetailFragment extends SherlockFragment implements
((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);
((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);
getView().findViewById(R.id.fdKeepInSync).setEnabled(true);
// hides the progress bar
ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);
progressBar.setVisibility(View.GONE);
}
}
@ -761,6 +784,10 @@ public class FileDetailFragment extends SherlockFragment implements
((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);
((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);
getView().findViewById(R.id.fdKeepInSync).setEnabled(true);
// hides the progress bar
ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);
progressBar.setVisibility(View.GONE);
}
}
@ -1074,4 +1101,14 @@ public class FileDetailFragment extends SherlockFragment implements
}
public ProgressBar getProgressBar() {
View v = getView();
if (v != null) {
return (ProgressBar) v.findViewById(R.id.fdProgressBar);
} else {
return null;
}
}
}

View file

@ -1039,8 +1039,7 @@ public class FilePreviewFragment extends SherlockFragment implements
* @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()));
}
/**

View file

@ -30,6 +30,8 @@ import java.util.Set;
import org.apache.commons.httpclient.methods.RequestEntity;
import com.owncloud.android.network.ProgressiveDataTransferer;
import eu.alefzero.webdav.OnDatatransferProgressListener;
import android.util.Log;
@ -40,7 +42,7 @@ 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();
@ -90,16 +92,25 @@ public class ChunkFromFileChannelRequestEntity implements RequestEntity {
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);
}
}
@ -116,9 +127,11 @@ public class ChunkFromFileChannelRequestEntity implements RequestEntity {
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());
}
}
}

View file

@ -31,6 +31,8 @@ import java.util.Set;
import org.apache.commons.httpclient.methods.RequestEntity;
import com.owncloud.android.network.ProgressiveDataTransferer;
import eu.alefzero.webdav.OnDatatransferProgressListener;
import android.util.Log;
@ -40,7 +42,7 @@ 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;
@ -69,17 +71,26 @@ public class FileRequestEntity implements RequestEntity {
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);
}
}
@ -102,9 +113,11 @@ public class FileRequestEntity implements RequestEntity {
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());
}
}
}

View file

@ -165,7 +165,7 @@ public class WebdavClient extends HttpClient {
try {
File f = new File(localFile);
FileRequestEntity entity = new FileRequestEntity(f, contentType);
entity.addOnDatatransferProgressListener(mDataTransferListener);
entity.addDatatransferProgressListener(mDataTransferListener);
put.setRequestEntity(entity);
status = executeMethod(put);