From: Matthias Baumann Date: Sat, 16 Mar 2013 17:56:27 +0000 (+0100) Subject: - InstantUpload path const not longer at two places, only at X-Git-Tag: oc-android-1.4.3~44 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/7392cfe5aba6d60f7d84dd335b759e08c94693a6?hp=--cc - InstantUpload path const not longer at two places, only at InstantUploadService - new method to create the full path for the instantupload's - add QUOTA_EXCEEDED to RemoteOperationResult.ResultCode enum to hande http-507 from oc - handle RuntimeException at connection lost as HOST_NOT_AVAILABLE - add the error message for failed uploads for every not uploaded picture, espacially for QUOTA_EXCEEDED is it necessary to show that to the user --- 7392cfe5aba6d60f7d84dd335b759e08c94693a6 diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 6b72738b..98f042f5 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -225,5 +225,7 @@ Ausgewählte löschen Versuche ausgewählte erneut hochzuladen Weitere Bilder laden -Upload nicht gestarted, Sie sind nicht online für ein Softupload + Upload nicht gestarted, Sie sind nicht online für ein Softupload + Fehlermeldung: + Bitte überprüfen sie ihre Serverkonfiguration, möglicherweise ist ihre Upload Limit überschritten diff --git a/res/values/strings.xml b/res/values/strings.xml index f518bdab..098da84d 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -241,5 +241,6 @@ retry to upload the image: Load more Picrures do nothing you are not online for instant upload - + Failure Message: + Pleas check your server configuration,maye your quota is exceeded. \ No newline at end of file diff --git a/src/com/owncloud/android/db/DbHandler.java b/src/com/owncloud/android/db/DbHandler.java index 3e4103a6..4d212fed 100644 --- a/src/com/owncloud/android/db/DbHandler.java +++ b/src/com/owncloud/android/db/DbHandler.java @@ -34,7 +34,7 @@ public class DbHandler { private SQLiteDatabase mDB; private OpenerHelper mHelper; private final String mDatabaseName = "ownCloud"; - private final int mDatabaseVersion = 2; + private final int mDatabaseVersion = 3; private final String TABLE_INSTANT_UPLOAD = "instant_upload"; @@ -50,19 +50,21 @@ public class DbHandler { mDB.close(); } - public boolean putFileForLater(String filepath, String account) { + public boolean putFileForLater(String filepath, String account, String message) { ContentValues cv = new ContentValues(); cv.put("path", filepath); cv.put("account", account); cv.put("attempt", UPLOAD_STATUS_UPLOAD_LATER); + cv.put("message", message); long result = mDB.insert(TABLE_INSTANT_UPLOAD, null, cv); Log.d(TABLE_INSTANT_UPLOAD, "putFileForLater returns with: " + result + " for file: " + filepath); return result != -1; } - public int updateFileState(String filepath, Integer status) { + public int updateFileState(String filepath, Integer status, String message) { ContentValues cv = new ContentValues(); cv.put("attempt", status); + cv.put("message", message); int result = mDB.update(TABLE_INSTANT_UPLOAD, cv, "path=?", new String[] { filepath }); Log.d(TABLE_INSTANT_UPLOAD, "updateFileState returns with: " + result + " for file: " + filepath); return result; @@ -100,12 +102,15 @@ public class DbHandler { @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + TABLE_INSTANT_UPLOAD + " (" + " _id INTEGER PRIMARY KEY, " + " path TEXT," - + " account TEXT,attempt INTEGER);"); + + " account TEXT,attempt INTEGER,message TEXT);"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - db.execSQL("ALTER TABLE " + TABLE_INSTANT_UPLOAD + " ADD COLUMN attempt;"); + if (oldVersion < 2) { + db.execSQL("ALTER TABLE " + TABLE_INSTANT_UPLOAD + " ADD COLUMN attempt INTEGER;"); + } + db.execSQL("ALTER TABLE " + TABLE_INSTANT_UPLOAD + " ADD COLUMN message TEXT;"); } } diff --git a/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java b/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java index 8fd06f3d..1232fa13 100644 --- a/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java +++ b/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java @@ -38,10 +38,10 @@ import com.owncloud.android.AccountUtils; import com.owncloud.android.authenticator.AccountAuthenticator; import com.owncloud.android.db.DbHandler; import com.owncloud.android.files.services.FileUploader; +import com.owncloud.android.utils.FileStorageUtils; public class InstantUploadBroadcastReceiver extends BroadcastReceiver { - public static String INSTANT_UPLOAD_DIR = "/InstantUpload/"; private static String TAG = "PhotoTakenBroadcastReceiver"; private static final String[] CONTENT_PROJECTION = { Media.DATA, Media.DISPLAY_NAME, Media.MIME_TYPE, Media.SIZE }; private static String NEW_PHOTO_ACTION = "com.android.camera.NEW_PICTURE"; @@ -100,7 +100,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { // same always temporally the picture to upload DbHandler db = new DbHandler(context); - db.putFileForLater(file_path, account.name); + db.putFileForLater(file_path, account.name, null); db.close(); if (!isOnline(context) || (instantUploadViaWiFiOnly(context) && !isConnectedViaWiFi(context))) { @@ -121,7 +121,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { Intent i = new Intent(context, FileUploader.class); i.putExtra(FileUploader.KEY_ACCOUNT, account); i.putExtra(FileUploader.KEY_LOCAL_FILE, file_path); - i.putExtra(FileUploader.KEY_REMOTE_FILE, INSTANT_UPLOAD_DIR + file_name); + i.putExtra(FileUploader.KEY_REMOTE_FILE, FileStorageUtils.getInstantUploadFilePath(file_name)); i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE); i.putExtra(FileUploader.KEY_MIME_TYPE, mime_type); i.putExtra(FileUploader.KEY_INSTANT_UPLOAD, true); @@ -164,7 +164,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { Intent i = new Intent(context, FileUploader.class); i.putExtra(FileUploader.KEY_ACCOUNT, account); i.putExtra(FileUploader.KEY_LOCAL_FILE, file_path); - i.putExtra(FileUploader.KEY_REMOTE_FILE, INSTANT_UPLOAD_DIR + f.getName()); + i.putExtra(FileUploader.KEY_REMOTE_FILE, FileStorageUtils.getInstantUploadFilePath(f.getName())); i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE); i.putExtra(FileUploader.KEY_INSTANT_UPLOAD, true); context.startService(i); diff --git a/src/com/owncloud/android/files/services/FileUploader.java b/src/com/owncloud/android/files/services/FileUploader.java index eaaea010..e21b831e 100644 --- a/src/com/owncloud/android/files/services/FileUploader.java +++ b/src/com/owncloud/android/files/services/FileUploader.java @@ -54,7 +54,6 @@ import com.owncloud.android.authenticator.AccountAuthenticator; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.db.DbHandler; -import com.owncloud.android.files.InstantUploadBroadcastReceiver; import com.owncloud.android.network.OwnCloudClientUtils; import com.owncloud.android.operations.ChunkedUploadFileOperation; import com.owncloud.android.operations.RemoteOperationResult; @@ -422,28 +421,10 @@ public class FileUploader extends Service implements OnDatatransferProgressListe // / create remote folder for instant uploads if (mCurrentUpload.isRemoteFolderToBeCreated()) { - mUploadClient.createDirectory(InstantUploadBroadcastReceiver.INSTANT_UPLOAD_DIR); // ignoring - // result; - // fail - // could - // just - // mean - // that - // it - // already - // exists, - // but - // local - // database - // is - // not - // synchronized; - // the - // upload - // will - // be - // tried - // anyway + mUploadClient.createDirectory(InstantUploadService.INSTANT_UPLOAD_DIR); + // ignoring result fail could just mean that it already exists, + // but local database is not synchronized the upload will be + // tried anyway } // / perform the upload @@ -543,11 +524,11 @@ public class FileUploader extends Service implements OnDatatransferProgressListe } private boolean checkAndFixInstantUploadDirectory(FileDataStorageManager storageManager) { - OCFile instantUploadDir = storageManager.getFileByPath(InstantUploadBroadcastReceiver.INSTANT_UPLOAD_DIR); + OCFile instantUploadDir = storageManager.getFileByPath(InstantUploadService.INSTANT_UPLOAD_DIR); if (instantUploadDir == null) { // first instant upload in the account, or never account not // synchronized after the remote InstantUpload folder was created - OCFile newDir = new OCFile(InstantUploadBroadcastReceiver.INSTANT_UPLOAD_DIR); + OCFile newDir = new OCFile(InstantUploadService.INSTANT_UPLOAD_DIR); newDir.setMimetype("DIR"); OCFile path = storageManager.getFileByPath(OCFile.PATH_SEPARATOR); @@ -738,8 +719,13 @@ public class FileUploader extends Service implements OnDatatransferProgressListe mNotificationManager.notify(R.string.uploader_upload_failed_ticker, finalNotification); DbHandler db = new DbHandler(this.getBaseContext()); - if (db.updateFileState(upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED) == 0) { - db.putFileForLater(upload.getOriginalStoragePath(), upload.getAccount().name); + String message = uploadResult.getLogMessage() + " errorCode: " + uploadResult.getCode(); + Log.e(TAG, message+" Http-Code: "+uploadResult.getHttpCode()); + if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) { + message = getString(R.string.failed_upload_quota_exceeded_text); + } + if (db.updateFileState(upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED, message) == 0) { + db.putFileForLater(upload.getOriginalStoragePath(), upload.getAccount().name, message); } db.close(); diff --git a/src/com/owncloud/android/files/services/InstantUploadService.java b/src/com/owncloud/android/files/services/InstantUploadService.java index ae1cb056..8ebcef44 100644 --- a/src/com/owncloud/android/files/services/InstantUploadService.java +++ b/src/com/owncloud/android/files/services/InstantUploadService.java @@ -23,16 +23,17 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import com.owncloud.android.network.OwnCloudClientUtils; - -import eu.alefzero.webdav.WebdavClient; - import android.accounts.Account; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; +import com.owncloud.android.network.OwnCloudClientUtils; +import com.owncloud.android.utils.FileStorageUtils; + +import eu.alefzero.webdav.WebdavClient; + public class InstantUploadService extends Service { public static String KEY_FILE_PATH = "KEY_FILEPATH"; @@ -43,7 +44,7 @@ public class InstantUploadService extends Service { private static String TAG = "InstantUploadService"; // TODO make it configurable over the settings dialog - public static String INSTANT_UPLOAD_DIR = "/InstantUpload"; + public static final String INSTANT_UPLOAD_DIR = "/InstantUpload"; private UploaderRunnable mUploaderRunnable; @Override @@ -59,54 +60,50 @@ public class InstantUploadService extends Service { Log.w(TAG, "Not all required information was provided, abording"); return Service.START_NOT_STICKY; } - + if (mUploaderRunnable == null) { mUploaderRunnable = new UploaderRunnable(); } - + String filename = intent.getStringExtra(KEY_DISPLAY_NAME); String filepath = intent.getStringExtra(KEY_FILE_PATH); String mimetype = intent.getStringExtra(KEY_MIME_TYPE); Account account = intent.getParcelableExtra(KEY_ACCOUNT); long filesize = intent.getLongExtra(KEY_FILE_SIZE, -1); - + mUploaderRunnable.addElementToQueue(filename, filepath, mimetype, filesize, account); - + // starting new thread for new download doesnt seems like a good idea // maybe some thread pool or single background thread would be better Log.d(TAG, "Starting instant upload thread"); new Thread(mUploaderRunnable).start(); - + return Service.START_STICKY; } - + private class UploaderRunnable implements Runnable { - + Object mLock; List> mHashMapList; - + public UploaderRunnable() { mHashMapList = new LinkedList>(); mLock = new Object(); } - - public void addElementToQueue(String filename, - String filepath, - String mimetype, - long length, - Account account) { + + public void addElementToQueue(String filename, String filepath, String mimetype, long length, Account account) { HashMap new_map = new HashMap(); new_map.put(KEY_ACCOUNT, account); new_map.put(KEY_DISPLAY_NAME, filename); new_map.put(KEY_FILE_PATH, filepath); new_map.put(KEY_MIME_TYPE, mimetype); new_map.put(KEY_FILE_SIZE, length); - + synchronized (mLock) { mHashMapList.add(new_map); } } - + private HashMap getFirstObject() { synchronized (mLock) { if (mHashMapList.size() == 0) @@ -116,10 +113,10 @@ public class InstantUploadService extends Service { return ret; } } - + public void run() { HashMap working_map; - + while ((working_map = getFirstObject()) != null) { Account account = (Account) working_map.get(KEY_ACCOUNT); String filename = (String) working_map.get(KEY_DISPLAY_NAME); @@ -127,15 +124,15 @@ public class InstantUploadService extends Service { String mimetype = (String) working_map.get(KEY_MIME_TYPE); WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(account, getApplicationContext()); - - wdc.createDirectory(INSTANT_UPLOAD_DIR); // fail could just mean that it already exists; put will be tried anyway + + wdc.createDirectory(INSTANT_UPLOAD_DIR); // fail could just mean that it already exists put will be tried anyway try { - wdc.putFile(filepath, INSTANT_UPLOAD_DIR + "/" + filename, mimetype); + wdc.putFile(filepath, FileStorageUtils.getInstantUploadFilePath(filename), mimetype); } catch (Exception e) { // nothing to do; this service is deprecated, indeed } } } } - + } diff --git a/src/com/owncloud/android/operations/RemoteOperationResult.java b/src/com/owncloud/android/operations/RemoteOperationResult.java index 718988a4..0ef5b31b 100644 --- a/src/com/owncloud/android/operations/RemoteOperationResult.java +++ b/src/com/owncloud/android/operations/RemoteOperationResult.java @@ -33,142 +33,126 @@ import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; import org.apache.jackrabbit.webdav.DavException; -import com.owncloud.android.network.CertificateCombinedException; +import android.util.Log; +import com.owncloud.android.network.CertificateCombinedException; /** * The result of a remote operation required to an ownCloud server. * - * Provides a common classification of remote operation results for all the application. + * Provides a common classification of remote operation results for all the + * application. * * @author David A. Velasco */ public class RemoteOperationResult implements Serializable { - + /** Generated - should be refreshed every time the class changes!! */ private static final long serialVersionUID = -7805531062432602444L; + private static final String TAG = "RemoteOperationResult"; - - public enum ResultCode { - OK, - OK_SSL, - OK_NO_SSL, - UNHANDLED_HTTP_CODE, - UNAUTHORIZED, - FILE_NOT_FOUND, - INSTANCE_NOT_CONFIGURED, - UNKNOWN_ERROR, - WRONG_CONNECTION, - TIMEOUT, - INCORRECT_ADDRESS, - HOST_NOT_AVAILABLE, - NO_NETWORK_CONNECTION, - SSL_ERROR, - SSL_RECOVERABLE_PEER_UNVERIFIED, - BAD_OC_VERSION, - CANCELLED, - INVALID_LOCAL_FILE_NAME, - INVALID_OVERWRITE, - CONFLICT, - SYNC_CONFLICT, - LOCAL_STORAGE_FULL, - LOCAL_STORAGE_NOT_MOVED, - LOCAL_STORAGE_NOT_COPIED + public enum ResultCode { + OK, OK_SSL, OK_NO_SSL, UNHANDLED_HTTP_CODE, UNAUTHORIZED, FILE_NOT_FOUND, INSTANCE_NOT_CONFIGURED, UNKNOWN_ERROR, WRONG_CONNECTION, TIMEOUT, INCORRECT_ADDRESS, HOST_NOT_AVAILABLE, NO_NETWORK_CONNECTION, SSL_ERROR, SSL_RECOVERABLE_PEER_UNVERIFIED, BAD_OC_VERSION, CANCELLED, INVALID_LOCAL_FILE_NAME, INVALID_OVERWRITE, CONFLICT, SYNC_CONFLICT, LOCAL_STORAGE_FULL, LOCAL_STORAGE_NOT_MOVED, LOCAL_STORAGE_NOT_COPIED, QUOTA_EXCEEDED } private boolean mSuccess = false; private int mHttpCode = -1; private Exception mException = null; private ResultCode mCode = ResultCode.UNKNOWN_ERROR; - + public RemoteOperationResult(ResultCode code) { mCode = code; mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL); } - + public RemoteOperationResult(boolean success, int httpCode) { - mSuccess = success; + mSuccess = success; mHttpCode = httpCode; if (success) { mCode = ResultCode.OK; - + } else if (httpCode > 0) { switch (httpCode) { - case HttpStatus.SC_UNAUTHORIZED: - mCode = ResultCode.UNAUTHORIZED; - break; - case HttpStatus.SC_NOT_FOUND: - mCode = ResultCode.FILE_NOT_FOUND; - break; - case HttpStatus.SC_INTERNAL_SERVER_ERROR: - mCode = ResultCode.INSTANCE_NOT_CONFIGURED; - break; - case HttpStatus.SC_CONFLICT: - mCode = ResultCode.CONFLICT; - break; - default: - mCode = ResultCode.UNHANDLED_HTTP_CODE; + case HttpStatus.SC_UNAUTHORIZED: + mCode = ResultCode.UNAUTHORIZED; + break; + case HttpStatus.SC_NOT_FOUND: + mCode = ResultCode.FILE_NOT_FOUND; + break; + case HttpStatus.SC_INTERNAL_SERVER_ERROR: + mCode = ResultCode.INSTANCE_NOT_CONFIGURED; + break; + case HttpStatus.SC_CONFLICT: + mCode = ResultCode.CONFLICT; + break; + case HttpStatus.SC_INSUFFICIENT_STORAGE: + mCode = ResultCode.QUOTA_EXCEEDED; + break; + default: + mCode = ResultCode.UNHANDLED_HTTP_CODE; + Log.d(TAG, "RemoteOperationResult has prcessed UNHANDLED_HTTP_CODE: " + httpCode); } } } - + public RemoteOperationResult(Exception e) { - mException = e; - + mException = e; + if (e instanceof OperationCancelledException) { mCode = ResultCode.CANCELLED; - - } else if (e instanceof SocketException) { + + } else if (e instanceof SocketException) { mCode = ResultCode.WRONG_CONNECTION; - + } else if (e instanceof SocketTimeoutException) { mCode = ResultCode.TIMEOUT; - + } else if (e instanceof ConnectTimeoutException) { mCode = ResultCode.TIMEOUT; - + } else if (e instanceof MalformedURLException) { mCode = ResultCode.INCORRECT_ADDRESS; - + } else if (e instanceof UnknownHostException) { mCode = ResultCode.HOST_NOT_AVAILABLE; - + } else if (e instanceof SSLException || e instanceof RuntimeException) { CertificateCombinedException se = getCertificateCombinedException(e); if (se != null) { mException = se; - if (se.isRecoverable()) { + if (se.isRecoverable()) { mCode = ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED; } - - } else { + } else if (e instanceof RuntimeException) { + mCode = ResultCode.HOST_NOT_AVAILABLE; + + } else { mCode = ResultCode.SSL_ERROR; } - + } else { mCode = ResultCode.UNKNOWN_ERROR; } - + } - - + public boolean isSuccess() { return mSuccess; } - + public boolean isCancelled() { return mCode == ResultCode.CANCELLED; } - + public int getHttpCode() { return mHttpCode; } - + public ResultCode getCode() { return mCode; } - + public Exception getException() { return mException; } @@ -176,11 +160,11 @@ public class RemoteOperationResult implements Serializable { public boolean isSslRecoverableException() { return mCode == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED; } - + private CertificateCombinedException getCertificateCombinedException(Exception e) { CertificateCombinedException result = null; if (e instanceof CertificateCombinedException) { - return (CertificateCombinedException)e; + return (CertificateCombinedException) e; } Throwable cause = mException.getCause(); Throwable previousCause = null; @@ -189,39 +173,38 @@ public class RemoteOperationResult implements Serializable { cause = cause.getCause(); } if (cause != null && cause instanceof CertificateCombinedException) { - result = (CertificateCombinedException)cause; + result = (CertificateCombinedException) cause; } return result; } - - + public String getLogMessage() { - + if (mException != null) { if (mException instanceof OperationCancelledException) { return "Operation cancelled by the caller"; - - } else if (mException instanceof SocketException) { + + } else if (mException instanceof SocketException) { return "Socket exception"; - + } else if (mException instanceof SocketTimeoutException) { return "Socket timeout exception"; - + } else if (mException instanceof ConnectTimeoutException) { return "Connect timeout exception"; - + } else if (mException instanceof MalformedURLException) { return "Malformed URL exception"; - + } else if (mException instanceof UnknownHostException) { return "Unknown host exception"; - + } else if (mException instanceof CertificateCombinedException) { if (((CertificateCombinedException) mException).isRecoverable()) return "SSL recoverable exception"; else return "SSL exception"; - + } else if (mException instanceof SSLException) { return "SSL exception"; @@ -238,25 +221,25 @@ public class RemoteOperationResult implements Serializable { return "Unexpected exception"; } } - + if (mCode == ResultCode.INSTANCE_NOT_CONFIGURED) { return "The ownCloud server is not configured!"; - + } else if (mCode == ResultCode.NO_NETWORK_CONNECTION) { return "No network connection"; - + } else if (mCode == ResultCode.BAD_OC_VERSION) { return "No valid ownCloud version was found at the server"; - + } else if (mCode == ResultCode.LOCAL_STORAGE_FULL) { return "Local storage full"; - + } else if (mCode == ResultCode.LOCAL_STORAGE_NOT_MOVED) { return "Error while moving file to final directory"; } - - return "Operation finished with HTTP status code " + mHttpCode + " (" + (isSuccess()?"success":"fail") + ")"; - + + return "Operation finished with HTTP status code " + mHttpCode + " (" + (isSuccess() ? "success" : "fail") + ")"; + } } diff --git a/src/com/owncloud/android/ui/activity/InstantUploadActivity.java b/src/com/owncloud/android/ui/activity/InstantUploadActivity.java index 4325b8ab..aaeac616 100644 --- a/src/com/owncloud/android/ui/activity/InstantUploadActivity.java +++ b/src/com/owncloud/android/ui/activity/InstantUploadActivity.java @@ -32,6 +32,7 @@ import android.util.SparseArray; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.widget.Button; import android.widget.CheckBox; @@ -39,6 +40,7 @@ import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ImageButton; import android.widget.LinearLayout; +import android.widget.TextView; import android.widget.Toast; import com.owncloud.android.AccountUtils; @@ -46,7 +48,7 @@ import com.owncloud.android.R; import com.owncloud.android.db.DbHandler; import com.owncloud.android.files.InstantUploadBroadcastReceiver; import com.owncloud.android.files.services.FileUploader; -import com.owncloud.android.files.services.InstantUploadService; +import com.owncloud.android.utils.FileStorageUtils; /** * This Activity is used to display a list with images they could not be @@ -77,6 +79,7 @@ public class InstantUploadActivity extends Activity { private int lastLoadImageIdx = 0; private SparseArray fileList = null; + CheckBox failed_upload_all_cb; @Override protected void onCreate(Bundle savedInstanceState) { @@ -87,7 +90,7 @@ public class InstantUploadActivity extends Activity { delete_all_btn.setOnClickListener(getDeleteListner()); Button retry_all_btn = (Button) findViewById(R.id.failed_upload_retry_all_btn); retry_all_btn.setOnClickListener(getRetryListner()); - CheckBox failed_upload_all_cb = (CheckBox) findViewById(R.id.failed_upload_headline_cb); + this.failed_upload_all_cb = (CheckBox) findViewById(R.id.failed_upload_headline_cb); failed_upload_all_cb.setOnCheckedChangeListener(getCheckAllListener()); listView = (LinearLayout) findViewById(R.id.failed_upload_scrollviewlayout); @@ -121,11 +124,12 @@ public class InstantUploadActivity extends Activity { lastLoadImageIdx++; String imp_path = c.getString(1); + String message = c.getString(4); fileList.put(lastLoadImageIdx, imp_path); - LinearLayout rowLayout = getLinearLayout(lastLoadImageIdx); + LinearLayout rowLayout = getHorizontalLinearLayout(lastLoadImageIdx); rowLayout.addView(getFileCheckbox(lastLoadImageIdx)); rowLayout.addView(getImageButton(imp_path, lastLoadImageIdx)); - rowLayout.addView(getFileButton(imp_path, lastLoadImageIdx)); + rowLayout.addView(getFileButton(imp_path, message, lastLoadImageIdx)); listView.addView(rowLayout); Log.d(LOG_TAG, imp_path + " on idx: " + lastLoadImageIdx); if (lastLoadImageIdx % MAX_LOAD_IMAGES == 0) { @@ -241,6 +245,7 @@ public class InstantUploadActivity extends Activity { public void onClick(View v) { try { + List list = getCheckboxList(); for (CheckBox checkbox : list) { boolean to_retry = checkbox.isChecked(); @@ -259,6 +264,9 @@ public class InstantUploadActivity extends Activity { // refresh the List listView.removeAllViews(); loadListView(true); + if (failed_upload_all_cb != null) { + failed_upload_all_cb.setChecked(false); + } } } @@ -276,6 +284,7 @@ public class InstantUploadActivity extends Activity { @Override public void onClick(View v) { + final DbHandler dbh = new DbHandler(getApplicationContext()); try { List list = getCheckboxList(); @@ -297,13 +306,16 @@ public class InstantUploadActivity extends Activity { // refresh the List listView.removeAllViews(); loadListView(true); + if (failed_upload_all_cb != null) { + failed_upload_all_cb.setChecked(false); + } } } }; } - private LinearLayout getLinearLayout(int id) { + private LinearLayout getHorizontalLinearLayout(int id) { LinearLayout linearLayout = new LinearLayout(getApplicationContext()); linearLayout.setId(id); linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, @@ -313,14 +325,51 @@ public class InstantUploadActivity extends Activity { return linearLayout; } - private Button getFileButton(final String img_path, int id) { - Button retryButton = new Button(this); + private LinearLayout getVerticalLinearLayout() { + LinearLayout linearLayout = new LinearLayout(getApplicationContext()); + linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.MATCH_PARENT)); + linearLayout.setGravity(Gravity.TOP); + linearLayout.setOrientation(LinearLayout.VERTICAL); + return linearLayout; + } + + private View getFileButton(final String img_path, String message, int id) { + + TextView failureTextView = new TextView(this); + failureTextView.setText(getString(R.string.failed_upload_failure_text) + message); + failureTextView.setBackgroundResource(R.color.owncloud_white); + failureTextView.setTextSize(8); + failureTextView.setOnLongClickListener(getOnLongClickListener(message)); + failureTextView.setPadding(5, 5, 5, 10); + TextView retryButton = new TextView(this); retryButton.setId(id); retryButton.setText(img_path); retryButton.setBackgroundResource(R.color.owncloud_white); retryButton.setTextSize(8); retryButton.setOnClickListener(getImageButtonOnClickListener(img_path)); - return retryButton; + retryButton.setOnLongClickListener(getOnLongClickListener(message)); + retryButton.setPadding(5, 5, 5, 10); + LinearLayout verticalLayout = getVerticalLinearLayout(); + verticalLayout.addView(retryButton); + verticalLayout.addView(failureTextView); + + return verticalLayout; + } + + private OnLongClickListener getOnLongClickListener(final String message) { + return new OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + Log.d(LOG_TAG, message); + Toast toast = Toast.makeText(InstantUploadActivity.this, getString(R.string.failed_upload_retry_text) + + message, Toast.LENGTH_LONG); + toast.show(); + return true; + } + + }; } private CheckBox getFileCheckbox(int id) { @@ -390,13 +439,13 @@ public class InstantUploadActivity extends Activity { */ private void startUpload(String img_path) { // extract filename - String filename = img_path.substring(img_path.lastIndexOf('/'), img_path.length()); + String filename = FileStorageUtils.getInstantUploadFilePath(img_path); if (canInstantUpload()) { Account account = AccountUtils.getCurrentOwnCloudAccount(InstantUploadActivity.this); // add file again to upload queue DbHandler db = new DbHandler(InstantUploadActivity.this); try { - db.updateFileState(img_path, DbHandler.UPLOAD_STATUS_UPLOAD_LATER); + db.updateFileState(img_path, DbHandler.UPLOAD_STATUS_UPLOAD_LATER, null); } finally { db.close(); } @@ -404,7 +453,7 @@ public class InstantUploadActivity extends Activity { Intent i = new Intent(InstantUploadActivity.this, FileUploader.class); i.putExtra(FileUploader.KEY_ACCOUNT, account); i.putExtra(FileUploader.KEY_LOCAL_FILE, img_path); - i.putExtra(FileUploader.KEY_REMOTE_FILE, InstantUploadService.INSTANT_UPLOAD_DIR + "/" + filename); + i.putExtra(FileUploader.KEY_REMOTE_FILE, filename); i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE); i.putExtra(com.owncloud.android.files.services.FileUploader.KEY_INSTANT_UPLOAD, true); diff --git a/src/com/owncloud/android/utils/FileStorageUtils.java b/src/com/owncloud/android/utils/FileStorageUtils.java index 5406cb5a..72815a9a 100644 --- a/src/com/owncloud/android/utils/FileStorageUtils.java +++ b/src/com/owncloud/android/utils/FileStorageUtils.java @@ -20,12 +20,14 @@ package com.owncloud.android.utils; import java.io.File; +import android.annotation.SuppressLint; import android.net.Uri; import android.os.Environment; import android.os.StatFs; +import android.util.Log; import com.owncloud.android.datamodel.OCFile; - +import com.owncloud.android.files.services.InstantUploadService; /** * Static methods to help in access to local file system. @@ -33,33 +35,56 @@ import com.owncloud.android.datamodel.OCFile; * @author David A. Velasco */ public class FileStorageUtils { - + private static final String LOG_TAG = "FileStorageUtils"; + public static final String getSavePath(String accountName) { File sdCard = Environment.getExternalStorageDirectory(); - return sdCard.getAbsolutePath() + "/owncloud/" + Uri.encode(accountName, "@"); - // URL encoding is an 'easy fix' to overcome that NTFS and FAT32 don't allow ":" in file names, that can be in the accountName since 0.1.190B + return sdCard.getAbsolutePath() + "/owncloud/" + Uri.encode(accountName, "@"); + // URL encoding is an 'easy fix' to overcome that NTFS and FAT32 don't allow ":" in file names, that can be in the accountName since 0.1.190B } - + public static final String getDefaultSavePathFor(String accountName, OCFile file) { return getSavePath(accountName) + file.getRemotePath(); } - + public static final String getTemporalPath(String accountName) { File sdCard = Environment.getExternalStorageDirectory(); return sdCard.getAbsolutePath() + "/owncloud/tmp/" + Uri.encode(accountName, "@"); // URL encoding is an 'easy fix' to overcome that NTFS and FAT32 don't allow ":" in file names, that can be in the accountName since 0.1.190B } + @SuppressLint("NewApi") public static final long getUsableSpace(String accountName) { File savePath = Environment.getExternalStorageDirectory(); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) { return savePath.getUsableSpace(); - + } else { StatFs stats = new StatFs(savePath.getAbsolutePath()); return stats.getAvailableBlocks() * stats.getBlockSize(); } - + + } + + // to ensure we will not add the slash twice between filename and + // folder-name + private static String getFileName(String filepath) { + if (filepath != null && !"".equals(filepath)) { + int psi = filepath.lastIndexOf('/'); + String filename = filepath; + if (psi > -1) { + filename = filepath.substring(psi + 1, filepath.length()); + Log.d(LOG_TAG, "extracted filename :" + filename); + } + return filename; + } else { + // Toast + Log.w(LOG_TAG, "the given filename was null or empty"); + return null; + } + } + + public static String getInstantUploadFilePath(String fileName) { + return InstantUploadService.INSTANT_UPLOAD_DIR + "/" + getFileName(fileName); } - } \ No newline at end of file