-->\r
<manifest package="eu.alefzero.owncloud"\r
android:versionCode="1"\r
- android:versionName="0.1.186B" xmlns:android="http://schemas.android.com/apk/res/android">\r
+ android:versionName="0.1.187B" xmlns:android="http://schemas.android.com/apk/res/android">\r
\r
<uses-permission android:name="android.permission.GET_ACCOUNTS" />\r
<uses-permission android:name="android.permission.USE_CREDENTIALS" />\r
android:layout_height="wrap_content"
android:src="@drawable/local_file_indicator"/>
- <ImageView
+ <!-- ImageView
android:id="@+id/imageView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:src="@drawable/downloading_file_indicator"/>
+ android:src="@drawable/downloading_file_indicator"/ >
+
+ <ImageView
+ android:id="@+id/imageView5"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/uploading_file_indicator"/ -->
<ImageView
android:id="@+id/imageView1"
cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
if (fileExists(file.getRemotePath())) {
- OCFile tmpfile = getFileByPath(file.getRemotePath());
- file.setStoragePath(tmpfile.getStoragePath());
+ OCFile oldFile = getFileByPath(file.getRemotePath());
+ if (file.getStoragePath() == null && oldFile.getStoragePath() != null)
+ file.setStoragePath(oldFile.getStoragePath());
if (!file.isDirectory());
cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
- file.setFileId(tmpfile.getFileId());
+ file.setFileId(oldFile.getFileId());
overriden = true;
if (getContentResolver() != null) {
public static final String EXTRA_FILE_PATH = "FILE_PATH";\r
public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";\r
public static final String EXTRA_FILE_SIZE = "FILE_SIZE";\r
- public static final String ACCOUNT_NAME = "ACCOUNT_NAME"; \r
+ public static final String ACCOUNT_NAME = "ACCOUNT_NAME";\r
+ \r
private static final String TAG = "FileDownloader";\r
\r
private NotificationManager mNotificationMngr;\r
tmpFile.getParentFile().mkdirs();\r
mDownloadsInProgress.put(buildRemoteName(mAccount.name, mRemotePath), tmpFile.getAbsolutePath());\r
File newFile = null;\r
- if (wdc.downloadFile(mRemotePath, tmpFile)) {\r
- newFile = new File(getSavePath() + mAccount.name + mFilePath);\r
- newFile.getParentFile().mkdirs();\r
- boolean moved = tmpFile.renameTo(newFile);\r
+ try {\r
+ if (wdc.downloadFile(mRemotePath, tmpFile)) {\r
+ newFile = new File(getSavePath() + mAccount.name + mFilePath);\r
+ newFile.getParentFile().mkdirs();\r
+ boolean moved = tmpFile.renameTo(newFile);\r
\r
- if (moved) {\r
- ContentValues cv = new ContentValues();\r
- cv.put(ProviderTableMeta.FILE_STORAGE_PATH, newFile.getAbsolutePath());\r
- getContentResolver().update(\r
- ProviderTableMeta.CONTENT_URI,\r
- cv,\r
- ProviderTableMeta.FILE_NAME + "=? AND "\r
- + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",\r
- new String[] {\r
- mFilePath.substring(mFilePath.lastIndexOf('/') + 1),\r
- mAccount.name });\r
- downloadResult = true;\r
+ if (moved) {\r
+ ContentValues cv = new ContentValues();\r
+ cv.put(ProviderTableMeta.FILE_STORAGE_PATH, newFile.getAbsolutePath());\r
+ getContentResolver().update(\r
+ ProviderTableMeta.CONTENT_URI,\r
+ cv,\r
+ ProviderTableMeta.FILE_NAME + "=? AND "\r
+ + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",\r
+ new String[] {\r
+ mFilePath.substring(mFilePath.lastIndexOf('/') + 1),\r
+ mAccount.name });\r
+ downloadResult = true;\r
+ }\r
}\r
+ } finally {\r
+ mDownloadsInProgress.remove(buildRemoteName(mAccount.name, mRemotePath));\r
}\r
- mDownloadsInProgress.remove(buildRemoteName(mAccount.name, mRemotePath));\r
\r
\r
/// notify result\r
public static final String UPLOAD_FINISH_MESSAGE = "UPLOAD_FINISH";
public static final String EXTRA_PARENT_DIR_ID = "PARENT_DIR_ID";
+ public static final String EXTRA_UPLOAD_RESULT = "RESULT";
+ public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
+ public static final String EXTRA_FILE_PATH = "FILE_PATH";
public static final String KEY_LOCAL_FILE = "LOCAL_FILE";
public static final String KEY_REMOTE_FILE = "REMOTE_FILE";
if (mimeType == null)
mimeType = "application/octet-stream";
mCurrentIndexUpload = i;
- mRemotePaths[i] = getAvailableRemotePath(wc, mRemotePaths[i]);
- mUploadsInProgress.put(buildRemoteName(mAccount.name, mRemotePaths[i]), mLocalPaths[i]);
long parentDirId = -1;
- if (mRemotePaths[i] != null && wc.putFile(mLocalPaths[i], mRemotePaths[i], mimeType)) {
- mSuccessCounter++;
- OCFile new_file = new OCFile(mRemotePaths[i]);
- new_file.setMimetype(mimeType);
- new_file.setFileLength(localFiles[i].length());
- new_file.setModificationTimestamp(System.currentTimeMillis());
- new_file.setLastSyncDate(0);
- new_file.setStoragePath(mLocalPaths[i]);
+ boolean uploadResult = false;
+ String availablePath = getAvailableRemotePath(wc, mRemotePaths[i]);
+ try {
File f = new File(mRemotePaths[i]);
parentDirId = storageManager.getFileByPath(f.getParent().endsWith("/")?f.getParent():f.getParent()+"/").getFileId();
- new_file.setParentId(parentDirId);
- storageManager.saveFile(new_file);
+ if(availablePath != null) {
+ mRemotePaths[i] = availablePath;
+ mUploadsInProgress.put(buildRemoteName(mAccount.name, mRemotePaths[i]), mLocalPaths[i]);
+ if (wc.putFile(mLocalPaths[i], mRemotePaths[i], mimeType)) {
+ OCFile new_file = new OCFile(mRemotePaths[i]);
+ new_file.setMimetype(mimeType);
+ new_file.setFileLength(localFiles[i].length());
+ new_file.setModificationTimestamp(System.currentTimeMillis());
+ new_file.setLastSyncDate(0);
+ new_file.setStoragePath(mLocalPaths[i]);
+ new_file.setParentId(parentDirId);
+ storageManager.saveFile(new_file);
+ mSuccessCounter++;
+ uploadResult = true;
+ }
+ }
+ } finally {
+ mUploadsInProgress.remove(buildRemoteName(mAccount.name, mRemotePaths[i]));
+
+ /// notify upload (or fail) of EACH file to activities interested
+ Intent end = new Intent(UPLOAD_FINISH_MESSAGE);
+ end.putExtra(EXTRA_PARENT_DIR_ID, parentDirId);
+ end.putExtra(EXTRA_UPLOAD_RESULT, uploadResult);
+ end.putExtra(EXTRA_REMOTE_PATH, mRemotePaths[i]);
+ end.putExtra(EXTRA_FILE_PATH, mLocalPaths[i]);
+ end.putExtra(ACCOUNT_NAME, mAccount.name);
+ sendBroadcast(end);
}
- mUploadsInProgress.remove(buildRemoteName(mAccount.name, mRemotePaths[i]));
- /// notify upload of EACH file to activities interested
- Intent end = new Intent(UPLOAD_FINISH_MESSAGE);
- end.putExtra(EXTRA_PARENT_DIR_ID, parentDirId);
- end.putExtra(ACCOUNT_NAME, mAccount.name);
- sendBroadcast(end);
}
/// notify final result
import eu.alefzero.owncloud.datamodel.OCFile;\r
import eu.alefzero.owncloud.files.services.FileDownloader;\r
import eu.alefzero.owncloud.ui.fragment.FileDetailFragment;\r
+import eu.alefzero.owncloud.ui.fragment.FileListFragment;\r
\r
/**\r
* This activity displays the details of a file like its name, its size and so\r
* @author Bartek Przybylski\r
* \r
*/\r
-public class FileDetailActivity extends SherlockFragmentActivity {\r
+public class FileDetailActivity extends SherlockFragmentActivity implements FileDetailFragment.ContainerActivity {\r
\r
private boolean mConfigurationChangedToLandscape = false;\r
\r
startActivity(intent);\r
finish();\r
}\r
+ \r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public void onFileStateChanged() {\r
+ // nothing to do here!\r
+ }\r
+ \r
\r
}\r
*/\r
\r
public class FileDisplayActivity extends SherlockFragmentActivity implements\r
- FileListFragment.ContainerActivity, OnNavigationListener, OnClickListener, android.view.View.OnClickListener {\r
+ FileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNavigationListener, OnClickListener, android.view.View.OnClickListener {\r
\r
private ArrayAdapter<String> mDirectories;\r
private OCFile mCurrentDir;\r
}\r
}\r
\r
+ \r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public void onFileStateChanged() {\r
+ FileListFragment fileListFragment = (FileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);\r
+ if (fileListFragment != null) { \r
+ fileListFragment.listDirectory();\r
+ }\r
+ }\r
+ \r
+ \r
/**\r
* Operations in this method should be preferably performed in onCreate to have a lighter onResume method. \r
* \r
import eu.alefzero.owncloud.datamodel.DataStorageManager;\r
import eu.alefzero.owncloud.datamodel.OCFile;\r
import eu.alefzero.owncloud.files.services.FileDownloader;\r
+import eu.alefzero.owncloud.files.services.FileUploader;\r
\r
import android.accounts.Account;\r
import android.content.Context;\r
} else {\r
fileIcon.setImageResource(R.drawable.ic_menu_archive);\r
}\r
- ImageView downloaded = (ImageView) view.findViewById(R.id.imageView2);\r
+ ImageView localStateView = (ImageView) view.findViewById(R.id.imageView2);\r
+ if (FileDownloader.isDownloading(mAccount, file.getRemotePath())) {\r
+ localStateView.setImageResource(R.drawable.downloading_file_indicator);\r
+ localStateView.setVisibility(View.VISIBLE);\r
+ } else if (FileUploader.isUploading(mAccount, file.getRemotePath())) {\r
+ localStateView.setImageResource(R.drawable.uploading_file_indicator);\r
+ localStateView.setVisibility(View.VISIBLE);\r
+ } else if (file.isDown()) {\r
+ localStateView.setImageResource(R.drawable.local_file_indicator);\r
+ localStateView.setVisibility(View.VISIBLE);\r
+ } else {\r
+ localStateView.setVisibility(View.INVISIBLE);\r
+ }\r
+ /*\r
+ ImageView down = (ImageView) view.findViewById(R.id.imageView2);\r
ImageView downloading = (ImageView) view.findViewById(R.id.imageView4);\r
+ ImageView uploading = (ImageView) view.findViewById(R.id.imageView5);\r
if (FileDownloader.isDownloading(mAccount, file.getRemotePath())) {\r
- downloaded.setVisibility(View.INVISIBLE);\r
+ down.setVisibility(View.INVISIBLE);\r
downloading.setVisibility(View.VISIBLE);\r
+ uploading.setVisibility(View.INVISIBLE);\r
+ } else if (FileUploader.isUploading(mAccount, file.getRemotePath())) {\r
+ down.setVisibility(View.INVISIBLE);\r
+ downloading.setVisibility(View.INVISIBLE);\r
+ uploading.setVisibility(View.VISIBLE);\r
} else if (file.isDown()) {\r
- downloaded.setVisibility(View.VISIBLE);\r
+ down.setVisibility(View.VISIBLE);\r
downloading.setVisibility(View.INVISIBLE);\r
+ uploading.setVisibility(View.INVISIBLE);\r
} else {\r
- downloaded.setVisibility(View.INVISIBLE);\r
+ down.setVisibility(View.INVISIBLE);\r
downloading.setVisibility(View.INVISIBLE);\r
- }\r
+ uploading.setVisibility(View.INVISIBLE);\r
+ }*/\r
\r
if (!file.isDirectory()) {\r
view.findViewById(R.id.file_size).setVisibility(View.VISIBLE);\r
\r
import android.accounts.Account;\r
import android.accounts.AccountManager;\r
+import android.annotation.SuppressLint;\r
+import android.app.Activity;\r
import android.content.ActivityNotFoundException;\r
import android.content.BroadcastReceiver;\r
import android.content.Context;\r
public static final String EXTRA_FILE = "FILE";\r
public static final String EXTRA_ACCOUNT = "ACCOUNT";\r
\r
+ private FileDetailFragment.ContainerActivity mContainerActivity;\r
+ \r
private int mLayout;\r
private View mView;\r
private OCFile mFile;\r
private ImageView mPreview;\r
\r
private DownloadFinishReceiver mDownloadFinishReceiver;\r
+ private UploadFinishReceiver mUploadFinishReceiver;\r
\r
private static final String TAG = "FileDetailFragment";\r
public static final String FTAG = "FileDetails"; \r
}\r
}\r
\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public void onAttach(Activity activity) {\r
+ super.onAttach(activity);\r
+ try {\r
+ mContainerActivity = (ContainerActivity) activity;\r
+ } catch (ClassCastException e) {\r
+ throw new ClassCastException(activity.toString() + " must implement FileListFragment.ContainerActivity");\r
+ }\r
+ }\r
+ \r
\r
@Override\r
public View onCreateView(LayoutInflater inflater, ViewGroup container,\r
@Override\r
public void onResume() {\r
super.onResume();\r
+ \r
mDownloadFinishReceiver = new DownloadFinishReceiver();\r
IntentFilter filter = new IntentFilter(\r
FileDownloader.DOWNLOAD_FINISH_MESSAGE);\r
getActivity().registerReceiver(mDownloadFinishReceiver, filter);\r
+ \r
+ mUploadFinishReceiver = new UploadFinishReceiver();\r
+ filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);\r
+ getActivity().registerReceiver(mUploadFinishReceiver, filter);\r
+ \r
mPreview = (ImageView)mView.findViewById(R.id.fdPreview);\r
}\r
\r
@Override\r
public void onPause() {\r
super.onPause();\r
+ \r
getActivity().unregisterReceiver(mDownloadFinishReceiver);\r
mDownloadFinishReceiver = null;\r
+ \r
+ getActivity().unregisterReceiver(mUploadFinishReceiver);\r
+ mUploadFinishReceiver = null;\r
+ \r
if (mPreview != null) {\r
mPreview = null;\r
}\r
i.putExtra(FileDownloader.EXTRA_FILE_SIZE, mFile.getFileLength());\r
\r
// update ui \r
- setButtonsForDownloading();\r
+ setButtonsForTransferring();\r
\r
getActivity().startService(i);\r
+ mContainerActivity.onFileStateChanged(); // this is not working; it is performed before the fileDownloadService registers it as 'in progress'\r
break;\r
}\r
case R.id.fdKeepInSync: {\r
fdsm.saveFile(mFile);\r
if (mFile.keepInSync()) {\r
onClick(getView().findViewById(R.id.fdDownloadBtn));\r
+ } else { \r
+ mContainerActivity.onFileStateChanged(); // put inside 'else' to not call it twice (here, and in the virtual click on fdDownloadBtn)\r
}\r
break;\r
}\r
cb.setChecked(mFile.keepInSync());\r
\r
// configure UI for depending upon local state of the file\r
- if (FileDownloader.isDownloading(mAccount, mFile.getRemotePath())) {\r
- setButtonsForDownloading();\r
+ if (FileDownloader.isDownloading(mAccount, mFile.getRemotePath()) || FileUploader.isUploading(mAccount, mFile.getRemotePath())) {\r
+ setButtonsForTransferring();\r
\r
} else if (mFile.isDown()) {\r
// Update preview\r
/**\r
* Enables or disables buttons for a file being downloaded\r
*/\r
- private void setButtonsForDownloading() {\r
+ private void setButtonsForTransferring() {\r
if (!isEmpty()) {\r
Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);\r
- downloadButton.setText(R.string.filedetails_download_in_progress);\r
+ //downloadButton.setText(R.string.filedetails_download_in_progress); // ugly\r
downloadButton.setEnabled(false); // TODO replace it with a 'cancel download' button\r
\r
// let's protect the user from himself ;)\r
private void setButtonsForDown() {\r
if (!isEmpty()) {\r
Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);\r
- downloadButton.setText(R.string.filedetails_redownload);\r
+ //downloadButton.setText(R.string.filedetails_redownload); // ugly\r
downloadButton.setEnabled(true);\r
\r
((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(true);\r
private void setButtonsForRemote() {\r
if (!isEmpty()) {\r
Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);\r
- downloadButton.setText(R.string.filedetails_download);\r
+ //downloadButton.setText(R.string.filedetails_download); // unnecessary\r
downloadButton.setEnabled(true);\r
\r
((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(false);\r
}*/\r
return false;\r
}\r
+ \r
+ \r
+ /**\r
+ * Interface to implement by any Activity that includes some instance of FileDetailFragment\r
+ * \r
+ * @author David A. Velasco\r
+ */\r
+ public interface ContainerActivity {\r
+\r
+ /**\r
+ * Callback method invoked when the detail fragment wants to notice its container \r
+ * activity about a relevant state the file shown by the fragment.\r
+ * \r
+ * Added to notify to FileDisplayActivity about the need of refresh the files list. \r
+ * \r
+ * Currently called when:\r
+ * - a download is started;\r
+ * - a rename is completed;\r
+ * - a deletion is completed;\r
+ * - the 'inSync' flag is changed;\r
+ */\r
+ public void onFileStateChanged();\r
+ \r
+ }\r
+ \r
\r
/**\r
* Once the file download has finished -> update view\r
String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);\r
if (mFile.getRemotePath().equals(downloadedRemotePath)) {\r
if (downloadWasFine) {\r
- mFile.setStoragePath(intent.getStringExtra(FileDownloader.EXTRA_FILE_PATH));\r
+ mFile.setStoragePath(intent.getStringExtra(FileDownloader.EXTRA_FILE_PATH)); // updates the local object without accessing the database again\r
}\r
updateFileDetails(); // it updates the buttons; must be called although !downloadWasFine\r
}\r
}\r
}\r
\r
+ \r
+ /**\r
+ * Once the file upload has finished -> update view\r
+ * \r
+ * Being notified about the finish of an upload is necessary for the next sequence:\r
+ * 1. Upload a big file.\r
+ * 2. Force a synchronization; if it finished before the upload, the file in transfer will be included in the local database and in the file list\r
+ * of its containing folder; the the server includes it in the PROPFIND requests although it's not fully upload. \r
+ * 3. Click the file in the list to see its details.\r
+ * 4. Wait for the upload finishes; at this moment, the details view must be refreshed to enable the action buttons.\r
+ */\r
+ private class UploadFinishReceiver extends BroadcastReceiver {\r
+ @Override\r
+ public void onReceive(Context context, Intent intent) {\r
+ String accountName = intent.getStringExtra(FileUploader.ACCOUNT_NAME);\r
+\r
+ if (!isEmpty() && accountName.equals(mAccount.name)) {\r
+ boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, false);\r
+ String uploadRemotePath = intent.getStringExtra(FileUploader.EXTRA_REMOTE_PATH);\r
+ if (mFile.getRemotePath().equals(uploadRemotePath)) {\r
+ if (uploadWasFine) {\r
+ FileDataStorageManager fdsm = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());\r
+ mFile = fdsm.getFileByPath(mFile.getRemotePath());\r
+ }\r
+ updateFileDetails(); // it updates the buttons; must be called although !uploadWasFine; interrupted uploads still leave an incomplete file in the server\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+\r
// this is a temporary class for sharing purposes, it need to be replaced in transfer service\r
private class ShareRunnable implements Runnable {\r
private String mPath;\r
mFile = mNew;\r
mHandler.post(new Runnable() {\r
@Override\r
- public void run() { updateFileDetails(mFile, mAccount); }\r
+ public void run() { \r
+ updateFileDetails(mFile, mAccount);\r
+ mContainerActivity.onFileStateChanged();\r
+ }\r
});\r
}\r
Log.e("ASD", ""+move.getQueryString());\r
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();\r
transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null)); // empty FileDetailFragment\r
transaction.commit();\r
+ mContainerActivity.onFileStateChanged();\r
\r
} else {\r
getActivity().finish();\r
}\r
\r
class BitmapLoader extends AsyncTask<String, Void, Bitmap> {\r
- @Override\r
+ @SuppressLint({ "NewApi", "NewApi", "NewApi" }) // to avoid Lint errors since Android SDK r20\r
+ @Override\r
protected Bitmap doInBackground(String... params) {\r
Bitmap result = null;\r
if (params.length != 1) return result;\r
int width = options.outWidth;\r
int height = options.outHeight;\r
int scale = 1;\r
- boolean recycle = false;\r
if (width >= 2048 || height >= 2048) {\r
scale = (int) Math.ceil((Math.ceil(Math.max(height, width) / 2048.)));\r
options.inSampleSize = scale;\r