mirror of
https://github.com/nextcloud/android.git
synced 2024-11-24 22:25:44 +03:00
restructuring
added for uploading KEY_WHILE_CHARGING_ONLY
This commit is contained in:
parent
d08e4369f7
commit
949c2ae3c0
3 changed files with 174 additions and 64 deletions
|
@ -113,6 +113,10 @@ public class UploadDbObject implements Serializable {
|
|||
* Upload only via wifi?
|
||||
*/
|
||||
boolean isUseWifiOnly;
|
||||
/**
|
||||
* Upload only if phone being charged?
|
||||
*/
|
||||
boolean isWhileChargingOnly;
|
||||
/**
|
||||
* Name of Owncloud account to upload file to.
|
||||
*/
|
||||
|
@ -270,4 +274,12 @@ public class UploadDbObject implements Serializable {
|
|||
return AccountUtils.getOwnCloudAccountByName(context, getAccountName());
|
||||
}
|
||||
|
||||
public void setWhileChargingOnly(boolean isWhileChargingOnly) {
|
||||
this.isWhileChargingOnly = isWhileChargingOnly;
|
||||
}
|
||||
|
||||
public boolean isWhileChargingOnly() {
|
||||
return isWhileChargingOnly;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ import com.owncloud.android.ui.activity.FileActivity;
|
|||
import com.owncloud.android.ui.activity.FileDisplayActivity;
|
||||
import com.owncloud.android.ui.activity.UploadListActivity;
|
||||
import com.owncloud.android.utils.ErrorMessageAdapter;
|
||||
import com.owncloud.android.utils.UploadUtils;
|
||||
import com.owncloud.android.utils.UriUtils;
|
||||
|
||||
/**
|
||||
|
@ -122,6 +123,7 @@ public class FileUploadService extends IntentService {
|
|||
public static final String KEY_FORCE_OVERWRITE = "KEY_FORCE_OVERWRITE";
|
||||
public static final String KEY_CREATE_REMOTE_FOLDER = "CREATE_REMOTE_FOLDER";
|
||||
public static final String KEY_WIFI_ONLY = "WIFI_ONLY";
|
||||
public static final String KEY_WHILE_CHARGING_ONLY = "KEY_WHILE_CHARGING_ONLY";
|
||||
public static final String KEY_LOCAL_BEHAVIOUR = "BEHAVIOUR";
|
||||
|
||||
/**
|
||||
|
@ -255,7 +257,7 @@ public class FileUploadService extends IntentService {
|
|||
mDb.updateUpload(uploadDbObject);
|
||||
}
|
||||
|
||||
//TODO This service can be instantiated at any time. Move this retry call to start of app.
|
||||
//TODO This service can be instantiated at any time. Better move this retry call to start of app.
|
||||
if(InstantUploadBroadcastReceiver.isOnline(getApplicationContext())) {
|
||||
Log_OC.d(TAG, "FileUploadService.retry() called by onCreate()");
|
||||
FileUploadService.retry(getApplicationContext());
|
||||
|
@ -289,24 +291,26 @@ public class FileUploadService extends IntentService {
|
|||
Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size() + " - before adding new uploads.");
|
||||
if (intent == null || intent.hasExtra(KEY_RETRY)) {
|
||||
Log_OC.d(TAG, "Receive null intent.");
|
||||
// service was restarted by OS (after return START_STICKY and kill
|
||||
// service) or connectivity change was detected. ==> check persistent upload
|
||||
// list.
|
||||
//
|
||||
// service was restarted by OS or connectivity change was detected or
|
||||
// retry of pending upload was requested.
|
||||
// ==> First check persistent uploads, then perform upload.
|
||||
int countAddedEntries = 0;
|
||||
List<UploadDbObject> list = mDb.getAllPendingUploads();
|
||||
for (UploadDbObject uploadDbObject : list) {
|
||||
// store locally.
|
||||
String uploadKey = buildRemoteName(uploadDbObject);
|
||||
UploadDbObject previous = mPendingUploads.putIfAbsent(uploadKey, uploadDbObject);
|
||||
|
||||
if(previous == null) {
|
||||
// and store persistently.
|
||||
uploadDbObject.setUploadStatus(UploadStatus.UPLOAD_LATER);
|
||||
mDb.updateUpload(uploadDbObject);
|
||||
countAddedEntries++;
|
||||
} else {
|
||||
//upload already pending. ignore.
|
||||
}
|
||||
}
|
||||
Log_OC.d(TAG, "added " + countAddedEntries
|
||||
+ " entrie(s) to mPendingUploads (this should be 0 except for the first time).");
|
||||
} else {
|
||||
Log_OC.d(TAG, "Receive upload intent.");
|
||||
UploadSingleMulti uploadType = (UploadSingleMulti) intent.getSerializableExtra(KEY_UPLOAD_TYPE);
|
||||
|
@ -372,6 +376,7 @@ public class FileUploadService extends IntentService {
|
|||
boolean forceOverwrite = intent.getBooleanExtra(KEY_FORCE_OVERWRITE, false);
|
||||
boolean isCreateRemoteFolder = intent.getBooleanExtra(KEY_CREATE_REMOTE_FOLDER, false);
|
||||
boolean isUseWifiOnly = intent.getBooleanExtra(KEY_WIFI_ONLY, true);
|
||||
boolean isWhileChargingOnly = intent.getBooleanExtra(KEY_WHILE_CHARGING_ONLY, true);
|
||||
LocalBehaviour localAction = (LocalBehaviour) intent.getSerializableExtra(KEY_LOCAL_BEHAVIOUR);
|
||||
if (localAction == null)
|
||||
localAction = LocalBehaviour.LOCAL_BEHAVIOUR_COPY;
|
||||
|
@ -385,6 +390,7 @@ public class FileUploadService extends IntentService {
|
|||
uploadObject.setCreateRemoteFolder(isCreateRemoteFolder);
|
||||
uploadObject.setLocalAction(localAction);
|
||||
uploadObject.setUseWifiOnly(isUseWifiOnly);
|
||||
uploadObject.setWhileChargingOnly(isWhileChargingOnly);
|
||||
uploadObject.setUploadStatus(UploadStatus.UPLOAD_LATER);
|
||||
|
||||
String uploadKey = buildRemoteName(uploadObject);
|
||||
|
@ -402,27 +408,46 @@ public class FileUploadService extends IntentService {
|
|||
// upload already pending. ignore.
|
||||
}
|
||||
}
|
||||
|
||||
// TODO check if would be clever to read entries from
|
||||
// UploadDbHandler and add to requestedUploads at this point
|
||||
|
||||
}
|
||||
|
||||
// at this point mPendingUploads is filled.
|
||||
|
||||
Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size() + " - before uploading.");
|
||||
|
||||
try {
|
||||
Iterator<String> it = mPendingUploads.keySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
String up = it.next();
|
||||
Log_OC.d(TAG, "Calling uploadFile for " + up);
|
||||
UploadDbObject uploadDbObject = mPendingUploads.get(up);
|
||||
boolean uploadSuccessful = uploadFile(uploadDbObject);
|
||||
String upload = it.next();
|
||||
UploadDbObject uploadDbObject = mPendingUploads.get(upload);
|
||||
|
||||
switch (canUploadFileNow(uploadDbObject)) {
|
||||
case NOW:
|
||||
Log_OC.d(TAG, "Calling uploadFile for " + upload);
|
||||
RemoteOperationResult uploadResult = uploadFile(uploadDbObject);
|
||||
|
||||
updateDataseUploadResult(uploadResult, mCurrentUpload);
|
||||
notifyUploadResult(uploadResult, mCurrentUpload);
|
||||
sendFinalBroadcast(uploadResult, mCurrentUpload);
|
||||
if (!shouldRetryFailedUpload(uploadResult)) {
|
||||
Log_OC.d(TAG, "Upload with result " + uploadResult.getCode() + ": " + uploadResult.getLogMessage()
|
||||
+ " will be abandoned.");
|
||||
mPendingUploads.remove(buildRemoteName(uploadDbObject));
|
||||
}
|
||||
} catch (ConcurrentModificationException e) {
|
||||
// for now: ignore. TODO: fix this.
|
||||
mCurrentUpload = null;
|
||||
break;
|
||||
case LATER:
|
||||
//TODO schedule retry for later upload.
|
||||
break;
|
||||
case FILE_GONE:
|
||||
mDb.updateUpload(uploadDbObject.getLocalPath(), UploadStatus.UPLOAD_FAILED_GIVE_UP,
|
||||
new RemoteOperationResult(ResultCode.FILE_NOT_FOUND));
|
||||
it.remove();
|
||||
break;
|
||||
case ERROR:
|
||||
Log_OC.e(TAG, "canUploadFileNow() returned ERROR. Fix that!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size() + " - after uploading.");
|
||||
Log_OC.i(TAG, "onHandleIntent end");
|
||||
}
|
||||
|
@ -564,38 +589,67 @@ public class FileUploadService extends IntentService {
|
|||
}
|
||||
}
|
||||
|
||||
enum CanUploadFileNowStatus {NOW, LATER, FILE_GONE, ERROR};
|
||||
|
||||
/**
|
||||
* Core upload method: sends the file(s) to upload. This function blocks
|
||||
* until upload succeeded or failed.
|
||||
* Returns true when the file may be uploaded now. This methods checks all
|
||||
* restraints of the passed {@link UploadDbObject}, these include
|
||||
* isUseWifiOnly(), check if local file exists, check if file was already
|
||||
* uploaded...
|
||||
*
|
||||
* If return value is CanUploadFileNowStatus.NOW, uploadFile() may be
|
||||
* called.
|
||||
*
|
||||
* @return CanUploadFileNowStatus.NOW is upload may proceed, <br>
|
||||
* CanUploadFileNowStatus.LATER if upload should be performed at a
|
||||
* later time, <br>
|
||||
* CanUploadFileNowStatus.ERROR if a severe error happened, calling
|
||||
* entity should remove upload from queue.
|
||||
*
|
||||
* @param uploadDbObject Key to access the upload to perform, contained in
|
||||
* mPendingUploads
|
||||
* @return true on success.
|
||||
*/
|
||||
private boolean uploadFile(UploadDbObject uploadDbObject) {
|
||||
private CanUploadFileNowStatus canUploadFileNow(UploadDbObject uploadDbObject) {
|
||||
|
||||
if(uploadDbObject.getUploadStatus() == UploadStatus.UPLOAD_SUCCEEDED) {
|
||||
if (uploadDbObject.getUploadStatus() == UploadStatus.UPLOAD_SUCCEEDED) {
|
||||
Log_OC.w(TAG, "Already succeeded uploadObject was again scheduled for upload. Fix that!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mCurrentUpload != null) {
|
||||
Log_OC.e(TAG,
|
||||
"mCurrentUpload != null. Meaning there is another upload in progress, cannot start a new one. Fix that!");
|
||||
return false;
|
||||
return CanUploadFileNowStatus.ERROR;
|
||||
}
|
||||
|
||||
if (uploadDbObject.isUseWifiOnly()
|
||||
&& !InstantUploadBroadcastReceiver.isConnectedViaWiFi(getApplicationContext())) {
|
||||
Log_OC.d(TAG, "Do not start upload because it is wifi-only.");
|
||||
return false;
|
||||
return CanUploadFileNowStatus.LATER;
|
||||
}
|
||||
|
||||
if(uploadDbObject.isWhileChargingOnly() && !UploadUtils.isCharging(getApplicationContext())) {
|
||||
Log_OC.d(TAG, "Do not start upload because it is while charging only.");
|
||||
return CanUploadFileNowStatus.LATER;
|
||||
}
|
||||
|
||||
if (!new File(uploadDbObject.getLocalPath()).exists()) {
|
||||
mDb.updateUpload(uploadDbObject.getLocalPath(), UploadStatus.UPLOAD_FAILED_GIVE_UP,
|
||||
new RemoteOperationResult(ResultCode.FILE_NOT_FOUND));
|
||||
Log_OC.d(TAG, "Do not start upload because local file does not exist.");
|
||||
return false;
|
||||
return CanUploadFileNowStatus.FILE_GONE;
|
||||
}
|
||||
return CanUploadFileNowStatus.NOW;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Core upload method: sends the file(s) to upload. This function blocks
|
||||
* until upload succeeded or failed.
|
||||
*
|
||||
* Before uploading starts mCurrentUpload is set.
|
||||
*
|
||||
* @param uploadDbObject Key to access the upload to perform, contained in
|
||||
* mPendingUploads
|
||||
* @return RemoteOperationResult of upload operation.
|
||||
*/
|
||||
private RemoteOperationResult uploadFile(UploadDbObject uploadDbObject) {
|
||||
|
||||
if (mCurrentUpload != null) {
|
||||
Log_OC.e(TAG,
|
||||
"mCurrentUpload != null. Meaning there is another upload in progress, cannot start a new one. Fix that!");
|
||||
return new RemoteOperationResult(new IllegalStateException("mCurrentUpload != null when calling uploadFile()"));
|
||||
}
|
||||
|
||||
AccountManager aMgr = AccountManager.get(this);
|
||||
|
@ -656,7 +710,6 @@ public class FileUploadService extends IntentService {
|
|||
uploadResult = new RemoteOperationResult(e);
|
||||
|
||||
} finally {
|
||||
mPendingUploads.remove(buildRemoteName(uploadDbObject));
|
||||
Log_OC.i(TAG, "Remove CurrentUploadItem from pending upload Item Map.");
|
||||
if (uploadResult.isException()) {
|
||||
// enforce the creation of a new client object for next
|
||||
|
@ -666,14 +719,7 @@ public class FileUploadService extends IntentService {
|
|||
mUploadClient = null;
|
||||
}
|
||||
}
|
||||
|
||||
// notify result
|
||||
notifyUploadResult(uploadResult, mCurrentUpload);
|
||||
sendFinalBroadcast(mCurrentUpload, uploadResult);
|
||||
|
||||
mCurrentUpload = null;
|
||||
|
||||
return uploadResult.isSuccess();
|
||||
return uploadResult;
|
||||
}
|
||||
|
||||
|
||||
|
@ -846,6 +892,13 @@ public class FileUploadService extends IntentService {
|
|||
|
||||
mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotificationBuilder.build());
|
||||
|
||||
updateDatabaseUploadStart(mCurrentUpload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the persistent upload database that upload is in progress.
|
||||
*/
|
||||
private void updateDatabaseUploadStart(UploadFileOperation upload) {
|
||||
mDb.updateUpload(upload.getOriginalStoragePath(), UploadStatus.UPLOAD_IN_PROGRESS, null);
|
||||
}
|
||||
|
||||
|
@ -910,34 +963,61 @@ public class FileUploadService extends IntentService {
|
|||
|
||||
if (uploadResult.isSuccess()) {
|
||||
|
||||
mDb.updateUpload(upload.getOriginalStoragePath(), UploadStatus.UPLOAD_SUCCEEDED, uploadResult);
|
||||
|
||||
// remove success notification, with a delay of 2 seconds
|
||||
NotificationDelayer.cancelWithDelay(mNotificationManager, R.string.uploader_upload_succeeded_ticker,
|
||||
2000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the persistent upload database with upload result.
|
||||
*/
|
||||
private void updateDataseUploadResult(RemoteOperationResult uploadResult, UploadFileOperation upload) {
|
||||
// result: success or fail notification
|
||||
if (uploadResult.isCancelled()) {
|
||||
mDb.updateUpload(upload.getOriginalStoragePath(), UploadStatus.UPLOAD_CANCELLED, uploadResult);
|
||||
} else {
|
||||
|
||||
if (uploadResult.isSuccess()) {
|
||||
mDb.updateUpload(upload.getOriginalStoragePath(), UploadStatus.UPLOAD_SUCCEEDED, uploadResult);
|
||||
} else {
|
||||
if (shouldRetryFailedUpload(uploadResult)) {
|
||||
mDb.updateUpload(upload.getOriginalStoragePath(), UploadStatus.UPLOAD_FAILED_RETRY, uploadResult);
|
||||
} else {
|
||||
// TODO: add other cases in which upload attempt is to be
|
||||
// abandoned.
|
||||
if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
|
||||
mDb.updateUpload(upload.getOriginalStoragePath(),
|
||||
UploadDbHandler.UploadStatus.UPLOAD_FAILED_GIVE_UP, uploadResult);
|
||||
} else {
|
||||
mDb.updateUpload(upload.getOriginalStoragePath(), UploadStatus.UPLOAD_FAILED_RETRY, uploadResult);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mDb.updateUpload(upload.getOriginalStoragePath(), UploadStatus.UPLOAD_FAILED_RETRY, uploadResult);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether with given uploadResult the upload should be retried later.
|
||||
* @param uploadResult
|
||||
* @return true if upload should be retried later, false if is should be abandoned.
|
||||
*/
|
||||
private boolean shouldRetryFailedUpload(RemoteOperationResult uploadResult) {
|
||||
if (uploadResult.isSuccess()) {
|
||||
return false;
|
||||
}
|
||||
switch (uploadResult.getCode()) {
|
||||
case HOST_NOT_AVAILABLE:
|
||||
case NO_NETWORK_CONNECTION:
|
||||
case TIMEOUT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a broadcast in order to the interested activities can update their
|
||||
* view
|
||||
*
|
||||
* @param upload Finished upload operation
|
||||
* @param uploadResult Result of the upload operation
|
||||
* @param upload Finished upload operation
|
||||
*/
|
||||
private void sendFinalBroadcast(UploadFileOperation upload, RemoteOperationResult uploadResult) {
|
||||
private void sendFinalBroadcast(RemoteOperationResult uploadResult, UploadFileOperation upload) {
|
||||
Intent end = new Intent(getUploadFinishMessage());
|
||||
end.putExtra(EXTRA_REMOTE_PATH, upload.getRemotePath()); // real remote
|
||||
// path, after
|
||||
|
|
18
src/com/owncloud/android/utils/UploadUtils.java
Executable file
18
src/com/owncloud/android/utils/UploadUtils.java
Executable file
|
@ -0,0 +1,18 @@
|
|||
package com.owncloud.android.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.BatteryManager;
|
||||
|
||||
|
||||
public class UploadUtils {
|
||||
|
||||
public static boolean isCharging(Context context) {
|
||||
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
||||
Intent batteryStatus = context.registerReceiver(null, ifilter);
|
||||
|
||||
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
|
||||
return status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue