Merge pull request #5761 from nextcloud/ezaquarii/migrate-file-downloader-service-to-user-model

Migrate FileDownloader server to User model
This commit is contained in:
Tobias Kaminsky 2020-04-09 15:08:26 +02:00 committed by GitHub
commit 517437eba9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 116 additions and 82 deletions

View file

@ -21,7 +21,7 @@ public interface CurrentAccountProvider {
Account getCurrentAccount(); Account getCurrentAccount();
/** /**
* Get currently active user profile. If there is no actice user, anonymous user is returned. * Get currently active user profile. If there is no active user, anonymous user is returned.
* *
* @return User profile. Profile is never null. * @return User profile. Profile is never null.
*/ */

View file

@ -38,6 +38,7 @@ import android.os.Message;
import android.os.Process; import android.os.Process;
import android.util.Pair; import android.util.Pair;
import com.nextcloud.client.account.User;
import com.nextcloud.client.account.UserAccountManager; import com.nextcloud.client.account.UserAccountManager;
import com.owncloud.android.R; import com.owncloud.android.R;
import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.authentication.AuthenticatorActivity;
@ -80,7 +81,7 @@ import dagger.android.AndroidInjection;
public class FileDownloader extends Service public class FileDownloader extends Service
implements OnDatatransferProgressListener, OnAccountsUpdateListener { implements OnDatatransferProgressListener, OnAccountsUpdateListener {
public static final String EXTRA_ACCOUNT = "ACCOUNT"; public static final String EXTRA_USER = "USER";
public static final String EXTRA_FILE = "FILE"; public static final String EXTRA_FILE = "FILE";
private static final String DOWNLOAD_ADDED_MESSAGE = "DOWNLOAD_ADDED"; private static final String DOWNLOAD_ADDED_MESSAGE = "DOWNLOAD_ADDED";
@ -192,11 +193,11 @@ public class FileDownloader extends Service
startForeground(FOREGROUND_SERVICE_ID, mNotification); startForeground(FOREGROUND_SERVICE_ID, mNotification);
if (intent == null || !intent.hasExtra(EXTRA_ACCOUNT) || !intent.hasExtra(EXTRA_FILE)) { if (intent == null || !intent.hasExtra(EXTRA_USER) || !intent.hasExtra(EXTRA_FILE)) {
Log_OC.e(TAG, "Not enough information provided in intent"); Log_OC.e(TAG, "Not enough information provided in intent");
return START_NOT_STICKY; return START_NOT_STICKY;
} else { } else {
final Account account = intent.getParcelableExtra(EXTRA_ACCOUNT); final User user = intent.getParcelableExtra(EXTRA_USER);
final OCFile file = intent.getParcelableExtra(EXTRA_FILE); final OCFile file = intent.getParcelableExtra(EXTRA_FILE);
final String behaviour = intent.getStringExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR); final String behaviour = intent.getStringExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR);
String activityName = intent.getStringExtra(SendShareDialog.ACTIVITY_NAME); String activityName = intent.getStringExtra(SendShareDialog.ACTIVITY_NAME);
@ -204,12 +205,17 @@ public class FileDownloader extends Service
this.conflictUpload = intent.getParcelableExtra(FileDownloader.EXTRA_CONFLICT_UPLOAD); this.conflictUpload = intent.getParcelableExtra(FileDownloader.EXTRA_CONFLICT_UPLOAD);
AbstractList<String> requestedDownloads = new Vector<String>(); AbstractList<String> requestedDownloads = new Vector<String>();
try { try {
DownloadFileOperation newDownload = new DownloadFileOperation(account, file, behaviour, activityName, DownloadFileOperation newDownload = new DownloadFileOperation(user.toPlatformAccount(),
packageName, getBaseContext()); file,
behaviour,
activityName,
packageName,
getBaseContext());
newDownload.addDatatransferProgressListener(this); newDownload.addDatatransferProgressListener(this);
newDownload.addDatatransferProgressListener((FileDownloaderBinder) mBinder); newDownload.addDatatransferProgressListener((FileDownloaderBinder) mBinder);
Pair<String, String> putResult = mPendingDownloads.putIfAbsent( Pair<String, String> putResult = mPendingDownloads.putIfAbsent(user.getAccountName(),
account.name, file.getRemotePath(), newDownload); file.getRemotePath(),
newDownload);
if (putResult != null) { if (putResult != null) {
String downloadKey = putResult.first; String downloadKey = putResult.first;
requestedDownloads.add(downloadKey); requestedDownloads.add(downloadKey);
@ -232,7 +238,6 @@ public class FileDownloader extends Service
return START_NOT_STICKY; return START_NOT_STICKY;
} }
/** /**
* Provides a binder object that clients can use to perform operations on the queue of downloads, * Provides a binder object that clients can use to perform operations on the queue of downloads,
* excepting the addition of new files. * excepting the addition of new files.

View file

@ -157,8 +157,9 @@ public class OfflineSyncJob extends Job {
for (File file : files) { for (File file : files) {
OCFile ocFile = storageManager.getFileByLocalPath(file.getPath()); OCFile ocFile = storageManager.getFileByLocalPath(file.getPath());
SynchronizeFileOperation synchronizeFileOperation = new SynchronizeFileOperation(ocFile.getRemotePath(), SynchronizeFileOperation synchronizeFileOperation = new SynchronizeFileOperation(ocFile.getRemotePath(),
user.toPlatformAccount(), true, getContext()); user,
true,
getContext());
synchronizeFileOperation.execute(storageManager, getContext()); synchronizeFileOperation.execute(storageManager, getContext());
} }
} }

View file

@ -26,6 +26,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.text.TextUtils; import android.text.TextUtils;
import com.nextcloud.client.account.User;
import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.files.services.FileDownloader;
import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.files.services.FileUploader;
@ -48,7 +49,7 @@ public class SynchronizeFileOperation extends SyncOperation {
private OCFile mLocalFile; private OCFile mLocalFile;
private String mRemotePath; private String mRemotePath;
private OCFile mServerFile; private OCFile mServerFile;
private Account mAccount; private User mUser;
private boolean mSyncFileContents; private boolean mSyncFileContents;
private Context mContext; private Context mContext;
private boolean mTransferWasRequested; private boolean mTransferWasRequested;
@ -70,21 +71,21 @@ public class SynchronizeFileOperation extends SyncOperation {
* Useful for direct synchronization of a single file. * Useful for direct synchronization of a single file.
* *
* @param remotePath remote path of the file * @param remotePath remote path of the file
* @param account ownCloud account holding the file. * @param user Nextcloud user owning the file.
* @param syncFileContents When 'true', transference of data will be started by the * @param syncFileContents When 'true', transference of data will be started by the
* operation if needed and no conflict is detected. * operation if needed and no conflict is detected.
* @param context Android context; needed to start transfers. * @param context Android context; needed to start transfers.
*/ */
public SynchronizeFileOperation( public SynchronizeFileOperation(
String remotePath, String remotePath,
Account account, User user,
boolean syncFileContents, boolean syncFileContents,
Context context) { Context context) {
mRemotePath = remotePath; mRemotePath = remotePath;
mLocalFile = null; mLocalFile = null;
mServerFile = null; mServerFile = null;
mAccount = account; mUser = user;
mSyncFileContents = syncFileContents; mSyncFileContents = syncFileContents;
mContext = context; mContext = context;
mAllowUploads = true; mAllowUploads = true;
@ -105,7 +106,7 @@ public class SynchronizeFileOperation extends SyncOperation {
* @param localFile Data of file (just) retrieved from local cache/database. * @param localFile Data of file (just) retrieved from local cache/database.
* @param serverFile Data of file (just) retrieved from a remote server. If null, * @param serverFile Data of file (just) retrieved from a remote server. If null,
* will be retrieved from network by the operation when executed. * will be retrieved from network by the operation when executed.
* @param account ownCloud account holding the file. * @param user Nextcloud user owning the file.
* @param syncFileContents When 'true', transference of data will be started by the * @param syncFileContents When 'true', transference of data will be started by the
* operation if needed and no conflict is detected. * operation if needed and no conflict is detected.
* @param context Android context; needed to start transfers. * @param context Android context; needed to start transfers.
@ -113,7 +114,7 @@ public class SynchronizeFileOperation extends SyncOperation {
public SynchronizeFileOperation( public SynchronizeFileOperation(
OCFile localFile, OCFile localFile,
OCFile serverFile, OCFile serverFile,
Account account, User user,
boolean syncFileContents, boolean syncFileContents,
Context context) { Context context) {
@ -130,7 +131,7 @@ public class SynchronizeFileOperation extends SyncOperation {
} else { } else {
throw new IllegalArgumentException("Both serverFile and localFile are NULL"); throw new IllegalArgumentException("Both serverFile and localFile are NULL");
} }
mAccount = account; mUser = user;
mSyncFileContents = syncFileContents; mSyncFileContents = syncFileContents;
mContext = context; mContext = context;
mAllowUploads = true; mAllowUploads = true;
@ -153,7 +154,7 @@ public class SynchronizeFileOperation extends SyncOperation {
* @param serverFile Data of file (just) retrieved from a remote server. * @param serverFile Data of file (just) retrieved from a remote server.
* If null, will be retrieved from network by the operation * If null, will be retrieved from network by the operation
* when executed. * when executed.
* @param account ownCloud account holding the file. * @param user Nextcloud user owning the file.
* @param syncFileContents When 'true', transference of data will be started by the * @param syncFileContents When 'true', transference of data will be started by the
* operation if needed and no conflict is detected. * operation if needed and no conflict is detected.
* @param allowUploads When 'false', uploads to the server are not done; * @param allowUploads When 'false', uploads to the server are not done;
@ -163,12 +164,12 @@ public class SynchronizeFileOperation extends SyncOperation {
public SynchronizeFileOperation( public SynchronizeFileOperation(
OCFile localFile, OCFile localFile,
OCFile serverFile, OCFile serverFile,
Account account, User user,
boolean syncFileContents, boolean syncFileContents,
boolean allowUploads, boolean allowUploads,
Context context) { Context context) {
this(localFile, serverFile, account, syncFileContents, context); this(localFile, serverFile, user, syncFileContents, context);
mAllowUploads = allowUploads; mAllowUploads = allowUploads;
} }
@ -278,7 +279,7 @@ public class SynchronizeFileOperation extends SyncOperation {
} }
Log_OC.i(TAG, "Synchronizing " + mAccount.name + ", file " + mLocalFile.getRemotePath() + Log_OC.i(TAG, "Synchronizing " + mUser.getAccountName() + ", file " + mLocalFile.getRemotePath() +
": " + result.getLogMessage()); ": " + result.getLogMessage());
return result; return result;
@ -293,7 +294,7 @@ public class SynchronizeFileOperation extends SyncOperation {
private void requestForUpload(OCFile file) { private void requestForUpload(OCFile file) {
FileUploader.uploadUpdateFile( FileUploader.uploadUpdateFile(
mContext, mContext,
mAccount, mUser.toPlatformAccount(),
file, file,
FileUploader.LOCAL_BEHAVIOUR_MOVE, FileUploader.LOCAL_BEHAVIOUR_MOVE,
FileUploader.NameCollisionPolicy.OVERWRITE FileUploader.NameCollisionPolicy.OVERWRITE
@ -310,7 +311,7 @@ public class SynchronizeFileOperation extends SyncOperation {
*/ */
private void requestForDownload(OCFile file) { private void requestForDownload(OCFile file) {
Intent i = new Intent(mContext, FileDownloader.class); Intent i = new Intent(mContext, FileDownloader.class);
i.putExtra(FileDownloader.EXTRA_ACCOUNT, mAccount); i.putExtra(FileDownloader.EXTRA_USER, mUser);
i.putExtra(FileDownloader.EXTRA_FILE, file); i.putExtra(FileDownloader.EXTRA_FILE, file);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
mContext.startForegroundService(i); mContext.startForegroundService(i);

View file

@ -20,12 +20,12 @@
package com.owncloud.android.operations; package com.owncloud.android.operations;
import android.accounts.Account;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.nextcloud.client.account.User;
import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.files.services.FileDownloader;
@ -71,7 +71,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
private String mRemotePath; private String mRemotePath;
/** Account where the file to synchronize belongs */ /** Account where the file to synchronize belongs */
private Account mAccount; private User user;
/** Android context; necessary to send requests to the download service */ /** Android context; necessary to send requests to the download service */
private Context mContext; private Context mContext;
@ -101,14 +101,13 @@ public class SynchronizeFolderOperation extends SyncOperation {
* *
* @param context Application context. * @param context Application context.
* @param remotePath Path to synchronize. * @param remotePath Path to synchronize.
* @param account ownCloud account where the folder is located. * @param user Nextcloud account where the folder is located.
* @param currentSyncTime Time stamp for the synchronization process in progress. * @param currentSyncTime Time stamp for the synchronization process in progress.
*/ */
public SynchronizeFolderOperation(Context context, String remotePath, Account account, public SynchronizeFolderOperation(Context context, String remotePath, User user, long currentSyncTime){
long currentSyncTime){
mRemotePath = remotePath; mRemotePath = remotePath;
mCurrentSyncTime = currentSyncTime; mCurrentSyncTime = currentSyncTime;
mAccount = account; this.user = user;
mContext = context; mContext = context;
mRemoteFolderChanged = false; mRemoteFolderChanged = false;
mFilesForDirectDownload = new Vector<>(); mFilesForDirectDownload = new Vector<>();
@ -159,7 +158,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
} }
private RemoteOperationResult checkForChanges(OwnCloudClient client) throws OperationCancelledException { private RemoteOperationResult checkForChanges(OwnCloudClient client) throws OperationCancelledException {
Log_OC.d(TAG, "Checking changes in " + mAccount.name + mRemotePath); Log_OC.d(TAG, "Checking changes in " + user.getAccountName() + mRemotePath);
mRemoteFolderChanged = true; mRemoteFolderChanged = true;
@ -178,7 +177,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
result = new RemoteOperationResult(ResultCode.OK); result = new RemoteOperationResult(ResultCode.OK);
Log_OC.i(TAG, "Checked " + mAccount.name + mRemotePath + " : " + Log_OC.i(TAG, "Checked " + user.getAccountName() + mRemotePath + " : " +
(mRemoteFolderChanged ? "changed" : "not changed")); (mRemoteFolderChanged ? "changed" : "not changed"));
} else { } else {
@ -187,10 +186,10 @@ public class SynchronizeFolderOperation extends SyncOperation {
removeLocalFolder(); removeLocalFolder();
} }
if (result.isException()) { if (result.isException()) {
Log_OC.e(TAG, "Checked " + mAccount.name + mRemotePath + " : " + Log_OC.e(TAG, "Checked " + user.getAccountName() + mRemotePath + " : " +
result.getLogMessage(), result.getException()); result.getLogMessage(), result.getException());
} else { } else {
Log_OC.e(TAG, "Checked " + mAccount.name + mRemotePath + " : " + Log_OC.e(TAG, "Checked " + user.getAccountName() + mRemotePath + " : " +
result.getLogMessage()); result.getLogMessage());
} }
@ -207,7 +206,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
ReadFolderRemoteOperation operation = new ReadFolderRemoteOperation(mRemotePath); ReadFolderRemoteOperation operation = new ReadFolderRemoteOperation(mRemotePath);
RemoteOperationResult result = operation.execute(client); RemoteOperationResult result = operation.execute(client);
Log_OC.d(TAG, "Synchronizing " + mAccount.name + mRemotePath); Log_OC.d(TAG, "Synchronizing " + user.getAccountName() + mRemotePath);
if (result.isSuccess()) { if (result.isSuccess()) {
synchronizeData(result.getData()); synchronizeData(result.getData());
@ -228,7 +227,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
private void removeLocalFolder() { private void removeLocalFolder() {
FileDataStorageManager storageManager = getStorageManager(); FileDataStorageManager storageManager = getStorageManager();
if (storageManager.fileExists(mLocalFolder.getFileId())) { if (storageManager.fileExists(mLocalFolder.getFileId())) {
String currentSavePath = FileStorageUtils.getSavePath(mAccount.name); String currentSavePath = FileStorageUtils.getSavePath(user.getAccountName());
storageManager.removeFolder( storageManager.removeFolder(
mLocalFolder, mLocalFolder,
true, true,
@ -351,7 +350,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
SynchronizeFileOperation operation = new SynchronizeFileOperation( SynchronizeFileOperation operation = new SynchronizeFileOperation(
localFile, localFile,
remoteFile, remoteFile,
mAccount, user,
true, true,
mContext mContext
); );
@ -383,7 +382,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
SynchronizeFileOperation operation = new SynchronizeFileOperation( SynchronizeFileOperation operation = new SynchronizeFileOperation(
child, child,
child.getEtagInConflict() != null ? child : null, child.getEtagInConflict() != null ? child : null,
mAccount, user,
true, true,
mContext mContext
); );
@ -409,7 +408,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
throw new OperationCancelledException(); throw new OperationCancelledException();
} }
Intent i = new Intent(mContext, FileDownloader.class); Intent i = new Intent(mContext, FileDownloader.class);
i.putExtra(FileDownloader.EXTRA_ACCOUNT, mAccount); i.putExtra(FileDownloader.EXTRA_USER, user);
i.putExtra(FileDownloader.EXTRA_FILE, file); i.putExtra(FileDownloader.EXTRA_FILE, file);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
mContext.startForegroundService(i); mContext.startForegroundService(i);
@ -465,7 +464,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
*/ */
private void searchForLocalFileInDefaultPath(OCFile file) { private void searchForLocalFileInDefaultPath(OCFile file) {
if (file.getStoragePath() == null && !file.isFolder()) { if (file.getStoragePath() == null && !file.isFolder()) {
File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file)); File f = new File(FileStorageUtils.getDefaultSavePathFor(user.getAccountName(), file));
if (f.exists()) { if (f.exists()) {
file.setStoragePath(f.getAbsolutePath()); file.setStoragePath(f.getAbsolutePath());
file.setLastSyncDateForData(f.lastModified()); file.setLastSyncDateForData(f.lastModified());
@ -486,13 +485,13 @@ public class SynchronizeFolderOperation extends SyncOperation {
if (!TextUtils.isEmpty(path)) { if (!TextUtils.isEmpty(path)) {
return path; return path;
} }
return FileStorageUtils.getDefaultSavePathFor(mAccount.name, mLocalFolder); return FileStorageUtils.getDefaultSavePathFor(user.getAccountName(), mLocalFolder);
} }
private void startSyncFolderOperation(String path){ private void startSyncFolderOperation(String path){
Intent intent = new Intent(mContext, OperationsService.class); Intent intent = new Intent(mContext, OperationsService.class);
intent.setAction(OperationsService.ACTION_SYNC_FOLDER); intent.setAction(OperationsService.ACTION_SYNC_FOLDER);
intent.putExtra(OperationsService.EXTRA_ACCOUNT, mAccount); intent.putExtra(OperationsService.EXTRA_ACCOUNT, user);
intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, path); intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, path);
mContext.startService(intent); mContext.startService(intent);
} }

View file

@ -47,6 +47,7 @@ import android.util.Log;
import android.util.SparseArray; import android.util.SparseArray;
import android.widget.Toast; import android.widget.Toast;
import com.nextcloud.client.account.User;
import com.nextcloud.client.account.UserAccountManager; import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.account.UserAccountManagerImpl; import com.nextcloud.client.account.UserAccountManagerImpl;
import com.nextcloud.client.preferences.AppPreferences; import com.nextcloud.client.preferences.AppPreferences;
@ -198,10 +199,11 @@ public class DocumentsStorageProvider extends DocumentsProvider {
OCFile ocFile = document.getFile(); OCFile ocFile = document.getFile();
Account account = document.getAccount(); Account account = document.getAccount();
final User user = accountManager.getUser(account.name).orElseThrow(RuntimeException::new); // should exist
if (!ocFile.isDown()) { if (!ocFile.isDown()) {
Intent i = new Intent(getContext(), FileDownloader.class); Intent i = new Intent(getContext(), FileDownloader.class);
i.putExtra(FileDownloader.EXTRA_ACCOUNT, account); i.putExtra(FileDownloader.EXTRA_USER, user);
i.putExtra(FileDownloader.EXTRA_FILE, ocFile); i.putExtra(FileDownloader.EXTRA_FILE, ocFile);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
context.startForegroundService(i); context.startForegroundService(i);
@ -223,8 +225,9 @@ public class DocumentsStorageProvider extends DocumentsProvider {
OCFile finalFile = ocFile; OCFile finalFile = ocFile;
Thread syncThread = new Thread(() -> { Thread syncThread = new Thread(() -> {
try { try {
FileDataStorageManager storageManager = new FileDataStorageManager(account, context.getContentResolver()); FileDataStorageManager storageManager = new FileDataStorageManager(user.toPlatformAccount(),
RemoteOperationResult result = new SynchronizeFileOperation(finalFile, null, account, context.getContentResolver());
RemoteOperationResult result = new SynchronizeFileOperation(finalFile, null, user,
true, context) true, context)
.execute(storageManager, context); .execute(storageManager, context);
if (result.getCode() == RemoteOperationResult.ResultCode.SYNC_CONFLICT) { if (result.getCode() == RemoteOperationResult.ResultCode.SYNC_CONFLICT) {
@ -233,7 +236,7 @@ public class DocumentsStorageProvider extends DocumentsProvider {
Intent i = new Intent(context, ConflictsResolveActivity.class); Intent i = new Intent(context, ConflictsResolveActivity.class);
i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra(ConflictsResolveActivity.EXTRA_FILE, finalFile); i.putExtra(ConflictsResolveActivity.EXTRA_FILE, finalFile);
i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, account); i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, user.toPlatformAccount());
context.startActivity(i); context.startActivity(i);
} else { } else {
FileStorageUtils.checkIfFileFinishedSaving(finalFile); FileStorageUtils.checkIfFileFinishedSaving(finalFile);
@ -265,7 +268,7 @@ public class DocumentsStorageProvider extends DocumentsProvider {
try { try {
Handler handler = new Handler(context.getMainLooper()); Handler handler = new Handler(context.getMainLooper());
return ParcelFileDescriptor.open(file, accessMode, handler, l -> { return ParcelFileDescriptor.open(file, accessMode, handler, l -> {
RemoteOperationResult result = new SynchronizeFileOperation(newFile, oldFile, account, true, RemoteOperationResult result = new SynchronizeFileOperation(newFile, oldFile, user, true,
context) context)
.execute(document.getClient(), document.getStorageManager()); .execute(document.getClient(), document.getStorageManager());

View file

@ -37,6 +37,9 @@ import android.os.Process;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Pair; import android.util.Pair;
import com.nextcloud.client.account.User;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.java.util.Optional;
import com.owncloud.android.MainApp; import com.owncloud.android.MainApp;
import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.OCFile;
@ -74,6 +77,9 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import dagger.android.AndroidInjection; import dagger.android.AndroidInjection;
public class OperationsService extends Service { public class OperationsService extends Service {
@ -133,6 +139,8 @@ public class OperationsService extends Service {
private ConcurrentMap<Integer, Pair<RemoteOperation, RemoteOperationResult>> private ConcurrentMap<Integer, Pair<RemoteOperation, RemoteOperationResult>>
mUndispatchedFinishedOperations = new ConcurrentHashMap<>(); mUndispatchedFinishedOperations = new ConcurrentHashMap<>();
@Inject UserAccountManager accountManager;
private static class Target { private static class Target {
public Uri mServerUrl; public Uri mServerUrl;
public Account mAccount; public Account mAccount;
@ -644,7 +652,7 @@ public class OperationsService extends Service {
case ACTION_SYNC_FILE: case ACTION_SYNC_FILE:
remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
boolean syncFileContents = operationIntent.getBooleanExtra(EXTRA_SYNC_FILE_CONTENTS, true); boolean syncFileContents = operationIntent.getBooleanExtra(EXTRA_SYNC_FILE_CONTENTS, true);
operation = new SynchronizeFileOperation(remotePath, account, syncFileContents, operation = new SynchronizeFileOperation(remotePath, toUser(account), syncFileContents,
getApplicationContext()); getApplicationContext());
break; break;
@ -653,7 +661,7 @@ public class OperationsService extends Service {
operation = new SynchronizeFolderOperation( operation = new SynchronizeFolderOperation(
this, // TODO remove this dependency from construction time this, // TODO remove this dependency from construction time
remotePath, remotePath,
account, toUser(account),
System.currentTimeMillis() // TODO remove this dependency from construction time System.currentTimeMillis() // TODO remove this dependency from construction time
); );
break; break;
@ -698,6 +706,20 @@ public class OperationsService extends Service {
} }
} }
/**
* This is a temporary compatibility helper to convert legacy {@link Account} instance
* to new {@link User} model.
*
* @param account Account instance
* @return User model that corresponds to Account
* @throws RuntimeException if account cannot be converted
*/
@NonNull
private User toUser(Account account) {
Optional<User> optionalUser = accountManager.getUser(account.name);
return optionalUser.orElseThrow(RuntimeException::new); // if account is valid, this should never fail
}
/** /**
* Notifies the currently subscribed listeners about the end of an operation. * Notifies the currently subscribed listeners about the end of an operation.
* *

View file

@ -130,7 +130,7 @@ public class ConflictsResolveActivity extends FileActivity implements OnConflict
if (!shouldDeleteLocal()) { if (!shouldDeleteLocal()) {
// Overwrite local file // Overwrite local file
Intent intent = new Intent(getBaseContext(), FileDownloader.class); Intent intent = new Intent(getBaseContext(), FileDownloader.class);
intent.putExtra(FileDownloader.EXTRA_ACCOUNT, getAccount()); intent.putExtra(FileDownloader.EXTRA_USER, getUser().orElseThrow(RuntimeException::new));
intent.putExtra(FileDownloader.EXTRA_FILE, file); intent.putExtra(FileDownloader.EXTRA_FILE, file);
if (conflictUpload != null) { if (conflictUpload != null) {
intent.putExtra(FileDownloader.EXTRA_CONFLICT_UPLOAD, conflictUpload); intent.putExtra(FileDownloader.EXTRA_CONFLICT_UPLOAD, conflictUpload);

View file

@ -22,10 +22,10 @@
*/ */
package com.owncloud.android.ui.activity; package com.owncloud.android.ui.activity;
import android.accounts.Account;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import com.nextcloud.client.account.User;
import com.nextcloud.client.jobs.BackgroundJobManager; import com.nextcloud.client.jobs.BackgroundJobManager;
import com.owncloud.android.R; import com.owncloud.android.R;
import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.OCFile;
@ -47,6 +47,7 @@ import androidx.fragment.app.FragmentTransaction;
public class ContactsPreferenceActivity extends FileActivity implements FileFragment.ContainerActivity { public class ContactsPreferenceActivity extends FileActivity implements FileFragment.ContainerActivity {
public static final String TAG = ContactsPreferenceActivity.class.getSimpleName(); public static final String TAG = ContactsPreferenceActivity.class.getSimpleName();
public static final String PREFERENCE_CONTACTS_AUTOMATIC_BACKUP = "PREFERENCE_CONTACTS_AUTOMATIC_BACKUP"; public static final String PREFERENCE_CONTACTS_AUTOMATIC_BACKUP = "PREFERENCE_CONTACTS_AUTOMATIC_BACKUP";
public static final String PREFERENCE_CONTACTS_LAST_BACKUP = "PREFERENCE_CONTACTS_LAST_BACKUP"; public static final String PREFERENCE_CONTACTS_LAST_BACKUP = "PREFERENCE_CONTACTS_LAST_BACKUP";
public static final String BACKUP_TO_LIST = "BACKUP_TO_LIST"; public static final String BACKUP_TO_LIST = "BACKUP_TO_LIST";
@ -84,7 +85,7 @@ public class ContactsPreferenceActivity extends FileActivity implements FileFrag
if (savedInstanceState == null) { if (savedInstanceState == null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (intent == null || intent.getParcelableExtra(ContactListFragment.FILE_NAME) == null || if (intent == null || intent.getParcelableExtra(ContactListFragment.FILE_NAME) == null ||
intent.getParcelableExtra(ContactListFragment.ACCOUNT) == null) { intent.getParcelableExtra(ContactListFragment.USER) == null) {
ContactsBackupFragment fragment = new ContactsBackupFragment(); ContactsBackupFragment fragment = new ContactsBackupFragment();
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putBoolean(EXTRA_SHOW_SIDEBAR, showSidebar); bundle.putBoolean(EXTRA_SHOW_SIDEBAR, showSidebar);
@ -92,8 +93,8 @@ public class ContactsPreferenceActivity extends FileActivity implements FileFrag
transaction.add(R.id.frame_container, fragment); transaction.add(R.id.frame_container, fragment);
} else { } else {
OCFile file = Parcels.unwrap(intent.getParcelableExtra(ContactListFragment.FILE_NAME)); OCFile file = Parcels.unwrap(intent.getParcelableExtra(ContactListFragment.FILE_NAME));
Account account = Parcels.unwrap(intent.getParcelableExtra(ContactListFragment.ACCOUNT)); User user = Parcels.unwrap(intent.getParcelableExtra(ContactListFragment.USER));
ContactListFragment contactListFragment = ContactListFragment.newInstance(file, account); ContactListFragment contactListFragment = ContactListFragment.newInstance(file, user);
transaction.add(R.id.frame_container, contactListFragment); transaction.add(R.id.frame_container, contactListFragment);
} }
transaction.commit(); transaction.commit();

View file

@ -2151,11 +2151,11 @@ public class FileDisplayActivity extends FileActivity
private void requestForDownload() { private void requestForDownload() {
Account account = getAccount(); User user = getUser().orElseThrow(RuntimeException::new);
//if (!mWaitingToPreview.isDownloading()) { //if (!mWaitingToPreview.isDownloading()) {
if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) { if (!mDownloaderBinder.isDownloading(user.toPlatformAccount(), mWaitingToPreview)) {
Intent i = new Intent(this, FileDownloader.class); Intent i = new Intent(this, FileDownloader.class);
i.putExtra(FileDownloader.EXTRA_ACCOUNT, account); i.putExtra(FileDownloader.EXTRA_USER, user);
i.putExtra(FileDownloader.EXTRA_FILE, mWaitingToPreview); i.putExtra(FileDownloader.EXTRA_FILE, mWaitingToPreview);
startService(i); startService(i);
} }
@ -2241,10 +2241,10 @@ public class FileDisplayActivity extends FileActivity
} }
private void requestForDownload(OCFile file, String downloadBehaviour, String packageName, String activityName) { private void requestForDownload(OCFile file, String downloadBehaviour, String packageName, String activityName) {
Account account = getAccount(); final User currentUser = getUser().orElseThrow(RuntimeException::new);
if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) { if (!mDownloaderBinder.isDownloading(currentUser.toPlatformAccount(), mWaitingToPreview)) {
Intent i = new Intent(this, FileDownloader.class); Intent i = new Intent(this, FileDownloader.class);
i.putExtra(FileDownloader.EXTRA_ACCOUNT, account); i.putExtra(FileDownloader.EXTRA_USER, currentUser);
i.putExtra(FileDownloader.EXTRA_FILE, file); i.putExtra(FileDownloader.EXTRA_FILE, file);
i.putExtra(SendShareDialog.PACKAGE_NAME, packageName); i.putExtra(SendShareDialog.PACKAGE_NAME, packageName);
i.putExtra(SendShareDialog.ACTIVITY_NAME, activityName); i.putExtra(SendShareDialog.ACTIVITY_NAME, activityName);
@ -2405,9 +2405,10 @@ public class FileDisplayActivity extends FileActivity
} }
public void startContactListFragment(OCFile file) { public void startContactListFragment(OCFile file) {
final User user = getUser().orElseThrow(RuntimeException::new);
Intent intent = new Intent(this, ContactsPreferenceActivity.class); Intent intent = new Intent(this, ContactsPreferenceActivity.class);
intent.putExtra(ContactListFragment.FILE_NAME, Parcels.wrap(file)); intent.putExtra(ContactListFragment.FILE_NAME, Parcels.wrap(file));
intent.putExtra(ContactListFragment.ACCOUNT, Parcels.wrap(getAccount())); intent.putExtra(ContactListFragment.USER, user);
startActivity(intent); startActivity(intent);
} }

View file

@ -22,7 +22,6 @@
package com.owncloud.android.ui.fragment.contactsbackup; package com.owncloud.android.ui.fragment.contactsbackup;
import android.Manifest; import android.Manifest;
import android.accounts.Account;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
@ -56,6 +55,7 @@ import android.widget.Toast;
import com.bumptech.glide.request.animation.GlideAnimation; import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget; import com.bumptech.glide.request.target.SimpleTarget;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import com.nextcloud.client.account.User;
import com.nextcloud.client.account.UserAccountManager; import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.di.Injectable; import com.nextcloud.client.di.Injectable;
import com.nextcloud.client.jobs.BackgroundJobManager; import com.nextcloud.client.jobs.BackgroundJobManager;
@ -111,7 +111,7 @@ public class ContactListFragment extends FileFragment implements Injectable {
public static final String TAG = ContactListFragment.class.getSimpleName(); public static final String TAG = ContactListFragment.class.getSimpleName();
public static final String FILE_NAME = "FILE_NAME"; public static final String FILE_NAME = "FILE_NAME";
public static final String ACCOUNT = "ACCOUNT"; public static final String USER = "USER";
public static final String CHECKED_ITEMS_ARRAY_KEY = "CHECKED_ITEMS"; public static final String CHECKED_ITEMS_ARRAY_KEY = "CHECKED_ITEMS";
private static final int SINGLE_ACCOUNT = 1; private static final int SINGLE_ACCOUNT = 1;
@ -142,20 +142,19 @@ public class ContactListFragment extends FileFragment implements Injectable {
private ContactListAdapter contactListAdapter; private ContactListAdapter contactListAdapter;
private Account account; private User user;
private List<VCard> vCards = new ArrayList<>(); private List<VCard> vCards = new ArrayList<>();
private OCFile ocFile; private OCFile ocFile;
@Inject UserAccountManager accountManager; @Inject UserAccountManager accountManager;
@Inject ClientFactory clientFactory; @Inject ClientFactory clientFactory;
@Inject BackgroundJobManager backgroundJobManager; @Inject BackgroundJobManager backgroundJobManager;
public static ContactListFragment newInstance(OCFile file, Account account) { public static ContactListFragment newInstance(OCFile file, User user) {
ContactListFragment frag = new ContactListFragment(); ContactListFragment frag = new ContactListFragment();
Bundle arguments = new Bundle(); Bundle arguments = new Bundle();
arguments.putParcelable(FILE_NAME, file); arguments.putParcelable(FILE_NAME, file);
arguments.putParcelable(ACCOUNT, account); arguments.putParcelable(USER, user);
frag.setArguments(arguments); frag.setArguments(arguments);
return frag; return frag;
} }
@ -209,11 +208,11 @@ public class ContactListFragment extends FileFragment implements Injectable {
ocFile = getArguments().getParcelable(FILE_NAME); ocFile = getArguments().getParcelable(FILE_NAME);
setFile(ocFile); setFile(ocFile);
account = getArguments().getParcelable(ACCOUNT); user = getArguments().getParcelable(USER);
if (!ocFile.isDown()) { if (!ocFile.isDown()) {
Intent i = new Intent(getContext(), FileDownloader.class); Intent i = new Intent(getContext(), FileDownloader.class);
i.putExtra(FileDownloader.EXTRA_ACCOUNT, account); i.putExtra(FileDownloader.EXTRA_FILE_PATH, user);
i.putExtra(FileDownloader.EXTRA_FILE, ocFile); i.putExtra(FileDownloader.EXTRA_FILE, ocFile);
getContext().startService(i); getContext().startService(i);
@ -505,8 +504,8 @@ public class ContactListFragment extends FileFragment implements Injectable {
if (FileDownloader.getDownloadFinishMessage().equalsIgnoreCase(intent.getAction())) { if (FileDownloader.getDownloadFinishMessage().equalsIgnoreCase(intent.getAction())) {
String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH); String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
FileDataStorageManager storageManager = new FileDataStorageManager(account, FileDataStorageManager storageManager = new FileDataStorageManager(user.toPlatformAccount(),
context.getContentResolver()); context.getContentResolver());
ocFile = storageManager.getFileByPath(downloadedRemotePath); ocFile = storageManager.getFileByPath(downloadedRemotePath);
loadContactsTask.execute(); loadContactsTask.execute();
} }

View file

@ -522,8 +522,8 @@ public class ContactsBackupFragment extends FileFragment implements DatePickerDi
} }
if (backupToRestore != null) { if (backupToRestore != null) {
Fragment contactListFragment = ContactListFragment.newInstance(backupToRestore, final User user = contactsPreferenceActivity.getUser().orElseThrow(RuntimeException::new);
contactsPreferenceActivity.getAccount()); Fragment contactListFragment = ContactListFragment.newInstance(backupToRestore, user);
contactsPreferenceActivity.getSupportFragmentManager(). contactsPreferenceActivity.getSupportFragmentManager().
beginTransaction() beginTransaction()

View file

@ -198,13 +198,13 @@ public class FileOperationsHelper {
public void startSyncForFileAndIntent(OCFile file, Intent intent) { public void startSyncForFileAndIntent(OCFile file, Intent intent) {
new Thread(() -> { new Thread(() -> {
Account account = fileActivity.getAccount(); User user = fileActivity.getUser().orElseThrow(RuntimeException::new);
FileDataStorageManager storageManager = new FileDataStorageManager(fileActivity.getAccount(), FileDataStorageManager storageManager = new FileDataStorageManager(fileActivity.getAccount(),
fileActivity.getContentResolver()); fileActivity.getContentResolver());
// check if file is in conflict (this is known due to latest folder refresh) // check if file is in conflict (this is known due to latest folder refresh)
if (file.isInConflict()) { if (file.isInConflict()) {
syncFile(file, account, storageManager); syncFile(file, user, storageManager);
EventBus.getDefault().post(new SyncEventFinished(intent)); EventBus.getDefault().post(new SyncEventFinished(intent));
return; return;
@ -230,22 +230,22 @@ public class FileOperationsHelper {
// check for changed eTag // check for changed eTag
CheckEtagRemoteOperation checkEtagOperation = new CheckEtagRemoteOperation(file.getRemotePath(), CheckEtagRemoteOperation checkEtagOperation = new CheckEtagRemoteOperation(file.getRemotePath(),
file.getEtag()); file.getEtag());
RemoteOperationResult result = checkEtagOperation.execute(account, fileActivity); RemoteOperationResult result = checkEtagOperation.execute(user.toPlatformAccount(), fileActivity);
// eTag changed, sync file // eTag changed, sync file
if (result.getCode() == RemoteOperationResult.ResultCode.ETAG_CHANGED) { if (result.getCode() == RemoteOperationResult.ResultCode.ETAG_CHANGED) {
syncFile(file, account, storageManager); syncFile(file, user, storageManager);
} }
EventBus.getDefault().post(new SyncEventFinished(intent)); EventBus.getDefault().post(new SyncEventFinished(intent));
}).start(); }).start();
} }
private void syncFile(OCFile file, Account account, FileDataStorageManager storageManager) { private void syncFile(OCFile file, User user, FileDataStorageManager storageManager) {
fileActivity.runOnUiThread(() -> fileActivity.showLoadingDialog(fileActivity.getResources() fileActivity.runOnUiThread(() -> fileActivity.showLoadingDialog(fileActivity.getResources()
.getString(R.string.sync_in_progress))); .getString(R.string.sync_in_progress)));
SynchronizeFileOperation sfo = new SynchronizeFileOperation(file, null, account, true, fileActivity); SynchronizeFileOperation sfo = new SynchronizeFileOperation(file, null, user, true, fileActivity);
RemoteOperationResult result = sfo.execute(storageManager, fileActivity); RemoteOperationResult result = sfo.execute(storageManager, fileActivity);
if (result.getCode() == RemoteOperationResult.ResultCode.SYNC_CONFLICT) { if (result.getCode() == RemoteOperationResult.ResultCode.SYNC_CONFLICT) {
@ -254,7 +254,7 @@ public class FileOperationsHelper {
Intent i = new Intent(fileActivity, ConflictsResolveActivity.class); Intent i = new Intent(fileActivity, ConflictsResolveActivity.class);
i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra(ConflictsResolveActivity.EXTRA_FILE, file); i.putExtra(ConflictsResolveActivity.EXTRA_FILE, file);
i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, account); i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, user);
fileActivity.startActivity(i); fileActivity.startActivity(i);
} else { } else {
if (file.isDown()) { if (file.isDown()) {
@ -313,7 +313,7 @@ public class FileOperationsHelper {
// since it was registered to observe again, assuming that local files // since it was registered to observe again, assuming that local files
// are linked to a remote file AT MOST, SOMETHING TO BE DONE; // are linked to a remote file AT MOST, SOMETHING TO BE DONE;
SynchronizeFileOperation sfo = SynchronizeFileOperation sfo =
new SynchronizeFileOperation(file, null, user.toPlatformAccount(), true, fileActivity); new SynchronizeFileOperation(file, null, user, true, fileActivity);
RemoteOperationResult result = sfo.execute(storageManager, fileActivity); RemoteOperationResult result = sfo.execute(storageManager, fileActivity);
fileActivity.dismissLoadingDialog(); fileActivity.dismissLoadingDialog();
if (result.getCode() == RemoteOperationResult.ResultCode.SYNC_CONFLICT) { if (result.getCode() == RemoteOperationResult.ResultCode.SYNC_CONFLICT) {

View file

@ -36,6 +36,7 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import com.nextcloud.client.account.User;
import com.nextcloud.client.di.Injectable; import com.nextcloud.client.di.Injectable;
import com.nextcloud.client.preferences.AppPreferences; import com.nextcloud.client.preferences.AppPreferences;
import com.owncloud.android.MainApp; import com.owncloud.android.MainApp;
@ -393,8 +394,9 @@ public class PreviewImageActivity extends FileActivity implements
Log_OC.d(TAG, "requestForDownload called without binder to download service"); Log_OC.d(TAG, "requestForDownload called without binder to download service");
} else if (!mDownloaderBinder.isDownloading(getAccount(), file)) { } else if (!mDownloaderBinder.isDownloading(getAccount(), file)) {
final User user = getUser().orElseThrow(RuntimeException::new);
Intent i = new Intent(this, FileDownloader.class); Intent i = new Intent(this, FileDownloader.class);
i.putExtra(FileDownloader.EXTRA_ACCOUNT, getAccount()); i.putExtra(FileDownloader.EXTRA_USER, user);
i.putExtra(FileDownloader.EXTRA_FILE, file); i.putExtra(FileDownloader.EXTRA_FILE, file);
startService(i); startService(i);
} }